1、透视镜效果示例

unity shader mode_游戏开发


场景中创建了三个物体,一个方块、一堵墙、一个球体

然后创建三个材质球、三个初始的shader,将三个shader分别拖给三个材质球

再把材质球拖给三个物体,给这三个物体红色、蓝色、绿色,便于观察

unity shader mode_shader_02


看一下以红色方块为透视镜看过去的效果:

Game视图:

unity shader mode_游戏_03


可以很明显的看到,通过红色方块的区域可以透过墙体看到绿色球体。

2、效果实现
透视效果其实就是通过模板测试来实现,以红色方块为遮罩,给三个shader添加相同模板值,再将球体通过模板测试就可以了。
具体步骤: 打开创建的三个初始shader,找到pass,添加模板测试

//cube.shader  红色方块
 Pass
        {
		Stencil
			{
                Ref 2 //模板值给一个2,三个物体模板值都必须相同
                Comp always//表示在模板测试中总是通过
                Pass replace//作为遮罩物
            }
//wall.shader  蓝色墙体
Pass
        {
			Stencil
			{
                Ref 2 
                Comp NotEqual//不通过模板测试
            }
//sphere.shader  绿色球体
Pass
        {
			Stencil
			{
                Ref 2 
                Comp Equal//通过模板测试
            }

现在来看一下效果:

unity shader mode_游戏_04


你会发现能看见红色方块,不能透它过去看绿色球体,这是因为在模板测试中,方块给的是Comp always,球体给的是Comp Equal,它们两个都会通过模板测试,所以都会写入缓冲区,并且只显示离摄像机更近的物体。

所以我们需要在cube.shader的pass里加一句代码:ZWrite Off

Pass
        {
		Stencil
			{
                Ref 2 //模板值给一个2,三个物体模板值都必须相同
                Comp always
                Pass replace
            }
			ZWrite Off//不写入缓冲区

现在再来看一下效果:

unity shader mode_游戏_05


现在已经实现了透视效果。引发了额外的问题

现在在游戏中直接去看球体时,是看不见的:

unity shader mode_游戏开发_06

这是因为通过了模板测试之后就不会在透视范围以外的缓冲区写入,解决的方法很简单,那就是将它的pass代码复制一份就可以了,也就是一个shader中有两个pass,但是复制的pass代码要将里面的测试模板代码删掉,也就是Stencil代码,这样就能在游戏中直接观察到物体了

unity shader mode_shader_07

3、模板测试原理简述

模板测试可以理解为将缓冲区分为了两个,一个是遮罩物体所在的范围,另一个就是遮罩物体以外的范围,上文例子中的两个范围,如图:

unity shader mode_shader_08


将各种情况总结为一张表格:

在下表中暂且将

遮罩物体所在范围的缓冲区称作:内缓冲区

遮罩物体以外范围的缓冲区称作:外缓冲区

是否作为遮罩物

是否通过模板测试

写入缓冲区情况



会写入内、外缓冲区



不会写入内缓冲区,会写入外缓冲区



会写入内缓冲区,不会写入外缓冲区



不会写入内缓冲区,会写入外缓冲区

利用这些原理就能实现简单透视效果,如果要实现类似X—ray的半透视效果,那就要深入学习渲染队列的控制。
本文就到这儿了,欢迎大家来点评!