【问题标题】:opengl : glGetTexImage for 2d textures and 1d texture array confusionopengl : glGetTexImage 用于 2d 纹理和 1d 纹理数组混淆
【发布时间】:2021-03-19 00:57:46
【问题描述】:

对于 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 纹理非常有效。

现在跳转到纹理一维数组,我读取特定 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;

但后来当我按如下方式创建我的 texture1D 数组时

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[读取每个像素仅 3 个字节纹理一维数组的 readMethod()] 一切都再次正常工作。所以我在这里真的很困惑,因为我所有的测试纹理都是 RGB 格式,而我观察到的是

->对于在 glGetTexImage() 中每个像素读取 4 个字节的 2D 纹理,但后来只为纹理格式指定了 RGB

->对于 1D 纹理数组,在 glGetTexImage() 中每个像素读取 3 个字节,但随后仅指定 RGB 纹理格式有效

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

我只使用这种方法来创建 2D 纹理,而不是其他任何地方。

谁能解释一下为什么会有差异?

【问题讨论】:

  • *"根据文档,它每像素写入 4 个字节" - 不,它没有。 glGetTexImage(...GL_RGB, GL_UNSIGNED_BYTE...) 每像素读取 3 个字节。一行的长度对齐到 4 个字节(如果GL_PACK_ALIGNMENT 为 4)。
  • 但是据说如果纹理是 RGB 格式,它会将 alpha 填充为零,对吗?即使这样,为什么即使它是 RGB 纹理,4 字节也适用于我的 tex2D?
  • 它说:“如果所选纹理图像不包含四个组件[...]”。这意味着如果您尝试将 RGB 纹理读取到 RGBA 目标缓冲区,则 alpha 通道将设置为 255。glGetTexImage 的参数不指定源纹理的格式,但它们指定目标缓冲区的格式。
  • 我明白了,但我为我的 1D 纹理数组指定了 unpack allignment 为 4 [忘记包含在我的问题中],但它什么也没做。我的缓冲区是 RGBA,我的对齐现在也是 4,但这并没有解决任何问题
  • 无论如何,我明天会尝试多玩一下缓冲区,并在我的问题中编辑结果

标签: java opengl textures


【解决方案1】:

根据文档,它每像素写入 4 个字节 [...]

不,它没有。 glGetTexImage(...GL_RGB, GL_UNSIGNED_BYTE...) 每像素读取 3 个字节。一行的长度对齐到 4 个字节(如果 GL_PACK_ALIGNMENT 为 4)。
glGetTexImage的参数format和_type不指定源纹理的格式,而是指定目标缓冲区的格式。

【讨论】:

  • 谢谢你,我会试一试,让你知道。我只使用了 UNPACK ALLIGNMENT 但没有使用 PACK ALLIGNMENT 也许这就是我要找的。​​span>
  • 是的,你又是对的。正如我需要指定解包对齐以使用 glTexImage2D 创建我的纹理一样,我需要指定打包对齐以从我的纹理中读取相同的像素,并且当我为我的 texture2D 和 1DArray 指定打包对齐为 1 时,我能够正确读取两者的像素仅使用 3 个分量的字节缓冲区。在我结束之前有没有办法使用它的宽度和每个像素的 numOfComponents 来破译纹理的对齐方式,而不是在我听说读取先前线程的性能影响的任何地方指定 1?
  • @Syncit 您不能指定每个像素的对齐方式。像素的大小仅取决于目标格式和类型。
  • 我明白了,无论如何,我为 RGB 指定对齐 1,为 RGBA 纹理指定对齐 4,它似乎适用于大多数一般情况。这就是我要问的,再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多