我有一些用于加载纹理的代码,我使用DevIL加载图像,然后OpenGL从像素创建纹理。这段代码工作正常,纹理正确显示,并且一切都很好。
除此之外,我还可以在程序中创建一个数组来创建纹理或直接在纹理的像素中进行更改。我的问题在于:在处理像素时,它们的格式似乎是ABGR而不是RGBA,正如我所希望的那样。
我偶然发现this SO question指的是glTexImage2D函数中传递的格式:
(...)如果你有GL_RGBA和GL_UNSIGNED_INT_8_8_8_8,那意味着像素以32位整数存储,并且颜色在逻辑顺序RGBA中是这样的整数,例如红色位于高位字节,alpha位于低位字节。但如果机器是little-endian(与Intel CPU一样),那么内存中的实际顺序是ABGR。然而,GL_RGBA与GL_UNSIGNED_BYTE将以RGBA顺序存储字节,无论计算机是小端还是大端。 (...)
确实我有一个Intel 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;
}
这个函数用于我的两种加载纹理的方法,从文件加载图像的方法和从数组创建纹理的方法。
让我们说我想创建一个像素数组并创建一个纹理,
GLuint pixels[ 128 * 128 ];
for ( int i = 0; i < 128 * 128; ++i ) {
pixels[ i ] = 0x800000FF;
}
texture.loadImageArray( pixels, 128, 128 );
通过用这个值填充像素,我希望看到一个略带深红色的颜色。
red = 0x80, green = 0x00, blue = 0x00, alpha = 0xFF
但我得到一个透明的红色,
alpha = 0x80, blue = 0x00, green = 0x00, red = 0xFF
我没有使用原始的无符号整数,而是建立了一个结构来帮助我处理各个频道:
struct Color4C {
unsigned char alpha;
unsigned char blue;
unsigned char green;
unsigned char red;
...
};
我可以使用Color4C数组轻松替换无符号整数数组,结果相同。如果我颠倒了通道的顺序(首先是红色,最后是alpha),那么我可以很容易地传递0xRRGGBBAA并使其工作。
简单的解决方案是简单地以ABGR格式处理这些值。但我也发现使用RGBA值更容易。如果我想使用硬编码颜色值,我宁愿把它们写成0xRRGGBBAA而不是0xAABBGGRR。
但是,让我们说我开始使用ABGR格式。如果我在另一台机器上运行我的代码,无论我直接更改像素/通道,我都会突然看到奇怪的颜色吗? 有更好的解决方案吗?