Unity中实现透明效果通过透明度测试和透明度混合
深度缓冲用于解决可见性问题,决定哪个物体那些部分被渲染在前面,哪些物体被遮挡。使用深度缓冲可以不用关心不透明物体的渲染顺序,但若想实现透明效果,此时关闭了深度写入ZWrite。
透明度测试:霸道机制。片元透明度不满足条件,通常小于某个阈值,则其对应的片元将舍去。透明度测试不需要关闭深度写入,它和其他不透明物体最大的不同是它会根据透明度舍弃片元。结果极端,要么完全透明看不到,要么完全不透明。
透明度混合:得到真正的半透明效果。使用当前片元透明度作为混合因子与已经存储在颜色缓冲中的颜色进行混合得到新的颜色。但是透明度混合需要关闭深度写入,必须小心物体的渲染顺序。深度缓冲只读。
1、渲染顺序
半透明物体背后可以被看到,但开启的话会被直接剔除,但关闭的话会破坏深度缓冲的工作机制。
EG:
A-半透明物体开启颜色写入,关闭深度写入 B-不透明物体,开启写入颜色缓冲和深度缓冲
-若先渲染B再渲染A,B首先会写入颜色缓冲和深度缓冲。随后渲染A,透明物体仍会进行深度测试,发现A比B更近,因此使用A的透明度来与颜色缓冲中B的颜色进行混合
-若先渲染A,深度缓冲中无任何数据,A直接写入颜色缓冲,但对半透明物体关闭深度写入,A不修改深度缓冲。B深度测试时将会认为是第一人而覆盖A的颜色
综上,应该在不透明物体渲染完之后渲染半透明物体
对于均为半透明物体A、B,A在前B在后
-先B后A,B写入颜色缓冲,A将和颜色缓冲中的B颜色进行混合,得到正确的半透明结果
-先A后B,A县写入颜色缓冲,随后B和颜色缓冲中的A混合,结果相反
渲染引擎对于物体的排序方法:
(1)先渲染所有不透明物体,并开启他们的深度测试和深度写入
(2)把半透明物体按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染,并开启深度测试,但关闭深度写入
2、Unity Shader的渲染顺序
渲染队列,SubShader的Queue标签
名称 | 队列索引号 | 描述 |
Background | 1000 | 渲染队列会在其他队列之前被渲染,绘制需要绘制在背景上的物体 |
Geometry | 2000 | 默认的渲染队列,大多数物体可使用这个队列。不透明物体使用这个序列 |
AlphaTest | 2450 | 需要透明度测试的物体。在不透明物体渲染后再渲染这个队列会更高效 |
Transparent | 3000 | 队列中的物体会在所有Geometry和AlphaTest物体渲染后再从后往前的顺序渲染。任何使用了透明度混合(例如关闭了深度写入的Shader)的物体都应使用该队列 |
Overlay | 4000 | 用于实现一些叠加效果。最后渲染的物体。 |
通过透明度测试实现透明效果:
SubShader{
Tags{"Queue" = "AlphaTest"}
Pass{...}
}
通过透明度混合实现透明效果:
SubShader{
Tags{"Queue" = "Transparent"}
Pass{
ZWrite Off
}
}
可写在Pass中,也可写在SubShader中,意味着所有Pass都会关闭深度写入。
3、透明度测试
透明度测试:只要有一个片元的透明度不满足条件,那么其对应的片元将会被舍弃。被舍弃的片元将不再进行任何处理,也不会对颜色缓冲产生任何影响,否则按照普通的不透明物体的处理方式来处理它。
使用clip函数进行透明度测试
如果给定参数的任何一个分量是负数,则舍弃当前像素的输出颜色
Shader "Unity Shaders Book/Chapter8/AlphaTest" {
Properties {
_MyColor ("Color", Color) = (1,1,1,1)
_MyMainTex ("Main Tex", 2D) = "white" {}