半透模型内部的深度显示问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zzxiang1985/article/details/50815201
在写半透shader时,我们一般会关闭ZWrite,以免离摄像机近的半透物体会遮挡离摄像机远的半透物体,导致后者完全显示不出来。(如果不理解为何会有这个现象,需要先学习深度缓存、ZWrite和ZTest的概念。)

但是有一次我们在立方体(Cube)上应用一个关闭了ZWrite的半透shader时,却遇到了问题。请看下面的立方体:



注意红框框住的那片花纹。它位于4号面上。4号面比1号面离摄像机更远,被1号面挡住。在上面这幅图中,我们透过1号面的镂空看到了4号面上的这片花纹。

下面把立方体转动一下,让1号面上的花纹挡住红框里的那片花纹。



然而从上图可见,花纹并没有被挡住,并没有因为位于1号面的花纹后面而有所衰减。

这倒也并不奇怪。因为ZWrite被关闭的缘故,立方体各顶点的深度并未写进深度缓存中,而各顶点相互之间的渲染次序又是未知的。 假如红框里的花纹在1号面之后渲染,那就会出现上图的情况,反而是4号面上红框里的花纹把1号面挡住了。

但是把ZWrite打开是行不通的,否则就会出现下图的情况——3、4、5号面因为被1、2、6号面遮挡而被裁减,完全显示不出来了:



后来想出一个办法。因为在这个角度下我们看到的3、4、5号面是它们的背面,所以我们可以控制好渲染顺序,让shader先渲染背面,再渲染正面。因此我为原有的Shader多加了一道Pass。新加的Pass和原有的Pass(原Shader只有一道Pass)一模一样,只是第一道Pass设置Cull Front,只渲染背面,第二道Pass设置Cull Back,只渲染正面,这样渲染结果就是对的了:



不过这个方法利用的是立方体的造型特点,也就是被遮挡的面一定以背面朝向摄像机,因此也有一定局限性。假如遇到一些比较复杂的模型(比如沙漏状的模型),这个方法就失效了。不过从本质上讲,对于半透模型来说,关键是控制渲染顺序。在更复杂的情况下就要摸索别的办法来控制渲染顺序了。
阅读更多

没有更多推荐了,返回首页