Search code examples
javaopengltextures

opengl : glGetTexImage for 2d textures and 1d texture array confusion


For texture2D i extract the texture for an mipmap as follows

pixels=ByteBuffer.allocateDirect(4*width*height);
    
GL11.glGetTexImage(
                    GL11.GL_TEXTURE_2D,mipMap
                   ,GL11.GL_RGB,GL11.GL_UNSIGNED_BYTE
                   ,pixels
                  );

As per the documentation it writes 4 bytes per pixels setting the required components to zero if the texture is not 4 components.

Later i can create an 2D texture using the pixels as follows

GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT,4); //4 bytes since RGBA bytes were read from texture

GL11.glTexImage2D(GL11.GL_TEXTURE_2D,0
                 ,GL11.GL_RGB,width,height,0
                 ,GL11.GL_RGB,GL11.GL_UNSIGNED_BYTE,pixels);

So this works perfectly for 2D textures.

Now jump to texture 1D Arrays i read the images for all layers of an specific mipmap as follows

pixels=ByteBuffer.allocateDirect(4*image.width*layers); //again creating RGBA byte buffer because thats the default behaviour

GL11.glGetTexImage(                                     //this will return the texture images of all layers of mipmap level 0
                   GL30.GL_TEXTURE_1D_ARRAY,0
                  ,GL11.GL_RGB,GL11.GL_UNSIGNED_BYTE
                  ,pixels
                 );

ByteBuffer levelN=ByteBuffer.allocateDirect(4*image.width);

int offset=4*image.width*level;                         //level is layer 0,layer 1 so on this part reads only the texels of an specific layer
for(int i=offset;i<offset+(image.width*4);i++){levelN.put(pixels.get(i));}

pixels=levelN;

But later when i create my texture1D array as follows

ByteBuffer[] layers=//read using above method

 GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT,4); //4 bytes since RGBA bytes were read from texture

GL11.glTexImage2D(GL30.GL_TEXTURE_1D_ARRAY,0                                //allocate enough storage for all layers
                 ,GL11.GL_RGB,width,layers.length,0
                 ,GL11.GL_RGB,GL11.GL_UNSIGNED_BYTE,(ByteBuffer)null);



for(int layer=0;i<layers.length;layer++)
{
 ByteBuffer image=layers[i];
 
 GL11.glTexSubImage2D(GL30.GL_TEXTURE_1D_ARRAY,0                              //Update individual layers using texSubImage
                      ,0,layer,width,1
                      ,GL11.GL_RGB,GL11.GL_UNSIGNED_BYTE,image);
}

The Colors come out all incorrect and even changing the texture format to GL_RGBA also didn't solve the problem.but when i change the constant from 4 to 3[read only 3 bytes per pixel in the readMethod() of texture 1d array] everything works correctly again. So i am really confused here because all my test textures are RGB format and what i observed was

->For 2D Textures reading 4 bytes per pixel in glGetTexImage() but then later specifying only RGB for the texture format worked

->For 1D Texture Arrays reading 3 bytes per pixel in the glGetTexImage() but then later specifying only RGB for texture format worked

But the specs say that it default reads 4 bytes per pixel for all texture types unless you the change that behaviour using pixelStorei()

and i am only using that method for creating 2D textures not anywhere else.

Can someone please explain why the diffrences?


Solution

  • As per the documentation it writes 4 bytes per pixels [...]

    No it does not. glGetTexImage(...GL_RGB, GL_UNSIGNED_BYTE...) reads 3 bytes per pixel. The length of a line is aligned to 4 bytes (if GL_PACK_ALIGNMENT is 4).
    The arguments format and _type of glGetTexImage do not specify the format of the source texture, but the format of the target buffer.