【问题标题】:OpenGL: Why isn't discarding fragments the same as setting their alpha to zero?OpenGL:为什么丢弃片段与将其 alpha 设置为零不同?
【发布时间】:2014-12-20 00:44:53
【问题描述】:

我一直在 OpenGL ES 2 中绘制贝塞尔曲线,并引用了以下 HLSL 着色器。结果如下:

引用的着色器依赖于 if 语句来完成效果:

        float alpha  = (0.5f - sd);
        if(alpha > 1f) {
             alpha = 1f; 
        }
        else if(alpha < 0f) {
             discard; 
        }
        else {
             alpha = alpha; 
        }
        gl_FragColor = vec4(uColor.x, uColor.y, uColor.z, alpha);

由于这些大大降低了 OpenGL 管道中的性能,我认为与其使用 if 语句来强制 alpha 或丢弃片段,我可以强制边缘像素在小于 0f 时变为透明,使用钳位功能:

gl_FragColor = vec4(uColor.x, uColor.y, uColor.z, clamp(alpha, 0f, 1f));

但是,这不起作用,因为侧面像素仍然部分可见:

我的问题是,我是否遗漏了 discard 函数的一些基本内容?为什么零 alpha 量完全可见?

【问题讨论】:

  • 好吧,没有混合函数基于源 alpha 或片段着色器运行后的 alpha 测试(现代 GL 不再支持),将 alpha 设置为 0 不会做很多事情。除此之外,discard 会杀死所有可能输出的东西,包括深度和模板。
  • 嗨@AndonM.Coleman,我正在OpenGL 上下文中进行渲染,其中可以正确表示alpha 量,例如我可以淡化三角形或图像。您认为这些工件可能来自其他缓冲区吗?
  • 等等,你是对的!已为此渲染区域停用混合。请提交您的评论作为答案!

标签: java opengl-es bezier


【解决方案1】:

alpha 组件在 OpenGL 中没有内在意义。

人们通常认为它自动意味着透明度,但这实际上只是混合方式和glAlphaFunc (...)(过去)工作方式的结果。

通常,当您希望 alpha 组件执行某些操作时,您会使用 alpha blending:

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

^^^ Color = FragmentColor * FragmentAlpha  +  FramebufferColor * (1.0 - FragmentAlpha)

或 alpha 测试:

glAlphaFunc (GL_GREATER, 0.0f);

现代 OpenGL 不支持后者,因为这个测试可以在片段着色器中实现,您猜对了,discard

在任何一种情况下,您都必须分别启用 GL_BLENDGL_ALPHA_TEST 才能让他们执行任何操作。


至于discard 和使用0.0 alpha 值with alpha 混合之间的区别,discard 实际上会丢弃深度和模板值除了消除源颜色。 GL_ALPHA_TEST 在支持它的地方扮演类似的角色(它是/曾经是在片段着色器运行并丢弃未通过测试的片段之后发生的每片段测试)。

【讨论】:

  • 非常丰富的答案。感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
相关资源
最近更新 更多