关于opengl:Alpha混合纹理和图元

Alpha blending textures and primitives

我有两个纹理和一个三角形图元(其顶点的颜色由glColor4f定义)。

纹理A看起来像这样:

Texture A

纹理B看起来像这样:

Texture B

三角形基元P看起来像这样:

Primitive P

当我渲染纹理A,然后渲染纹理B时,我得到了预期的结果,即矩形的中间是透明的。

Render A then Render B

但是,如果我渲染图元P,然后渲染纹理A,然后渲染纹理B,则会得到错误的颜色。 P不是纯红色,纹理颜色全部变为黑色。

P-> A-> B

如何解决此问题,以便保持适当的透明度和颜色。

纹理参数:

1
2
3
4
5
6
    GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER));
    GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER));
    GLfloat debugColor[] = {1.0f, 0.0f, 1.0f, 1.0f};
    GL_CALL(glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, debugColor));

融合功能:

1
2
GL_CALL(glEnable(GL_BLEND));
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));

P,A和B的渲染:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
        if(true)
        {
            // Render Primitive P

            GL_CALL(glBegin(GL_TRIANGLES));

            GL_CALL(glColor4f(1.0f, 0.0f, 0.0f, 1.0f));
            GL_CALL(glVertex2f(-0.5f, -0.5f));

            GL_CALL(glColor4f(1.0f, 0.0f, 0.0f, 1.0f));
            GL_CALL(glVertex2f(0.0f, 0.5f));

            GL_CALL(glColor4f(1.0f, 0.0f, 0.0f, 1.0f));
            GL_CALL(glVertex2f(0.5f, -0.5f));

            glEnd();
        }
        if(true)
        {
            // Render Texture A

            GL_CALL(glBindTexture(GL_TEXTURE_2D, textureId));
            GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageWidth, imageHeight, 0,
                                 GL_RGBA, GL_UNSIGNED_BYTE, image));

            real32 screenPercentage = 0.25f;

            GL_CALL(glBegin(GL_TRIANGLES));

            // Lower triangle
            GL_CALL(glTexCoord2f(0.0f, 0.0f));
            GL_CALL(glVertex2f(-screenPercentage, screenPercentage));

            GL_CALL(glTexCoord2f(1.0f, 0.0f));
            GL_CALL(glVertex2f(screenPercentage, screenPercentage));

            GL_CALL(glTexCoord2f(1.0f, 1.0f));
            GL_CALL(glVertex2f(screenPercentage, -screenPercentage));

            //  Upper triangle
            GL_CALL(glTexCoord2f(0.0f, 0.0f));
            GL_CALL(glVertex2f(-screenPercentage, screenPercentage));

            GL_CALL(glTexCoord2f(1.0f, 1.0f));
            GL_CALL(glVertex2f(screenPercentage, -screenPercentage));

            GL_CALL(glTexCoord2f(0.0f, 1.0f));
            GL_CALL(glVertex2f(-screenPercentage, -screenPercentage));

            glEnd();
        }

        if(true)
        {
            // Render Texture B

            GL_CALL(glBindTexture(GL_TEXTURE_2D, textureId));
            GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, window[0].offscreenBuffer.width, window[0].offscreenBuffer.height, 0,
                                 GL_RGBA, GL_UNSIGNED_BYTE, window[0].offscreenBuffer.data));

            real32 screenPercentage = 1.0f;

            GL_CALL(glBegin(GL_TRIANGLES));

            // Lower triangle
            GL_CALL(glTexCoord2f(0.0f, 0.0f));
            GL_CALL(glVertex2f(-screenPercentage, screenPercentage));

            GL_CALL(glTexCoord2f(1.0f, 0.0f));
            GL_CALL(glVertex2f(screenPercentage, screenPercentage));

            GL_CALL(glTexCoord2f(1.0f, 1.0f));
            GL_CALL(glVertex2f(screenPercentage, -screenPercentage));

            // Upper triangle
            GL_CALL(glTexCoord2f(0.0f, 0.0f));
            GL_CALL(glVertex2f(-screenPercentage, screenPercentage));

            GL_CALL(glTexCoord2f(1.0f, 1.0f));
            GL_CALL(glVertex2f(screenPercentage, -screenPercentage));

            GL_CALL(glTexCoord2f(0.0f, 1.0f));
            GL_CALL(glVertex2f(-screenPercentage, -screenPercentage));

            glEnd();
        }

编辑:尝试@ Rabbid76的解决方案后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        if(true)
        {
        // Render triangle with all vertices having color 1.0f, 0.0f, 0.0f, 1.0f
        }
        if(true)
        {
        // Render texture A with color set to 1.0f, 1.0f, 1.0f, 1.0f and the appropriate texture u,v coordinates
        }

        if(true)
        {
            // Render texture B with color set to 1.0f, 1.0f, 1.0f, 1.0f and the appropriate texture u,v coordinates
        }

我得到以下结果:

enter image description here

即使所有三个实体的alpha为1.0f,而空心区域的alpha为0.0f,颜色仍然不正确


如果启用纹理,则默认情况下,纹理像素的颜色将乘以当前颜色,因为默认情况下纹理环境模式(GL_TEXTURE_ENV_MODE)为GL_MODULATE。请参阅glTexEnv

这导致纹理的纹理像素的颜色与glColor4f设置的最后一种颜色"混合"。
渲染纹理时,仍会设置三角形的红色,这将导致纹理变为红色。绿色和蓝色通道完全消失,并且由于纹理没有红色通道,因此剩下的一切都是黑色。

为了解决您的问题,必须在渲染纹理之前设置白色:

1
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

并在渲染三角形之前禁用GL_TEXTURE_2D,但在渲染纹理之前将其启用。
请注意,始终存在纹理绑定,没有"没有纹理"之类的东西,默认纹理对象0也是有效对象。
这将导致纹理查找呈现完全黑色,并与由glColor4f设置的红色混合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
glDisable( GL_TEXTURE_2D );
if( true )
{
    // Render Primitive P
    .....
}

glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glEnable( GL_TEXTURE_2D );
if ( true )
{
    // Render Texture A
    .....
}