Shader模板测试

Created by miccall (转载请注明出处 miccall.tech)

先来展示一下效果

我们先来分析一下这个设计的组成 :

乍一看,好像没啥呀,不就是层级叠加么。

仔细一看,好像不对,图层叠加,做不出这种效果

仔细看一下,中间的主界面,相对于大的背景,肯定是在前面的,那么,主界面内的background呢 ?

第二层 ? 好像不是,因为主界面背面的大背景,没有被它遮住,所以大背景是在第二层,这下问题来了,主界面的background是在第几层呢 ?

其实,这就是今天所说的,模板测试 , 什么是模板测试呢 ?

通俗的讲,就是 当渲染器层级渲染的时候,中间有一个过度区,称为模板缓存区,渲染器要对比每一层中每个像素的模板计数值,当然,这个值也是我们自己指定的,是大还是小啊,还是相等 。

对比方式当然也是我们来选择的。

也许这样说似懂非懂,那我们就来做做看 。

对于图层的叠加,大家应该不会很陌生,在所有设计软件当中,都是一样的:

那对比我们要做的,好像就有思路了,不就是让第一层透视,穿过第二层,直接看到第三层么。这样的话,只要是在第一层的遮罩范围内,我们让第三层显示在里面就行了。

画个图:


相信这样,大家就有所明白了,接下来就讲讲在shader中的用法吧:

在像素的渲染过程中,渲染器的判断方式为:


他的意思是说 假设 A = 参考值与读遮罩值 进行按位与(&)操作

B = 模板缓存得值 与 读遮罩值 进行按位与(&)操作

如果A 与 B 满足一定得关系 ,就显示像素,否则就抛弃像素 。

这个一定的关系,就是比大小咯 :


那我们就来做这个 :

如何让像素抛弃第一层和第二层的,来显示第三层的像素呢?

我们回过头来看看这个公式

referenceValue 值 是由我们自己定义的,readMask先不去管他,忽略即可,stencilBufferValue就是模板缓存区里面的值,这是由渲染器管理的一块地方。

所以我们能做的,就是 referenceValue 和 比较关系 :

首先,我们想,我们要是能让第三层的图像,显示在第一层之上,这样我们的效果就达到了:


我们的渲染流程是 ,渲染第一个图像 , 并且渲染结束之后,把 通过的 Buffer里面的值改为 2

当渲染第二个图像的时候 , 在第一个图像渲染的后面 ,因为buffer已经变为2了,而没有通过的地方,还是0 。

于是,我们比较第二层时,使得 第二层的 模板值 2 != buffer里面的值 ,也就是说 , 之前渲染第一层的地方,第二层时渲染不到的,之前没有渲染1的地方,那么就是第二层渲染上了 。(如图 √ 和 × 表示是否渲染 ,最左边的表示渲染的结果 )

那么开始渲染第三层 ,此时 buffer里面还是 0 与 2 ,我们要让 是 2 的部分渲染出来,而0的部分不渲染 ,我们的比较关系就是 ,大于等于 ,或则说 ,等于也行 。(如图 √ 和 × 表示 )

这样,我们的结果就得到了 :

剩下的细节部分就不在这里累赘了 ,设计师朋友们都知道该怎么做了 ,但是shader的语法还没提到,考虑到大部分人,我就不细深究

    Stencil {
            Ref 2
            Comp GEqual
        }

只要在shader里面加入类似这样的就ok

ref是指定当前的模板值 ,comper是比较 ,唯一一个比较特殊的是第一层:

当通过时,我们替换buffer里面的

            ZWrite off 
            Stencil {
                Ref 2
                Comp Always
                Pass REPLACE
            }

好了 , 就讲这么多了 。

懂模板测试的程序们,实现一下设计效果 ,

会平面设计的美术们,懂了实现方式原理,创造更多的奇观吧 。