PNG + OpenGL problem

Hi all,

I?m trying to modify the nehe lesson 6 (SDL + OpenGL), but loading a PNG
image with SDL_image instead of use SDL. I can?t see correctly the picture
as texture.

The change I did is to do not use the LoadBMP functionimplemented in the
example. In their place, I’ve used the IMG_load of the SDL_image:

// Load Texture
SDL_Surface *image1;
SDL_RWops *rwop;
rwop = SDL_RWFromFile("…/…/Data06/NeHe.png",“rb”);
//image1 = LoadBMP("…/…/Data06/NeHe.bmp");
if(IMG_isPNG(rwop)){
image1 = IMG_LoadPNG_RW(rwop);
}
if (!image1) {
SDL_Quit();
exit(1);
}

And to invert the texture matrix because the BMP is inverted otherwise:
///////////// Texture Inversion ///////////////
glMatrixMode(GL_TEXTURE);
glScalef(1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);

Without the matrix inversion the the BMP texture is displayed inverted but
with this inversion runs fine. In the PNG case do not run correctly. Any
solution to help a newbie? :slight_smile:

Maybe exists a restriction to the PNG supported (as resolution, size or
something like that)?

Thanks in advance.

Ferran–
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.1.394 / Virus Database: 268.10.1/391 - Release Date: 18/07/2006

I?m trying to modify the nehe lesson 6 (SDL + OpenGL), but loading a PNG
image with SDL_image instead of use SDL. I can?t see correctly the
picture as texture.

There’s a couple parts missing in your exercise, just to make sure
you’re on the right track I’ll mention those parts here:

  1. Load the image from disk to ram and be able to access the picture
    elements (getpixel(x,y), etc…)
  2. Prepare the image data for OpenGL, sometimes the data must be
    re-aligned to fit the requirements of OpenGL. OpenGL likes to have a
    one-dimensionnal array of colors one after the other like this:

unsigned char thePixels[256 * 256 * 4]; // This creates an array for an
image of size 256x256 with 4 color components (RGBA).

Then you put the information for opengl:
thePixels[ x4 + y2564 + 0 ] = r; //red component of pixel at position
(x,y)
thePixels[ x
4 + y2564 + 1 ] = g;
thePixels[ x4 + y2564 + 2 ] = b;
thePixels[ x
4 + y2564 + 3 ] = a;

  1. Once the data is ready you now need to upload it to opengl so that
    the texture is inside the video RAM. Uploading the image to opengl will
    also tell OpenGL how to display the image under certain circumstances
    (is it far away, really close). Functions to use: gluBuild2DMipmaps

  2. Once the image is uploaded, you now need to enable textures, bind
    to the texture of your choice and render a quad with glTexCoord2f and
    also make sure you draw with color of (1,1,1) or the texture colors will
    be multiplied by the glColor3f().

Finally, I did not find an error in the small bits of code you sent.
However, I don’t suggest telling OpenGL to modify your image to make it
correct, I would give a corrected image to opengl.

And at last, when you have trouble with textures, it can be one of the
following most of the time: black texture (are they enabled, bound
correctly, uploaded at any time?), random color texture (trouble with
the uploading, format doesn’t match, make sure your data is not RGBA
when trying to upload for RGB). Sometimes the whole polygon is just one
color, it might be because you didn’t not use the glTexCoord*() funcs
correctly.

HTH,
Simon

Hi Simon. I made it!!!
After a lot of investigation I’ve successfully load the png. This is the
algoritm:

bool CTextureLoader::load(const char* fileName)
{
GLuint texture;
GLuint *theImage;
// Load Texture
SDL_Surface *image1;
SDL_RWops *rwop;
//--------------------------------------------------------------
// Aqui comprobar si la textura ya ha sido cargada
//-------------------------------------------------------------

// intentar cargar la imagen
if (!(image1 = IMG_Load(fileName)))
{
	SDL_Quit();
	exit(1);
}
// no estan soportadas las imagenes paletizadas
if (image1->format->palette)
{
	SDL_Quit();
	exit(1);
}
m_text_name = strdup(fileName);
theImage = (GLuint*)image1->pixels;
m_width = image1->w;
m_height = image1->h;
m_bitsPerPixel = image1->format->BitsPerPixel;

if (image1->format->BitsPerPixel == 24)
{

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
if (image1->format->Rshift < image1->format->Bshift) m_type
= GL_RGB;
else m_type = GL_BGR_EXT;
#else
if (image1->format->Rshift < image1->format->Bshift) m_type
= GL_BGR;
else m_type->format = GL_RGB;
#endif
}

// 32 bits texture format finder
else if (image1->format->BitsPerPixel == 32) {

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
if (image1->format->Rshift < image1->format->Bshift) m_type
= GL_RGBA;
else m_type = GL_BGRA_EXT;
#else
if (image1->format->Rshift < image1->format->Bshift) m_type
= GL_BGRA;
else m_type = GL_RGBA;
#endif
}
// unsupported texture format
else {

	SDL_Quit();
	exit(1);
}

// Create Texture	
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);   // 2d texture (x and y

