欢迎光临散文网 会员登陆 & 注册

UnityShader-透明效果

2022-05-30 17:04 作者:YONCE1999  | 我要投稿

在Unity中我们通常用两种方式来实现透明效果,第一种为Alpha Test(透明度测试),第二种为Alpha Blending(透明度混合)。在介绍这两种方式之前我们需要简单了解一下渲染的顺序


深度缓冲(深度测试与深度写入)

当场景中存在很多模型时,我们并不需要考虑先渲染A或者B或者C,渲染的顺序并不会影响最终的渲染结果,正是因为深度缓冲的作用,它的基本思想是根据深度缓存中的值来判断该片元距离摄像机的距离,当渲染一个片元时,需要把他的深度值和已经存于深度缓冲中的值进行比较(开启了深度测试的前提),如果它的值距离摄像机更远,则说明有物体挡住了它不需要渲染到屏幕上,否则就覆盖此时颜色缓冲当中的像素值,并且更新到深度缓冲中(深度写入)但是如果要实现透明效果,尤其是透明度混合时,将会关闭深度写入。

    透明度测试

        当一个片元的透明度不满足条件时(例如小于某个阈值),则舍弃这个片元,这种方法产生的效果非常极端,要么完全透明,要么完全不透明。

    透明度混合

        可以得到真正的半透明效果,使用当前片元的透明度作为混合因子,和已经存在颜色缓冲中的颜色值进行混合得到新的颜色。但是透明度混合需要关闭深度写入,如果不关闭深度写入,则会出现当半透明物体挡在不透明物体前时,由于没有关闭深度写入而将半透明物体的深度值写入,不透明物体深度测试时,会认为自己不需要被渲染,那么就会出现半透明物体完全挡住了不透明物体的奇怪现象。在这种情况下,渲染的顺序就十分重要了。

渲染引擎一般都会对物体进行排序之后再渲染,常用的方法是:

  1. 先渲染所有的不透明物体,并开启它们的深度测试和深度写入。

  2. 把半透明物体按他们的距离摄像机的远近排序,按照从后往前的顺序渲染这些半透明物体,并且开启深度测试,关闭深度写入。

    同样的半通明物体从前往后的顺序也存在一定问题,通常情况下,我们默认物体A全部都在B前面或者全部都在B后面,但是不可避免的会出现物体AB交错的情况,部分在前,部分在后,这个时候我们可以选择把物体拆分为两个部分在进行正确的排序。

透明度测试

大致部分与之前漫发射纹理差不多,其中Cutoff系数作为控制透明度的阈值,纹理上小于Cufoff的片元将被直接舍弃,使用的Cilp方法。

效果图

透明度混合

当然,由于上述的关闭深度写入带来的各种问题,当模型本身具有复杂的遮挡关系就会因为各种排序错误而产生错误的透明效果。如图

接下来我们将会实现开启深度写入的半透明效果,其中一种解决办法为,使用两个Pass来渲染模型,第一个Pass开启深度写入,但不输出颜色,第二个Pass进行正常的透明度混合。缺点为多一个Pass会对性能造成一定的影响。

双面渲染的透明效果

单面透明

如果一个物体是透明的,意味着我们不仅可以透过他看到其他物体,当然也可以看到这个物体的内部结构,在之前的实现的透明效果中,我们都无法观察到正方体的内部结构,导致物体看起来好像只有半个,原因是因为渲染引擎默认剔除了物体背面的渲染图元,如果我们想要得到双面的渲染效果,可以使用Cull指令来控制剔除那个面的渲染图元

Cull Back|Front|Off   分别表示剔除背面,剔除正面,全部渲染


例如在之前透明度测试的代码中,我们可以在Pass中加入Cull Off就能得到双面渲染的结果

然而透明度混合中实现双面渲染会跟更复杂一些,还是因为我们关闭了深度写入,我们希望渲染顺序是从后往前渲染,关闭深度写入导致无法通过按逐像素的力度进行深度排序,因此为了保证同一物体的背面图元先渲染,我们将双面渲染的Pass分为两个,第一个只渲染背面,第二个只渲染正面,因为渲染时会依次执行Subshader中的Pass,就保证了背面总是在正面之前被渲染。代码如下

效果图



本节学习成果


UnityShader-透明效果的评论 (共 条)

分享到微博请遵守国家法律