Generate texture for a heightmap
- by James
I've recently been trying to blend multiple textures based on the height at different points in a heightmap. However i've been getting poor results. I decided to backtrack and just attempt to recreate one single texture from an SDL_Surface (i'm using SDL) and just send that into opengl. I'll put my code for creating the texture and reading the colour values. It is a 24bit TGA i'm loading, and i've confirmed that the rest of my code works because i was able to send the surfaces pixels directly to my createTextureFromData function and it drew fine.
struct RGBColour
{
RGBColour() : r(0), g(0), b(0) {}
RGBColour(unsigned char red, unsigned char green, unsigned char blue) : r(red), g(green), b(blue) {}
unsigned char r;
unsigned char g;
unsigned char b;
};
// main loading code
SDLSurfaceReader* reader = new SDLSurfaceReader(m_renderer);
reader->readSurface("images/grass.tga");
// new texture
unsigned char* newTexture = new unsigned char[reader->m_surface->w * reader->m_surface->h * 3 * reader->m_surface->w];
for (int y = 0; y < reader->m_surface->h; y++)
{
for (int x = 0; x < reader->m_surface->w; x += 3)
{
int index = (y * reader->m_surface->w) + x;
RGBColour colour = reader->getColourAt(x, y);
newTexture[index] = colour.r;
newTexture[index + 1] = colour.g;
newTexture[index + 2] = colour.b;
}
}
unsigned int id = m_renderer->createTextureFromData(newTexture, reader->m_surface->w, reader->m_surface->h, RGB);
// functions for reading pixels
RGBColour SDLSurfaceReader::getColourAt(int x, int y)
{
Uint32 pixel;
Uint8 red, green, blue;
RGBColour rgb;
pixel = getPixel(m_surface, x, y);
SDL_LockSurface(m_surface);
SDL_GetRGB(pixel, m_surface->format, &red, &green, &blue);
SDL_UnlockSurface(m_surface);
rgb.r = red;
rgb.b = blue;
rgb.g = green;
return rgb;
}
// this function taken from SDL documentation
// http://www.libsdl.org/cgi/docwiki.cgi/Introduction_to_SDL_Video#getpixel
Uint32 SDLSurfaceReader::getPixel(SDL_Surface* surface, int x, int y)
{
int bpp = m_surface->format->BytesPerPixel;
Uint8 *p = (Uint8*)m_surface->pixels + y * m_surface->pitch + x * bpp;
switch (bpp)
{
case 1:
return *p;
case 2:
return *(Uint16*)p;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32*)p;
default:
return 0;
}
}
I've been stumped at this, and I need help badly! Thanks so much for any advice.