OpenGL: 对于2D纹理和1D纹理数组,glGetTexImage存在困惑

3
对于texture2D,我按以下方式提取mipmap的纹理。
pixels=ByteBuffer.allocateDirect(4*width*height);
    
GL11.glGetTexImage(
                    GL11.GL_TEXTURE_2D,mipMap
                   ,GL11.GL_RGB,GL11.GL_UNSIGNED_BYTE
                   ,pixels
                  );

根据文档,每像素写入4个字节,如果纹理不是4个分量,则将所需组件设置为零。
稍后,我可以使用这些像素创建2D纹理,如下所示。
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);

对于2D纹理,这个解决方案完美地实现了它的功能。

现在,跳到1D纹理数组中,我按以下方式读取特定mipmap的所有图层的图像:

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;

但是后来当我创建我的1D纹理数组如下所示
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);
}

颜色显示不正确,即使将纹理格式更改为GL_RGBA也无法解决问题。但是当我将常量从4更改为3时[只读取1d纹理数组的readMethod()中每个像素的3个字节],一切都正常工作了。所以我很困惑,因为我的所有测试纹理都是RGB格式,而我观察到的是:

->对于2D纹理,在glGetTexImage()中每个像素读取4个字节,但稍后仅指定RGB作为纹理格式即可。

->对于1D纹理数组,在glGetTexImage()中每个像素读取3个字节,但稍后仅指定RGB作为纹理格式即可。

specs说它默认读取所有纹理类型的每个像素的4个字节,除非您使用pixelStorei()更改该行为

而我只在创建2D纹理的方法中使用了该方法,没有其他地方使用。

有人能解释一下这些差异吗?


根据文档,它每个像素写入4个字节。- 不是的。glGetTexImage(...GL_RGB, GL_UNSIGNED_BYTE...) 每个像素读取3个字节。如果 GL_PACK_ALIGNMENT 为4,则一行的长度将对齐到4个字节。 - Rabbid76
但是它说如果纹理是RGB格式,它会将alpha填充为零,对吗?即使如此,为什么我的tex2D使用4个字节,即使它是一个RGB纹理? - Sync it
我明白了,但我在我的问题中指定了1D纹理数组的解包对齐方式为4,但这并没有起作用。我的缓冲区为RGBA格式,解包对齐方式现在也是4,但这并没有解决任何问题。 - Sync it
但我把它读到了一个GL_RGBA目标[我的字节缓冲器有4个分量],但它没起作用。1N 2D纹理可能会相当昂贵。 - Sync it
1
无论如何,明天我会尝试更多地操作缓冲区,并在我的问题中编辑结果。 - Sync it
显示剩余4条评论
1个回答

2
根据文档,每个像素会写入4个字节[...]。
不是的。 glGetTexImage(...GL_RGB, GL_UNSIGNED_BYTE...) 读取每个像素3个字节。如果GL_PACK_ALIGNMENT为4,则一行的长度对齐到4个字节。
函数glGetTexImage的参数format和_type并不指定源纹理的格式,而是目标缓冲区的格式。

谢谢,我会尝试并告诉你结果。我只用过UNPACK ALLIGNMENT而没有用过PACK ALLIGNMENT,也许那就是我要找的东西。 - Sync it
1
是的,你又说对了。就像我需要指定解包对齐方式来创建我的纹理使用glTexImage2D一样,我需要指定打包对齐方式来从我的纹理读取相同的像素,当我为我的texture2D和1DArray都指定打包对齐方式为1时,我可以正确地使用仅3个组件的bytebuffer从两个中读取像素。在我结束之前,有没有一种方法可以通过纹理的宽度和每像素的组件数来解密纹理的对齐方式,而不是到处指定1,这听说会影响性能? - Sync it
1
@Syncit 你无法按像素指定对齐方式。像素的大小仅取决于目标格式和类型。 - Rabbid76
1
我明白了,无论如何,对于RGB纹理,我指定对齐方式为1,对于RGBA纹理,我指定对齐方式为4,这似乎适用于大多数一般情况。这就是我要问的了,再次感谢。 - Sync it

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接