【问题标题】:Opengl ES 2.0 shader - discard pixels with alpha == 0 without discard and ifOpengl ES 2.0 着色器 - 丢弃 alpha == 0 的像素而不丢弃,如果
【发布时间】:2019-12-27 11:25:15
【问题描述】:

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

  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);
}

但是,如果我添加丢弃,那么所有工作都像预期的那样。删除 alpha==0.0 的像素。但是我正在使用 OpenGL ES 2.0,着色器将在不同的 android 设备上运行,并且我读到了由“if”和“discard”引起的可能的性能问题。这就是我使用“mix”而不是“if”的原因。

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;
}

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

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

【问题讨论】:

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


    【解决方案1】:

    当你这样做时

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

    那么纹理的alpha通道被丢弃,如果是c.a == 1.0,因为alpha通道也是从c读取的。

    您必须混合纹理和颜色的.rgb 分量,但您必须使用纹理的 Alpha 通道(无论如何)来解决问题:

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

    如果颜色应该是黑色,即纹理的 alpha 通道为 0.0 的部分,则颜色必须乘以纹理的 alpha 通道,然后才能混合:

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

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

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

    【讨论】:

    • 谢谢,我虽然差不多,但是不行。它给了我与我上次尝试相同的结果。我用丢弃和你的 gl_FragColor = vec4(mix(p.rgb, c.rgb, c.a), p.a); 添加了结果图像
    • 我正在尝试,但仍然没有运气:(
    • 这行得通:gl_FragColor = mix(p,vec4(mix(p.rgb, c.rgb, p.a), p.a), c.a);但我不知道为什么,谁能解释一下?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多