OpenGL 透明度做了奇怪的事情

标签 opengl transparency

我正在尝试渲染一个带有 Alpha channel 的纹理。

这是我用于纹理加载的:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);

我在渲染纹理之前启用了GL_BLEND:glEnable(GL_BLEND);

我也在代码开头(初始化)执行了此操作:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

这是结果(应该是第一人称手的透明纹理): enter image description here

但是当我像这样加载纹理时(无 Alpha channel ):

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);

这是结果:

enter image description here

有谁知道什么会导致这个问题,或者我是否需要提供更多代码? 抱歉英语不好,提前谢谢。

编辑:

我的纹理加载代码:

GLuint Texture::loadTexture(const char * imagepath) {

    printf("Reading image %s\n", imagepath);

    // Data read from the header of the BMP file
    unsigned char header[54];
    unsigned int dataPos;
    unsigned int imageSize;
    unsigned int width, height;
    // Actual RGB data
    unsigned char * data;

    // Open the file
    FILE * file = fopen(imagepath, "rb");
    if (!file) { printf("%s could not be opened. \n", imagepath); getchar(); exit(0); }

    // Read the header, i.e. the 54 first bytes

    // If less than 54 bytes are read, problem
    if (fread(header, 1, 54, file) != 54) {
        printf("Not a correct BMP file\n");
        exit(0);
    }
    // A BMP files always begins with "BM"
    if (header[0] != 'B' || header[1] != 'M') {
        printf("Not a correct BMP file\n");
        exit(0);
    }
    // Make sure this is a 24bpp file
    if (*(int*)&(header[0x1E]) != 0) { printf("Not a correct BMP file\n");}
    if (*(int*)&(header[0x1C]) != 24) { printf("Not a correct BMP file\n");}

    // Read the information about the image
    dataPos = *(int*)&(header[0x0A]);
    imageSize = *(int*)&(header[0x22]);
    width = *(int*)&(header[0x12]);
    height = *(int*)&(header[0x16]);

    // Some BMP files are misformatted, guess missing information
    if (imageSize == 0)    imageSize = width*height * 3; // 3 : one byte for each Red, Green and Blue component
    if (dataPos == 0)      dataPos = 54; // The BMP header is done that way

                                         // Create a buffer
    data = new unsigned char[imageSize];

    // Read the actual data from the file into the buffer
    fread(data, 1, imageSize, file);

    // Everything is in memory now, the file wan be closed
    fclose(file);

    // Create one OpenGL texture
    GLuint textureID;
    glGenTextures(1, &textureID);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glBindTexture(GL_TEXTURE_2D, textureID);
    if (imagepath == "hand.bmp") {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    }else {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    delete[] data;
    return textureID;
}

正如你所见,这不是我自己编写的代码,我是从 opengl-tutorial.org 获取的

最佳答案

我的第一条评论是这样的:

The repeating, offset pattern looks like the data is treated as having a larger offset, when in reality it has smaller (or opposite).

那是在我真正注意到你做了什么之前。是的,正是如此。您不能将每像素 4 字节的数据视为每像素 3 字节的数据。 Alpha channel 被解释为颜色,这就是它全部以这种方式偏移的原因。

如果您想忽略 Alpha channel ,则需要在加载时将其剥离,以便 OpenGL 纹理内存中的每个像素值最终拥有 3 个字节。 (这就是@RetoKoradi的答案所建议的,即从 RGBA 数据创建 RGB 纹理)。

<小时/>

如果它实际上不应该看起来那么蓝色,也许它实际上不是在 BGR 布局中?

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);
                                                          ^
                                                          \--- change to GL_RGBA as well

我的大胆猜测是,人类皮肤反射的红光多于蓝光。

关于OpenGL 透明度做了奇怪的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34951201/

相关文章:

python - 使用 matplotlib 中的大小缩放误差条透明度

html - 使它下面的一切和它本身透明的形状

svg - SVG对象可以同时具有填充颜色和填充图案吗?

java - OpenGL:使用一个 VAO (LWJGL) 渲染 3D 模型的一个或多个部分

c++ - OpenGL 4.2 glBindAttribLocation 无效值?

cocoa - 让简单的 VBO 在 Mac 上运行时出现问题

c++ - Qt 中鼠标悬停在透明度上

c# - Unity 从透明度淡入不起作用

math - 将 3d 面绘制为 2d

opengl - 在 opengl glut 中绘制圆环的内置函数