C++ 打开GL-为什么像素值在ABGR中以及如何在RGBA中使用它们

C++ 打开GL-为什么像素值在ABGR中以及如何在RGBA中使用它们,c++,opengl,pixelformat,C++,Opengl,Pixelformat,我有一些加载纹理的代码,我使用DevIL加载图像,然后OpenGL从像素创建纹理。这段代码运行良好,纹理正确显示,一切正常 除此之外,我还可以从程序中创建一个数组来创建纹理或直接更改纹理的像素。我的问题是:在处理像素时,它们的格式似乎是ABGR,而不是我希望的RGBA 我无意中发现了GLTEXAGE2D函数中传递的格式: (…)如果有GL_RGBA和GL_UNSIGNED_INT_8_8_8_8_8_8,这意味着像素存储在32位整数中,并且颜色在这样的整数中是逻辑顺序RGBA,例如,红色在高阶字

我有一些加载纹理的代码,我使用DevIL加载图像,然后OpenGL从像素创建纹理。这段代码运行良好,纹理正确显示,一切正常

除此之外,我还可以从程序中创建一个数组来创建纹理或直接更改纹理的像素。我的问题是:在处理像素时,它们的格式似乎是ABGR,而不是我希望的RGBA

我无意中发现了GLTEXAGE2D函数中传递的格式:

(…)如果有GL_RGBA和GL_UNSIGNED_INT_8_8_8_8_8_8,这意味着像素存储在32位整数中,并且颜色在这样的整数中是逻辑顺序RGBA,例如,红色在高阶字节中,alpha在低阶字节中。但如果机器是little endian(与Intel CPU一样),那么内存中的实际顺序就是ABGR。然而,具有GL_UNSIGNED_字节的GL_RGBA将以RGBA顺序存储字节,而不管计算机是小端还是大端。(……)

事实上,我有一个英特尔的CPU。图像的加载方式和现在一样,我实际上使用了GL_RGBA模式和GL_UNSIGNED_字节类型

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 );
但是我得到了一个透明的红色

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格式。如果我在另一台机器上运行我的代码,我会在直接改变像素/通道的地方突然看到奇怪的颜色吗?
有更好的解决方案吗?

您理解的问题:
0xRR,0xGG,0xBB,0xAA
在您(英特尔,little endian)的机器上是
0xAABBGGRR
。您已经发现信息表明,
GL\u UNSIGNED\u BYTE
保留跨机器的二进制数据块格式,而
GL\u UNSIGNED\u INT\u 8\u 8
保留像
0xRRGGBBAA
这样的文本格式。因为不同的机器在二进制和文本之间有不同的对应关系,所以您完全不可能同时拥有这两种类型的可移植性。在保留图像和硬编码文字之间,我想保留图像数据,因为我主要是为我的应用程序加载图像。所以,如果我真的写了
0xAABBGGRR
,那实际上是我机器上的RGBA,在另一台机器上运行这段代码会在屏幕上显示不同的结果?@aslg,是的,因为OpenGL会将其重新解释为
未签名的字节
。C++在使用着色之后需要一个种子库。Swizzle操作很便宜。您还可以将不同的格式传递给不同的函数调用。
struct Color4C {
    unsigned char alpha;
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    ...
};