1
votes

I have created a sample application using glew and glut which reads a dds file and displays it. I manually read the dds file (NPOT(886 x 317) file in R8G8B8) and creates the data pointer(unsigned char*).

Then I prepared the texture using

void prepareTexture(int w, int h, unsigned char* data) {

    /* Create and load texture to OpenGL */
    glGenTextures(1, &textureID); /* Texture name generation */
    glBindTexture(GL_TEXTURE_2D, textureID); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 
                w, h, 
                0, GL_RGB, GL_UNSIGNED_BYTE,
                data); 
    glGenerateMipmap(GL_TEXTURE_2D);
}

enter image description here

In the above figure, First one shows the original dds file and second one is the rendering result of my application which is obviously wrong. If I re-size the image to 1024 x 512, both images will look same.

From the OpenGL Specification

I.3 Non-Power-Of-Two Textures

The restriction of textures to power-of-two dimensions has been relaxed for all texture targets, so that non-power-of-two textures may be specified without generating errors. Non-power-of-two textures was promoted from the ARB texture non power of two extension.

From which what I understand is from OpenGl 2.0 we can use NPOT textures and OpenGL will handle this.

I tried using the DevIL image library to load the dds file but end up with same result. If I convert the image to a RGBA and and change the internal format and format of glTexImage2D to GL_RGBA I will get correct result even if the dds file is NPOT.

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 
                w, h, 
                0, GL_RGBA, GL_UNSIGNED_BYTE,
                data);

I tried the application in PC's with NVIDA card and Radeon card and both of them are giving the same result.

My sample source code can be downloaded from the link

Can anybody tell me what is wrong with my application? Or OpenGL does not allow NPOT if the image is in R8G8B8.

1

1 Answers

8
votes

This looks like an alignment issue. Add this before the glTexImage2D() call:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

This value specifies the row alignment of your data in bytes. The default value is 4.

With your texture width of 886 and 3 bytes per pixel for GL_RGB, each row is 886 * 3 = 2658 bytes, which is not a multiple of 4.

With the UNPACK_ALIGNMENT value at the default, the size would be rounded up to the next multiple of 4, which is 2660. So 2660 bytes will be read for each row, which explains the increasing shift for each row. The first row would be correct, the second one 2 bytes off, the 2nd row 4 bytes off, the 3rd row 6 bytes off, etc.