size)
m_texIndex = texture;

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //

scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //
scale linearly when image smalled than texture

// 2d texture, level of detail 0 (normal), 3 components (red, green,

blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and
finally the data itself.
glTexImage2D(GL_TEXTURE_2D, 0, 3, m_width, m_height, 0, m_type,
GL_UNSIGNED_BYTE, theImage);

// liberamos la memoria
SDL_FreeSurface(image1);
theImage = NULL;

}

//==========================================================================
Quick and dirty, I know, but it’s only a preview.

Thanks for all :slight_smile:

Ferran
|-----Mensaje original-----
|De: sdl-bounces+ferranferri=yahoo.es at libsdl.org [mailto:sdl-
|bounces+ferranferri=yahoo.es at libsdl.org] En nombre de Simon
|Enviado el: lunes, 24 de julio de 2006 1:46
|Para: A list for developers using the SDL library. (includes SDL-announce)
|Asunto: Re: [SDL] PNG + OpenGL problem
|
|> I?m trying to modify the nehe lesson 6 (SDL + OpenGL), but loading a PNG
|> image with SDL_image instead of use SDL. I can?t see correctly the
|> picture as texture.
|
|There’s a couple parts missing in your exercise, just to make sure
|you’re on the right track I’ll mention those parts here:
|
| 1) Load the image from disk to ram and be able to access the picture
|elements (getpixel(x,y), etc…)
| 2) Prepare the image data for OpenGL, sometimes the data must be
|re-aligned to fit the requirements of OpenGL. OpenGL likes to have a
|one-dimensionnal array of colors one after the other like this:
|
|unsigned char thePixels[256 * 256 * 4]; // This creates an array for an
|image of size 256x256 with 4 color components (RGBA).
|
|Then you put the information for opengl:
|thePixels[ x4 + y2564 + 0 ] = r; //red component of pixel at position
|(x,y)
|thePixels[ x
4 + y2564 + 1 ] = g;
|thePixels[ x4 + y2564 + 2 ] = b;
|thePixels[ x
4 + y2564 + 3 ] = a;
|
| 3) Once the data is ready you now need to upload it to opengl so that
|the texture is inside the video RAM. Uploading the image to opengl will
|also tell OpenGL how to display the image under certain circumstances
|(is it far away, really close). Functions to use: gluBuild2DMipmaps
|
| 4) Once the image is uploaded, you now need to enable textures, bind
|to the texture of your choice and render a quad with glTexCoord2f and
|also make sure you draw with color of (1,1,1) or the texture colors will
|be multiplied by the glColor3f().
|
|Finally, I did not find an error in the small bits of code you sent.
|However, I don’t suggest telling OpenGL to modify your image to make it
|correct, I would give a corrected image to opengl.
|
|And at last, when you have trouble with textures, it can be one of the
|following most of the time: black texture (are they enabled, bound
|correctly, uploaded at any time?), random color texture (trouble with
|the uploading, format doesn’t match, make sure your data is not RGBA
|when trying to upload for RGB). Sometimes the whole polygon is just one
|color, it might be because you didn’t not use the glTexCoord*() funcs
|correctly.
|
|HTH,
| Simon
|
|
|_______________________________________________
|SDL mailing list
|SDL at libsdl.org
|http://www.libsdl.org/mailman/listinfo/sdl

No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.1.394 / Virus Database: 268.10.3/395 - Release Date: 21/07/2006

No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.1.394 / Virus Database: 268.10.4/396 - Release Date: 24/07/2006


LLama Gratis a cualquier PC del Mundo.
Llamadas a fijos y m?viles desde 1 c?ntimo por minuto.
http://es.voice.yahoo.com

Great work, here’s an addition to your code, or a suggestion if you want…

   // liberamos la memoria
   SDL_FreeSurface(image1);
   theImage = NULL;

Here you delete the data that was read on disk. This is super-fine in
most cases, but since you’re dealing with open, and you might also
want to have your application toggle from fullscreen to windowed, or
have it resizable. Well for compatibility reasons, you’ll have to
reupload your texture anytime the window properties change (specially
on windows, linux seems fine). According to the docs, you should take
care of freeing past textures from video ram, then resize window, then
upload textures again, then render.

So the suggestion is to not clean the SDL_Surface you have, it is
already loaded, and ready to be re-uploaded. The difficulty is to
keep track of your Mag filters associated with the image (in a project
of mine, I have to mix GL_LINEAR with GL_NEAREST for different images
that have different purposes).

Great stuff ahead!
Simon