Opengl 使用stb_图像加载32位png并将GL_UNSIGNED_INT_8_8_8_8_8_8作为glTexImage2D类型参数时显示的颜色不正确

Opengl 使用stb_图像加载32位png并将GL_UNSIGNED_INT_8_8_8_8_8_8作为glTexImage2D类型参数时显示的颜色不正确,opengl,png,textures,glteximage2d,Opengl,Png,Textures,Glteximage2d,我只是在学习如何在OpenGL中使用纹理,我对我得到的一些结果感到有点困惑 我正在使用stb_图像加载以下棋盘png图像: 当我保存png图像时,我明确选择将其保存为32位。这会让我相信,每个组件(RGBA)将被存储为8位,总共32位,即无符号整数的大小。但是,使用以下代码: unsigned char * texture_data = stbi_load("resources/graphics-scene/tut/textures/checker.png", &w, &

我只是在学习如何在OpenGL中使用纹理,我对我得到的一些结果感到有点困惑

我正在使用stb_图像加载以下棋盘png图像:

当我保存png图像时,我明确选择将其保存为32位。这会让我相信,每个组件(RGBA)将被存储为8位,总共32位,即无符号整数的大小。但是,使用以下代码:

unsigned char * texture_data = 
  stbi_load("resources/graphics-scene/tut/textures/checker.png", &w, &h, nullptr, 4);

// ...

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0,
  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,  texture_data);
收益率:

如果改用GL_UNSIGNED_BYTE作为类型参数,则会得到正确的结果

此外,为了方便起见,我还尝试了以下图片:

产生

GL_UNSIGNED_BYTE在这种情况下也会给出正确的结果

我不确定这是不是我误解了glTexImage2D还是stb_图像(它是否将加载的数据转换为8位?我似乎不太可能)

编辑:我终于找到了一个相关的帖子(已经搜索了一些,但没有运气)。然而答案()使我困惑。如果是这样的话,类型参数指定每个组件有多少字节,那么像GL_UNSIGNED_BYTE_3_3_2和GL_UNSIGNED_INT_8_8_8_8_8_8_8_8_8_8_8_8_8这样的东西到底意味着什么

如果是这样的话,类型参数指定每个组件有多少字节,那么像GL_UNSIGNED_BYTE_3_3_2和GL_UNSIGNED_INT_8_8_8_8_8_8_8_8_8_8_8_8_8_8_8_8_8这样的东西到底意味着什么

这两者都可以,具体取决于实际的类型

如果只是一种数据类型,则它指定每个组件的数据大小。如果其中包含数字,则类型指定每像素数据的大小;这些数字指定该数据类型中的各个零部件尺寸

GL_UNSIGNED_INT_8_8_8_8_8
意味着OpenGL将把每个像素解释为一个无符号整数。第一个分量是高8位,下一个分量是下一个8位,依此类推

然而您的问题来自于一个事实,即机顶盒映像不能处理无符号整数。每个像素以RGBA顺序写入4个单独的字节。基本上,它是这样做的:

GLubyte arr[4] = {red, green, blue, alpha};
现在,这听起来可能是同一件事。但事实并非如此。原因与此有关

在C/C++中执行此操作时:

GLuint foo = 0;
foo |= (red << 24);
foo |= (green << 16);
foo |= (blue << 8);
foo |= (alpha << 0);
也就是说,
foo
指向的内存的第一个字节不必是
红色的
组件

在低位字节排序中,32位整数的低位字节存储在第一位,而不是最后一位

当OpenGL看到
GL\u UNSIGNED\u INT
时,这意味着它将完全按照CPU的方式解释这四个字节。因此,
GL_UNSIGNED_INT_8_8_8_8_8
将与上面的
foo
等效。它看到的内存的第一个字节将在一个小的endian机器上被解释为低字节,而不是高字节

机顶盒图像不输出
GL_UNSIGNED_INT_8_8_8_8
。它将每个像素视为一个4字节数组,如上面的
arr
。因此,您必须告诉OpenGL这就是数据的存储方式。所以你说每个组件是一个字节。这就是
GL\u UNSIGNED\u BYTE
所做的

如果是这样的话,类型参数指定每个组件有多少字节,那么像GL_UNSIGNED_BYTE_3_3_2和GL_UNSIGNED_INT_8_8_8_8_8_8_8_8_8_8_8_8_8_8_8_8_8这样的东西到底意味着什么

这两者都可以,具体取决于实际的类型

如果只是一种数据类型,则它指定每个组件的数据大小。如果其中包含数字,则类型指定每像素数据的大小;这些数字指定该数据类型中的各个零部件尺寸

GL_UNSIGNED_INT_8_8_8_8_8
意味着OpenGL将把每个像素解释为一个无符号整数。第一个分量是高8位,下一个分量是下一个8位,依此类推

然而您的问题来自于一个事实,即机顶盒映像不能处理无符号整数。每个像素以RGBA顺序写入4个单独的字节。基本上,它是这样做的:

GLubyte arr[4] = {red, green, blue, alpha};
现在,这听起来可能是同一件事。但事实并非如此。原因与此有关

在C/C++中执行此操作时:

GLuint foo = 0;
foo |= (red << 24);
foo |= (green << 16);
foo |= (blue << 8);
foo |= (alpha << 0);
也就是说,
foo
指向的内存的第一个字节不必是
红色的
组件

在低位字节排序中,32位整数的低位字节存储在第一位,而不是最后一位

当OpenGL看到
GL\u UNSIGNED\u INT
时,这意味着它将完全按照CPU的方式解释这四个字节。因此,
GL_UNSIGNED_INT_8_8_8_8_8
将与上面的
foo
等效。它看到的内存的第一个字节将在一个小的endian机器上被解释为低字节,而不是高字节

机顶盒图像不输出
GL_UNSIGNED_INT_8_8_8_8
。它将每个像素视为一个4字节数组,如上面的
arr
。因此,您必须告诉OpenGL这就是数据的存储方式。所以你说每个组件是一个字节。这就是
GL\u UNSIGNED\u BYTE
所做的