Alpha 混合纹理和图元
Alpha blending textures and primitives
我有两个纹理和一个三角形图元(其顶点的颜色由 glColor4f
定义)。
纹理 A 看起来像这样:
纹理 B 看起来像这样:
三角形基元 P 看起来像这样:
当我渲染纹理 A,然后渲染纹理 B 时,我得到了预期的结果,即矩形的中间是透明的。
但是,如果我先渲染图元 P,再渲染纹理 A,再渲染纹理 B,我会得到错误的颜色。 P 不是纯红色,纹理颜色全部变成黑色。
如何解决此问题以保持适当的透明度和颜色。
纹理参数:
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));
混合函数:
GL_CALL(glEnable(GL_BLEND));
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
P、A、B渲染图:
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 的解决方案后:
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
}
我得到以下结果:
即使三个实体的alpha都是1.0f,空心区域的alpha是0.0f,颜色还是不对
如果启用纹理,则默认情况下纹理元素的颜色乘以当前颜色,因为默认情况下纹理环境模式 (GL_TEXTURE_ENV_MODE
) 为 GL_MODULATE
。参见 glTexEnv
。
这会导致纹理纹素的颜色是 "mixed" 您通过 glColor4f
设置的最后一种颜色。
当您渲染纹理时,三角形的红色仍然设置,这导致纹理呈现红色。绿色和蓝色通道完全丢失,并且由于纹理没有红色通道,所以剩下的一切都是黑色。
为了解决您的问题,您必须在渲染纹理之前设置白色:
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
并在渲染三角形之前禁用 GL_TEXTURE_2D
,但在渲染纹理之前启用它。
注意总是有一个纹理边界,没有像 "no texture" 这样的东西,默认纹理对象 0 也是一个有效对象。
这导致纹理查找给出完全黑色,并且与红色混合,红色由 glColor4f
:
设置
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
.....
}
我有两个纹理和一个三角形图元(其顶点的颜色由 glColor4f
定义)。
纹理 A 看起来像这样:
纹理 B 看起来像这样:
三角形基元 P 看起来像这样:
当我渲染纹理 A,然后渲染纹理 B 时,我得到了预期的结果,即矩形的中间是透明的。
但是,如果我先渲染图元 P,再渲染纹理 A,再渲染纹理 B,我会得到错误的颜色。 P 不是纯红色,纹理颜色全部变成黑色。
如何解决此问题以保持适当的透明度和颜色。
纹理参数:
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));
混合函数:
GL_CALL(glEnable(GL_BLEND));
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
P、A、B渲染图:
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 的解决方案后:
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
}
我得到以下结果:
即使三个实体的alpha都是1.0f,空心区域的alpha是0.0f,颜色还是不对
如果启用纹理,则默认情况下纹理元素的颜色乘以当前颜色,因为默认情况下纹理环境模式 (GL_TEXTURE_ENV_MODE
) 为 GL_MODULATE
。参见 glTexEnv
。
这会导致纹理纹素的颜色是 "mixed" 您通过 glColor4f
设置的最后一种颜色。
当您渲染纹理时,三角形的红色仍然设置,这导致纹理呈现红色。绿色和蓝色通道完全丢失,并且由于纹理没有红色通道,所以剩下的一切都是黑色。
为了解决您的问题,您必须在渲染纹理之前设置白色:
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
并在渲染三角形之前禁用 GL_TEXTURE_2D
,但在渲染纹理之前启用它。
注意总是有一个纹理边界,没有像 "no texture" 这样的东西,默认纹理对象 0 也是一个有效对象。
这导致纹理查找给出完全黑色,并且与红色混合,红色由 glColor4f
:
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
.....
}