Thread: Texture won't load (libpng with OpenGL)

  1. #1
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555

    Texture won't load (libpng with OpenGL)

    I was following this tutorial: http://nehe.gamedev.net/data/lessons....asp?lesson=06
    But as I don't have the GLaux library and didn't feel like I wanted it I went ahead studied how to use libpng with OpenGL following this tutorial: http://www.macdevcenter.com/pub/a/ma...ps.html?page=1
    The resulting code was copied and slightly modified code from the site,
    Code:
    unsigned char* glxReadPNG (TCHAR* file, png_uint_32* w, png_uint_32* h)
    {
    	FILE* f;
    	unsigned char sig[8];
    	png_structp png_ptr;
    	png_infop   info_ptr;
    	unsigned char* image_data;
    	int bit_depth;
    	int color_type;
    	unsigned int rowbytes;
    	png_uint_32 i;
    	png_bytepp row_pointers;
    
    	if ((f = fopen(file, "rb")) == NULL)
    		return NULL;
    	fread(sig, sizeof(*sig), sizeof(sig), f);
    	if (!png_check_sig(sig, sizeof(*sig))) {
    		fclose(f);
    		return NULL;
    	}
    	if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
    		fclose(f);
    		return NULL;
    	}
    	if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
    		png_destroy_read_struct(&png_ptr, NULL, NULL);
    		fclose(f);
    		return NULL;
    	}
    
    	if (setjmp(png_jmpbuf(png_ptr))) {
    		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    		fclose(f);
    		return NULL;
    	}
    	png_ptr->io_ptr = (png_voidp) f;
    	png_set_sig_bytes(png_ptr, 8);
    
    	png_read_info(png_ptr, info_ptr);
    	png_get_IHDR(png_ptr, info_ptr, w, h, &bit_depth, &color_type, NULL, NULL, NULL);
    	if (color_type & PNG_COLOR_MASK_ALPHA)
    		png_set_strip_alpha(png_ptr);
    	if (bit_depth > 8)
    		png_set_strip_16(png_ptr);
    	if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    		png_set_gray_to_rgb(png_ptr);
    	if (color_type == PNG_COLOR_TYPE_PALETTE)
    		png_set_palette_to_rgb(png_ptr);
    	png_read_update_info(png_ptr, info_ptr);
    
    	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    	if ((image_data = malloc(*h * rowbytes)) == NULL) {
    		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    		fclose(f);
    		return NULL;
    	}
    	if ((row_pointers = malloc(*h * sizeof(png_bytep))) == NULL) {
    		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    		fclose(f);
    		free(image_data);
    		return NULL;
    	}
    
    	for (i = 0; i < *h; i++)
    		row_pointers[*h - 1 - i] = image_data + i*rowbytes;
    	png_read_image(png_ptr, row_pointers);
    	free(row_pointers);
    	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    	fclose(f);
    
    	return image_data;
    }
    Also following the same site, I loaded this texture using the lines found on page 3 and probably a mix from the NeHe tutorial.
    Global variables and static variables for wndproc (window procedure for the OpenGL window):
    Code:
    //global
    int w;
    int h;
    GLfloat xrot = 0.0f;
    GLfloat yrot = 0.0f;
    GLuint imgname;
    
    //static variables for wndproc
    static HDC   hdc;
    static HGLRC hrc;
    static HFONT font;
    static RECT  re = {0, 0, 0, 0};
    static unsigned char* image;
    static int imgw, imgh;
    WM_CREATE for wndproc:
    Code:
    		case WM_CREATE:
    		{
    			PIXELFORMATDESCRIPTOR pfd = {
    				sizeof(pfd),
    				1,
    				PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    				PFD_TYPE_RGBA,
    				32,
    				0, 0, 0, 0, 0, 0,
    				0,
    				0,
    				0,
    				0, 0, 0, 0,
    				32,
    				0,
    				0,
    				PFD_MAIN_PLANE,
    				0,
    				0, 0, 0
    			};
    			if ((hdc = GetDC(hwnd)) == NULL ||
    			    !SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd) ||
    			    (hrc = wglCreateContext(hdc)) == NULL ||
    			    !wglMakeCurrent(hdc, hrc))
    			{
    				Error();
    				PostQuitMessage(1);
    				break;
    			}
    			font = CreateFont(-MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "MS Shell Dlg");
    			if (font == NULL) {
    				Error();
    				PostQuitMessage(1);
    				break;
    			}
    			SetTextColor(hdc, RGB(0, 0xFF, 0));
    			SetBkMode(hdc, TRANSPARENT);
    			if ((image = glxReadPNG(TEXT("ogl.png"), &imgw, &imgh)) == NULL) {
    				Error();
    				PostQuitMessage(1);
    				break;
    			}
    			glGenTextures(1, &imgname);
    			glBindTexture(GL_TEXTURE_2D, imgname);
    			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    			free(image);
    			glEnable(GL_TEXTURE_2D);
    			glShadeModel(GL_SMOOTH);
    			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    			glClearDepth(1.0f);
    			glEnable(GL_DEPTH_TEST);
    			glDepthFunc(GL_LEQUAL);
    			glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    			break;
    		}
    The rendering function is pretty much identical with the one from the OpenGL tutorial, the exception being that I still have the triangle from earlier lessons still drawn but I think that shouldn't matter, also, this message is probably already too long to drop more code.

    I don't know where it fails, when the screen was first drawn I saw nothing. Then I thought it was probably because the color was set to black so I changed it to white and that gave me a white cube, with no textures on it.

    I don't think the PNG-loading function is failing as I wrote a test program in SDL to test it out. It returns the right width, height and pixel data as my test program had no problem drawing the picture it loaded (except upside down and horizontally flipped, which it should do according to the libpng guide).

    Compiled using MinGW and libpng 1.2.8. Attaching ogl.c (main program), ogl.png (texture) and test.c (SDL program to test libpng).
    I'm suffering from a cold at the moment and can't think clearly so I'm sorry if this thread isn't as helpful as it could. I'm gonna go grab some painkillers after posting this.

  2. #2
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    I guess I'm on my own in this matter.
    What functionalities of errorchecking does OpenGL provide? All the functions return void so that's not very helpful. I googled around and found out about the functions glGetError() as well as gluErrorString() and then I made this function:
    Code:
    GLvoid glxError (GLvoid)
    {
    	GLenum error;
    	while ((error = glGetError()) != GL_NO_ERROR)
    		MessageBox(NULL, gluErrorString(error), NULL, MB_OK | MB_ICONSTOP);
    }
    And called it after the glTexImage2D() call and some other random places like in the rendering function and there was no sign of a message box so obviously there were no errors, yet I get no textures.
    Since there really should be errors I got suspicious and called the function inbetween a glBegin() and glEnd() which is supposed to give an error, but it didn't. So the function that handles errors is getting errors. That's just great. Could the fault lie in the libraries perhaps?

    And why am I writing as if I was doing a novel?

  3. #3
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    I doubt the texture is failing to load, you're either not handing it to OGL correctly, or drawing correctly. I'm going to say you're not handing it to OGL correctly, because you're passing GL_RGB to what I remember to be the number of color channels. GL_RGB is definitely not 3.

    I applaud your inner monolague.

  4. #4
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    Changing GL_RGB to 3 didn't change the results.
    I tried the glaux approach, converting the texture to a bitmap and not to my surprise that worked just fine. The triangle seems to have been affected as well but I couldn't care less about that. Maybe there's something wrong with my PNG-reading function beside the sizeof(*sig) which should be sizeof(sig) in png_check_sig after all.
    Since the data sent into the glTextureImage2D is in a specific format I should be able to compare the data of the PNG and BMP images to see how they differ, right? Stay tuned for results!

    EDIT: Okay this is just downright creepy. I can dump the data of the BMP picture to a file but when I do the same to the PNG picture I get a file with 0 size, and no errors found in errno or GetLastError().

    EDIT2: So I finally got a hold of the data for the PNG image by putting the output routine inside the function that loads it. The data for the BMP image and the PNG image are exactly the same. The data was dumped using
    fwrite(image, 1, 3*width*height, file)
    (pseudocode) and since the image is 80x80 a 19 200 byte file was generated for both.
    Could my source be haunted? Maybe there's an invisible force causing the data to act strange like in the first edit. Yes, that must be it.

    EDIT3: Haha oh wow, I finally found the error. I'm passing w and h to glTextureImage2D() whereas imgw and imgh were the variables that contained the size. w and h contain the dimensions of the window.
    All this work debugging something so simple.

    Still, shouldn't I be getting a segfault or an error from OpenGL? The starting width and height of the application is 629 and 449 respectively, which is way larger than the array's dimensions.
    Last edited by OnionKnight; 10-05-2006 at 01:13 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Texture Binding with OpenGL
    By scwizzo in forum Game Programming
    Replies: 5
    Last Post: 07-01-2008, 11:02 AM
  2. Linking OpenGL in Dev-C++
    By linkofazeroth in forum Game Programming
    Replies: 4
    Last Post: 09-13-2005, 10:17 AM
  3. Pong is completed!!!
    By Shamino in forum Game Programming
    Replies: 11
    Last Post: 05-26-2005, 10:50 AM
  4. OpenGL Window
    By Morgul in forum Game Programming
    Replies: 1
    Last Post: 05-15-2005, 12:34 PM
  5. OpenGL and Windows
    By sean345 in forum Game Programming
    Replies: 5
    Last Post: 06-24-2002, 10:14 PM