opengl-es - Opengl ES 2.0 着色器 - 丢弃 alpha == 0 的像素而不丢弃,如果

标签 opengl-es glsl shader opengl-es-2.0 fragment-shader

我的片段着色器做了两件事:

  1. 显示来自纹理的原始像素颜色,v_Color 变量设置为 r=0,g=0,b=0,a=0
  2. 或丢弃原始像素颜色为存储在 v_Color 中的颜色。如果我将 v_Color 中的 alpha 设置为 1.0,则会采用此值,在其他情况下,会使用原始像素的颜色。

但是,如果我将此着色器应用于具有 alpha == 0.0 像素的图像,则在第二种情况下我会遇到问题。我预计这些像素是不可见的,但它们也是彩色的。在第一种情况下,我没有这个问题。我需要丢弃 alpha == 0 的像素

例如: 我有应该着色的人物轮廓纹理,但应该跳过透明像素。

在程序开始时我设置:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

这是我的片段着色器:

void main()
{
    vec4 c = vec4(v_Color);
    vec4 p = texture2D( s_texture, v_texCoord);

    gl_FragColor = mix(p, c, c.a);
}

但是,如果我添加 discard,那么一切都会像预期的那样工作。 alpha==0.0 的像素被移除。但我正在使用 OpenGL ES 2.0,着色器将在不同的 android 设备上运行,我读到了由“if”和“discard”引起的可能的性能问题。这就是为什么我使用“混合”而不是“如果”。

void main()
{
    vec4 c = vec4(v_Color);
    vec4 p = texture2D( s_texture, v_texCoord);

    if (p.a == 0.0) {
        discard;
    }

    gl_FragColor = mix(p, c, c.a);
}

我尝试了另一种尝试来解决这个问题。我记得来自纹理的原始 alpha,我在最后应用它。但它仍然给我奇怪的结果。 gl_FragColor.a = backup_alpha 对结果 alpha 做了一些事情,它在某种程度上是透明的但不完全。

void main()
{
    vec4 c = vec4(v_Color);
    vec4 p = texture2D( s_texture, v_texCoord);
    float backup_alpha = p.a;

    gl_FragColor = mix(p, c, c.a);
    gl_FragColor.a = backup_alpha;
}

enter image description here

感谢@Rabbid76 的帮助,这是正确的:

gl_FragColor = vec4(mix(p.rgb, c.rgb*p.a, c.a), p.a);

最佳答案

当你做的时候

gl_FragColor = mix(p, c, c.a);

然后丢弃纹理的alpha channel ,如果c.a == 1.0,因为alpha channel 也是从c读取的。

您必须混合纹理和颜色的 .rgb 组件,但您必须使用纹理的 alpha channel (在任何情况下)来解决问题:

gl_FragColor = vec4(mix(p.rgb, c.rgb, c.a), p.a);

如果颜色应该是黑色,那部分纹理的 alpha channel 为 0.0,那么在混合之前颜色必须乘以纹理的 alpha channel :

gl_FragColor = vec4(mix(p.rgb, c.rgb*p.a, c.a), p.a);

但请注意,由于纹理 filtering ,可能会出现,纹理中的某些红色颜色完全透明。如果您希望输出颜色完全不透明或完全透明,则必须将 alpha channel 与阈值进行比较。这可以通过 glsl 函数 step 来完成。 ,返回 1.0 或 0.0:

gl_FragColor = vec4(mix(p.rgb, c.rgb, c.a), step(0.5, p.a));

关于opengl-es - Opengl ES 2.0 着色器 - 丢弃 alpha == 0 的像素而不丢弃,如果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57604217/

相关文章:

ios - 使用 GL_LINE_STRIP 绘制三角形轮廓时的奇怪顺序

iOS 纹理重复半 npot 纹理

android - OpenGL ES 2.0 中的等 ionic 着色器性能

c++ - 由于缺乏对纹理坐标的理解,场景体素化不起作用

unity-game-engine - Unity - 着色器中的 AlphaToMask 似乎不适用于移动设备(透明度)

树莓派 : Cannot find GLESv2 的 qt 交叉编译

iphone - iphone 上的 OpenGL 上下文。它是做什么的/它是如何工作的?

opengl-es - 在 OpenGL 着色器中在 main 之外进行计算是否合理?

opengl - 编译着色器失败,我需要英特尔平台上的 ubuntu 的 openGL 驱动程序吗?

android - PowerVR GPU 上的着色器执行流程问题