openGL透明像素意外白色

时间:2018-05-09 19:29:49

标签: c++ opengl sdl photoshop alpha-transparency

我注意到我的openGL纹理渲染中存在一个大问题:

假设透明像素呈现为纯白色。根据StackOverflow上讨论的类似问题的大多数解决方案,我需要设置glBlend /正确的函数,但我已经设置了必要的gl状态,并且我认为纹理正确加载是正确的。我的纹理加载函数如下:

GLboolean GL_texture_load(Texture* texture_id, const char* const path, const GLboolean alpha, const GLint param_edge_x, const GLint param_edge_y)
{
    // load image
    SDL_Surface* img = nullptr; 
    if (!(img = IMG_Load(path))) {
        fprintf(stderr, "SDL_image could not be loaded %s, SDL_image Error: %s\n", 
               path, IMG_GetError());
        return GL_FALSE;
    }


    glBindTexture(GL_TEXTURE_2D, *texture_id);
    // image assignment
    GLuint format = (alpha) ? GL_RGBA : GL_RGB;
    glTexImage2D(GL_TEXTURE_2D, 0, format, img->w, img->h, 0, format, GL_UNSIGNED_BYTE, img->pixels);

    // wrapping behavior
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, param_edge_x);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, param_edge_y);
    // texture filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D, 0);
    // free the surface
    SDL_FreeSurface(img);

    return GL_TRUE;
}

我使用Adobe Photoshop导出“for the web”24位+透明度.png文件 - 72像素/英寸,6400 x 720.我不知道如何设置颜色模式(8,16,32) ,但这可能与问题有关。我也使用默认的sRGB颜色配置文件,但我想在一个点上删除颜色配置文件。这没有做任何事情。 无论如何,从Photoshop导出的png在透明像素上显示为纯白色。

如果我在例如Gimp,我有正确的透明度。导入Adobe .psd或.png似乎不起作用,无论如何我更喜欢使用Photoshop进行编辑。

有没有人遇到过这个问题?我想Photoshop必须添加一些奇怪的元数据,或者我没有使用正确的颜色模式 - 或两者兼而有之。 (我担心这超出了Stack Overflow的范围,但我的问题与图像编辑和编程相交。无论如何,如果这不是正确的地方,请告诉我。)

编辑:

在Photoshop和Gimp中,我创建了一个测试用例 - 顺时针方向为8像素(红色,绿色,透明,蓝色)。

tiny square

在Photoshop中,透明正方形读取为1,1,1,0并显示为白色。 在Gimp中,透明正方形是0,0,0,0。

我还检查了片段着色器,看透明度是否有效。随着时间的推移改变alpha会增加透明度,因此alpha不会被完全忽略。出于某种原因,1,1,1,0计为固体。 此外,使用glClearColor将背景颜色设置为黑色似乎可以防止alpha增加透明度。

我不知道如何解释这些行为中的一些,但似乎有些东西似乎没有。无论颜色如何,0 alpha应该是相同的,不应该吗?

(请注意,我在彼此的顶部渲染了一些形状,但我尝试只渲染一个用于测试目的。)

我能做的最好的事情是发布更多我的设置代码(省略位):

//顶点数组和缓冲区设置

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
// I think that the blend function may be wrong (GL_ONE that is).
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

glDepthRange(0, 1);
glDepthFunc(GL_LEQUAL);

Texture tex0;
// same function as above, but generates one texture id for me
if (GL_texture_gen_and_load_1(&tex0, "./textures/sq2.png", GL_TRUE,  GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE) == GL_FALSE) {
    return EXIT_FAILURE;
}

glUseProgram(shader_2d);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex0);
glUniform1i(glGetUniformLocation(shader_2d, "tex0"), 0);

bool active = true;
while (active) {
       glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

       // uniforms, game logic, etc.

       glDrawElements(GL_TRIANGLES, tri_data.i_count, GL_UNSIGNED_INT,   (void*)0);
}

1 个答案:

答案 0 :(得分:2)

  

我不知道如何解释其中的一些行为,但似乎有些事情没有。无论颜色如何,0 alpha应该是相同的,不应该吗?

如果想要获得0.0的alpha通道的相同结果,独立于红色,绿色和蓝色通道,则必须更改混合功能。请参阅glBlendFunc

使用:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

这导致红色,绿色和蓝色通道乘以alpha通道。 如果alpha通道为0.0,则生成的RGB颜色为(0,0,0)。 如果alpha通道为1.0,则RGB颜色通道保持不变。


请参阅Alpha Compositing, OpenGL Blending and Premultiplied Alpha