当前位置:   article > 正文

【Unity Shaders】Alpha Test和Alpha Blending_alphatest

alphatest


写在前面


关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到半透明问题的时候,总是不知道为什么A就遮挡了B,而B明明在A前面。这篇文章就总结一下我现在的认识~


Alpha Test和Alpha Blending是两种处理透明的方法。


Alpha Test采用一种很霸道极端的机制,只要一个像素的alpha不满足条件,那么它就会被fragment shader舍弃,“我才不要你类!”。被舍弃的fragments不会对后面的各种Tests产生影响;否则,就会按正常方式写入到缓存中,并进行正常的深度检验等等,也就是说,Alpha Test是不需要关闭ZWrite的Alpha Test产生的效果也很极端,要么完全透明,即看不到,要么完全不透明。


Alpha Blending则是一种中庸的方式,它使用当前fragment的alpha作为混合因子,来混合之前写入到缓存中颜色值。但Alpha Blending麻烦的一点就是它需要关闭ZWrite,并且要十分小心物体的渲染顺序。如果不关闭ZWrite,那么在进行深度检测的时候,它背后的物体本来是可以透过它被我们看到的,但由于深度检测时大于它的深度就被剔除了,从而我们就看不到它后面的物体了。因此,我们需要保证物体的渲染顺序是从后往前,并且关闭该半透明对象的ZWrite。


注意Alpha Blending只是关闭ZWrite,人家可没有关闭ZTest哦!这意味着,在输出一个Alpha Blending的fragment时,它还是会判断和当前Color Buffer中的fragment的深度关闭,如果它比当前的fragment深度更远,那么它就不会再做后续的混合操作;否则,它就会和当前的fragment进行混合,但是不会把自己的深度信息写入Depth Buffer中。这是非常重要的,这一点决定了,即便一个不透明物体出现在一个透明物体的前面,不透明物体仍可以正常的遮挡住透明物体!也就说说,对于Alpha Blending来说,Depth Buffer是只读的。



Surface Shader


在Unity的Surface Shader里实现上述两种技术是非常简单的,可以参见之前的文章——Alpha TestAlpha Blending。简单总结一下就是,只要在#pragma里设置alphatest:_Cutoffalpha指令即可。


但是,很多童鞋说在使用Alpha Blending的时候得不到正确的结果,那么很大可能就是Tags没有设对,更具体一点,就是渲染队列没有设置正确。一般透明对象应该起码设置为Tags { "Queue"Transparent" }。为什么要正确设置渲染队列呢?如果没有正确设置,那么很有可能透明物体后面的物体会出现在透明物体的前面。


但是,它们背后的原理是什么呢?这就要从它们生成的Vertex & Fragment Shader说起了。那么,请看下一节~



Vertex & Fragment Shader


我们先来说比较简单的Alpha Test


在Vertex & Fragment Shader里,要实现它非常简单。


一种方法是自己在shader中编写代码,只要使用类似下面的语句就可以了:

  // alpha test
  clip (o.Alpha - _Cutoff);

clip函数非常简单,就是检查它的参数是否小于0。如果是,就调用 discard舍弃该fragment;否则就放过它。


另一种方法是使用固定管线的Alphatest指令。具体可见官方文档使用

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/107687
推荐阅读
相关标签
  

闽ICP备14008679号