asl*_*slg 5 c++ opengl pixelformat
我有一些用于加载纹理的代码,其中我使用 DevIL 加载图像,然后 OpenGL 从像素创建纹理。这段代码工作正常,纹理显示正确,这一切都很好。
除此之外,我还可以从程序内创建一个数组来创建纹理或直接更改纹理的像素。我的问题在于:处理像素时,它们的格式似乎是 ABGR 而不是我希望的 RGBA。
我偶然发现了这个问题,它指的是在 glTexImage2D 函数中传递的格式:
(...) 如果你有 GL_RGBA 和 GL_UNSIGNED_INT_8_8_8_8,这意味着像素存储在 32 位整数中,并且颜色按照这样的整数中的逻辑顺序 RGBA 排列,例如,红色位于高位字节,而颜色位于高位字节。 alpha 位于低位字节。但如果机器是小尾数法(如 Intel CPU),则内存中的实际顺序是 ABGR。而 GL_RGBA 和 GL_UNSIGNED_BYTE 将以 RGBA 顺序存储字节,无论计算机是小端还是大端。(...)
事实上我有一个英特尔CPU。图像按照现在的方式加载得很好,我实际上使用 GL_RGBA 模式和 GL_UNSIGNED_BYTE 类型。
GLuint makeTexture( const GLuint* pixels, GLuint width, GLuint height ) {
GLuint texture = 0;
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, NULL );
GLenum error = glGetError();
if ( error != GL_NO_ERROR ) {
return 0;
}
return texture;
}
Run Code Online (Sandbox Code Playgroud)
这个函数在我的两种加载纹理的方法中使用,一种是从文件加载图像的方法,另一种是从数组创建纹理的方法。
假设我想创建一个像素数组并创建一个纹理,
GLuint pixels[ 128 * 128 ];
for ( int i = 0; i < 128 * 128; ++i ) {
pixels[ i ] = 0x800000FF;
}
texture.loadImageArray( pixels, 128, 128 );
Run Code Online (Sandbox Code Playgroud)
通过用这个值填充像素,我预计会看到略带深红色的颜色。
red = 0x80, green = 0x00, blue = 0x00, alpha = 0xFF
Run Code Online (Sandbox Code Playgroud)
但我得到的是透明的红色,
alpha = 0x80, blue = 0x00, green = 0x00, red = 0xFF
Run Code Online (Sandbox Code Playgroud)
我没有使用原始无符号整数,而是创建了一个结构来帮助我处理各个通道:
struct Color4C {
unsigned char alpha;
unsigned char blue;
unsigned char green;
unsigned char red;
...
};
Run Code Online (Sandbox Code Playgroud)
我可以轻松地将无符号整数数组替换为 Color4C 数组,结果是相同的。如果我反转通道的顺序(首先是红色,最后是 alpha),那么我可以轻松地传递 0xRRGGBBAA 并使其工作。
简单的解决方案是简单地以 ABGR 格式处理这些值。但我也发现使用 RGBA 值更容易。如果我想使用硬编码的颜色值,我更愿意将它们写成 0xRRGGBBAA 而不是 0xAABBGGRR。
但假设我开始使用 ABGR 格式。如果我要在另一台机器上运行代码,我是否会在直接更改像素/通道的地方突然看到奇怪的颜色?有更好的解决方案吗?
将一些有用的评论推广到答案:
\n\n\n\n
0xRR,0xGG,0xBB,0xAA
在你的(英特尔,小端)机器上是0xAABBGGRR
. 您已经找到的信息表明 GL_UNSIGNED_BYTE 保留跨机器的二进制数据块的格式,同时GL_UNSIGNED_INT_8_8_8_8
保留像这样的文字格式0xRRGGBBAA
. 因为不同的机器在二进制和文字之间有不同的对应关系,所以你绝对不可能同时拥有两种类型的可移植性。\xe2\x80\x93 本·沃伊特
\n\n[
\n0xAABBGGRR
在您的机器上写入实际上是 RGBA,但在另一台机器上运行此代码可能会显示不同的结果]因为 OpenGL 会将其重新解释为UNSIGNED_BYTE
. 毕竟,C++ 需要一个字节顺序库。\xe2\x80\x93 WorldSender
归档时间: |
|
查看次数: |
3579 次 |
最近记录: |