OpenGL:为什么丢弃片段与将其alpha设置为零不一样?

Map*_*psy 1 java bezier opengl-es

我一直在参考以下HLSL着色器在OpenGL ES 2中绘制Bezier曲线。下面显示了结果:

贝塞尔曲线1

引用的着色器依赖于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);
Run Code Online (Sandbox Code Playgroud)

由于这些会大大降低OpenGL管道中的性能,因此我认为,如果不使用if语句来强制Alpha或丢弃片段,则可以使用钳位函数强制边缘像素小于0f时变得透明。

gl_FragColor = vec4(uColor.x, uColor.y, uColor.z, clamp(alpha, 0f, 1f));
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

我的问题是,我是否缺少有关该discard功能的基本知识?为什么零的alpha量完全可见?

And*_*man 5

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

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

通常,当您希望Alpha组件执行某些操作时,可以使用Alpha混合:

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

^^^ Color = FragmentColor * FragmentAlpha  +  FramebufferColor * (1.0 - FragmentAlpha)
Run Code Online (Sandbox Code Playgroud)

或Alpha测试:

glAlphaFunc (GL_GREATER, 0.0f);
Run Code Online (Sandbox Code Playgroud)

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

无论哪种情况,您都必须启用GL_BLENDGL_ALPHA_TEST分别使它们执行任何操作。


至于0.0 alpha值 alpha混合之间的差异discard以及使用0.0 alpha值 Alpha混合使用之间的差异discard,除了消除源颜色之外,实际上还会丢弃深度和模板值。GL_ALPHA_TEST在受支持的地方起着类似的作用(它是/曾经是片段着色器运行,在片段着色器运行并丢弃未通过测试的片段之后进行)。