使用 GLSL 在两个不同的通道上进行 Alpha 混合纹理

Posted

技术标签:

【中文标题】使用 GLSL 在两个不同的通道上进行 Alpha 混合纹理【英文标题】:Alpha Blending textures on two different passes using GLSL 【发布时间】:2012-11-28 05:04:22 【问题描述】:

我所拥有的是一组 3x3 网格中的 9 个正方形,用于测试此混合功能。这就是想法。

通过 1:

绑定 texture1(污垢) 使用 tex1 = Dirt 渲染方块

通行证 2:

绑定texture2(字母) 使用 tex2 = Letter W 渲染相同的正方形

这是针对游戏内编辑器的。我们希望能够在输入文本图集时更改字母的颜色。着色器应该从纹理中检查片段的 alpha 值。任何不等于 0(即可见)的值都应更改为作为属性传递到着色器的所需颜色。

//Draw all Squares

glBindTexture(GL_TEXTURE_2D, textureID1);   //Dirt Texture

for (int Index = 0; Index < 9; Index++)

//Pass in Vertex Positions...
//Pass in UV's...
glDrawArrays(GL_TRIANGLES, 0, 6); // From index 0 to 6 -> 2 triangle


//Redraw Squares with letter texture bound.

glBindTexture(GL_TEXTURE_2D, textureID2);  //Letter Texture

glVertexAttrib3f(2,255,0,0);  //Desired Color of letter, passed to shaders.

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.05f);  //Anything with alpha < 0.05 is discarded.

//Draw all Squares
for (int Index = 0; Index < 9; Index++)

   //Pass in Vertex Positions...
   //Pass in UV's...
glDrawArrays(GL_TRIANGLES, 0, 6); // From index 0 to 6 -> 2 triangle


glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_ALPHA_TEST);

//Draw blue vertex dots...etc...

这是一张显示源图像的图片,以及 2 个略有不同的片段着色器的输出。以及想要的结果。

Image Sources, with Frag Shaders and Desired Result

已加载纹理,两者都有 Alpha 通道(GL_BGRA、Targas)。我使用 GL_NEAREST 作为 MIN/MAG 过滤器。

奇怪的是,如果我在 LETTER TEXTURE 的 Alpha 通道中使用 99% 白色(即 254),则此着色器对我有效,而当我使用全白色(即 255)时,它会失败。

我尝试过启用 GL_BLEND 并使用各种 BlendFunc,但它们似乎不起作用。

我想问题是。在不使用多纹理着色器且不渲染到 FBO 的情况下,这是进行这种混合的正确方法吗?

【问题讨论】:

"不使用多纹理着色器" 绝对没有不能处理多纹理的基于着色器的硬件。我认为你没有理由不使用多重纹理。 感谢您的意见。我同意多重纹理将是解决此问题的简单方法。但是,我想尝试使用一次仅绑定 1 个纹理的单个着色器来执行此操作。 【参考方案1】:

事实证明,这是着色器的行为与我预期一样的情况之一,但我误解了它的确切含义。

在这种情况下,我使用相同的着色器来渲染初始背景纹理和覆盖文本纹理。因为背景纹理上的 Alpha 通道一直是纯色 1.0(白色),所以将污垢纹理渲染为纯红色。然后在第二遍时,它会正确渲染文本,但我看不到它,因为它也被渲染为红色。

我在这种情况下解决了我的问题,而是在字母纹理的 Alpha 通道中用黑色(即透明)绘制字母,然后在着色器中进行 Alpha 测试并在必要时进行反转。此方法的关键是在呈现字母之前启用混合,并在之后禁用它。

最后,着色器的工作原理是这样的。

如果片段 alpha 然后,颜色 = vec4(in_color,(tex_color.a = (tex.color.a) ? (1.0 - tex_color.a) : 1.0));

否则,(Alpha = 1) 反转 Alpha 通道 tex_color.a = 0; 颜色 = tex_color;

这使得在 Alpha 通道中以黑色绘制的任何内容在启用混合时将变为彩色而不是透明。

最后,多纹理可能是要走的路,但就我而言,我想尝试一次只启用 1 个纹理。

【讨论】:

以上是关于使用 GLSL 在两个不同的通道上进行 Alpha 混合纹理的主要内容,如果未能解决你的问题,请参考以下文章

如何在视频之上叠加不同的 Alpha 通道动画?

Premiere 2.0 alpha道的问题

透明视频,如何在每台设备上正确显示 webm 文件的 alpha 通道; VP9 还是 VP8 编码?

如何在png里删除alpha通道

Sketch 03/26

ffmpeg 使用过滤器分割 RGB 和 Alpha 通道