一、闲话不多扯,先摘几条官方手册关于深度测试的说明:
1、ZWrite(On/Off)
Controls whether pixels from this object are written to the depth buffer (default is On). If you’re drawng solid objects, leave this on. If you’re drawing semitransparent effects, switch to ZWrite Off.
译:深度缓存控制指令,控制这个物体上的像素是否写到深度缓存区内(默认为On,开启)。如果你在绘制实心物体,就保持其默认的开启值即可。如果你想绘制的是半透明的效果,那么就将Zwrite的值设为Off,即关闭深度缓存写。
2、Ztest(ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
How should depth testing be performed. Default is LEqual (draw objects in from or at the distance as existing objects; hide objects behind them).
译:决定了深度测试如何进行,默认值为LEqual(即绘制距离相机更近的物体,即如果正在绘制的物体离摄像机更近,那么已经存在的后面的物体将会被遮挡住)
3、Offset(Offset Factor, Units)
Allows you specify a depth offset with two parameters. factor and units. Factor scales the maximum Z slope, with respect to X or Y of the polygon, and units scale the minimum resolvable depth buffer value. This allows you to force one polygon to be drawn on top of another although they are actually in the same position. For example Offset 0, –1 pulls the polygon closer to the camera ignoring the polygon’s slope, whereas Offset –1, –1 will pull the polygon even closer when looking at a grazing angle.
二、上例子(以做一个水池子为例)
1、搭建场景,用5个cube搭建如下水池子基本结构(不包含水面),5个cube的材质是自己新建的材质球,shader用的是unity的standard标准材质,换了张贴图。
2、制作水面贴图。在PS cs3中随便画了张如下图所示的带有透明通道的图片。
3、将水面贴图导入unity,在场景中新建一个plane作为水面,新建一个材质球,然后新建一个unlit shader,将其赋给新建的材质球,看到如下效果:
4、打开新建的shader,进行改写。考虑到要渲染的是水面这种有透明效果的物体(因为要透明效果,所以要带有alpha通道的贴图),所以在subshader的tags里面应该设置其渲染队列为半透明,渲染类型为半透明即Tags{"Queue"="Transparent" "RenderType"="Transparent" },根据上面的说明,渲染半透明的物体要关闭写缓存,故设置 ZWrite Off。这时候返回unity中会发现其实并没有什么变化,那是因为前面的设置并没有利用到透明通道,即其实还是把他们当做实心物体渲染的,故会有遮挡。此时再在subshader里加上 Blend SrcAlpha OneMinusSrcAlpha,即可发现水面神奇的就变成透明的,可以看到水池底了!如下图:
5、扩展之一:让水面动起来
再在新建的shader中继续修改,将顶点着色器中的下面这句:o.uv = TRANSFORM_TEX(v.uv, _MainTex);
改成o.uv = TRANSFORM_TEX(v.uv, _MainTex)+float2(sin(6.28*_Time.x),0);保存并返回unity运行会发现水面有周期的左右移动了。
6、扩展之二:改变某些设置指令
(1)将上面修改过后的Tags里的两个设置项去掉,会发现对结果并没有什么影响太大的影响,但是在某些角度下会出现一些怪异的缺少面等的结果。查阅官网手册看到渲染队列中的Queue的默认值为geometry,即为一般的不透明物体的渲染队列(原文:Geometry
(default) - this is used for most objects. Opaque geometry uses this queue.)由于按照不透明物体进行渲染,混合方式不变,故影响不是很大。
(2)开启ZWrite。开启后若不设置ZTest,默认为LEqual,此时是没有太大的影响的,但是如果将ZTest设置为Greater,就会发现有很大的变化,如下图
出现上图所示的效果的原因如下:由于开启了ZWrite,且设置的是同一像素点上远离相机的物体会被渲染,所以会出现上图的效果,那么问题是,为什么上图还会有水呢?中间区域没有水好理解,周边的水就难理解了。周边的水和池子共三层,即两层池子实体中间夹杂一层水,那为什么只渲染出中间的水呢?我的猜想是:因为先渲染的水池的实体,深度缓存中保存的是最上面的一层的水池实体的深度值,水池实体渲染完成后,再渲染水,水的位置是在两层水池实体中间的,其深度值大于缓冲区的值,所以会通过深度测试,从而被渲染出来。
本文完,有不足及谬误之处,恳请指出,不胜感激!