入门图形学:渲染队列

     请提前查看之前的相关博客:透明原理

     要是了解三维图形学中透明原理,也大致知道引擎处理场景渲染是先处理不透明渲染,然后处理透明渲染,根据透明渲染的对象的深度值进行AlphaTest或者AlphaBlend,这种处理也比较符合真实世界的实际情况。但是在三维图形场景中,并不一定是那么的符合真实世界,如以下问题:

      1.如果美术创建场景的时候将两面墙壁网格贴近,导致他们在视口区域中拥有相同的深度值怎么办?那么引擎到底是显示A墙还是B墙?或者一帧显示A墙一帧显示B墙,这个问题也被称为Zfighting,是一个很常见的问题,解决方法可以将AB墙网格间隔增大,也可以减小视口区域Far/Near距离以提高depth的差异。

      2.玩过吃鸡嘛?神仙多吧,典型的就是透视挂,直接将人物隔着墙体/山体等显示出来,这个功能要怎么实现呢(毕竟有的游戏中这个功能还是玩法之一)?

      这些都是不同于现实世界的渲染情况,所以渲染队列这个概率就显得很重要,首先我们看看unity官方的文档,如下:

      入门图形学:渲染队列_第1张图片

      决定了对象的渲染顺序,比如RenderQueue标记为Transparent的物体比Geometry的物体后渲染,表现效果上就是Transparent叠在Geometry前面了,我们先做个实验,如下:

      假设有两面墙壁网格AB,坐标相同,也就是说在视口区域depth相同。我们给A的RenderQueue设置为Geometry,B设置为Transparent,表现效果为如下:

       入门图形学:渲染队列_第2张图片

       

       事实上,shaderGUI面板也可以直接设置值,,可以看出来Geometry默认数值为2000,Transparent为3000,当然上面提到的6个渲染队列标签都有各自的数值,具体如下:

       默认下,shaderGUI面板抛出了常用的队列选项,如下:

       入门图形学:渲染队列_第3张图片

      常用的Geometry=2000/AlphaTest=2450/Transparent=3000/FromShader就是shader中写好的 = 1000,“overlay”=4000。

      当然了,同学们可以试一下,哪怕Queue相差数值为1也会区分渲染顺序,顺序就是Queue越小,越先渲染,先渲染好Queue小的物体,那么Queue大的物体覆盖已经渲染好的Queue小物体的,表现效果就是Queue大的物体在Queue小的物体“前面”,符合引擎渲染实际情况。

      接下来我们拖拽一下Transparent Queue的面片B,让面片B距离摄像机比面片A更远。会发现,就算面片B的Queue更大,也不会渲染到面片A的“前面”,如下图:

      入门图形学:渲染队列_第4张图片

      这是因为深度测试ZTest的优先级是高于RenderQueue的,也就是说,ZTest深度测试决定要丢弃B的片段,因为B的片段depth比A的片段depth大,距离相机更远,则丢弃。所以我们可以在B的shader中关闭深度测试,让ZTest失效,则优先级其次的RenderQueue开始起作用,B就渲染到了A的“前面”,如下图:

      

      亦或者将A的shader的ZWrite off掉,这样的话,深度缓冲区的深度就没有记录A的深度,所以B就算不关闭ZTest,也可以顺利的深度测试通过,渲染到A的“前面”,如下图:

      

      最终都能达到所谓的“透视挂”效果,如图:

      入门图形学:渲染队列_第5张图片

     当然了ZTest函数也有如下提供的比较方法,如下:

     入门图形学:渲染队列_第6张图片

         通过上面的比较函数我们也能发现一些事情,比如我们只关注面片A,让ZTest Greater,那么意思就是当前A的片段的depth如果比深度缓冲区depth大则深度测试通过,则渲染片段。测试发现面片A不论处于任何Z值都不会被渲染,意味着深度缓冲区默认的depth值为最大(或者说大于等于1)。同时视口区域中的物体,也就是depth值处于[-1,1]区间的物体,是必须比深度缓冲区默认depth值更小的,所以无论如何A的片段都不会测试通过被渲染,如下图:

         

         入门图形学:渲染队列_第7张图片

         如果我们写ZTest Less或者使用默认的ZTest就可以正常渲染,同时我们将面片B的shader的ZTest Greater,那么意味着,当面片B的depth比面片A更大(也就是面片B距离视口比面片A距离视口更远)则测试通过渲染,当然如果更小则测试失败丢弃,和现实中实际渲染情况则正好相反,如下图:

         

         入门图形学:渲染队列_第8张图片

         这个也是“透视挂”的原理,直接修改着色器文本文件的ZTest和RenderQueue就可以达到透视的效果。

         下面对三维图形的渲染顺序进行总结:

         1.深度测试为第一优先级,深度测试通过的片段被渲染,失败则丢弃,同时深度测试允许我们开发者进行测试函数选择和使用,所以可以自由控制深度测试。

         2.渲染队列为第二优先级,当深度测试通过以后,再使用RenderQueue的数值决定是否渲染。

         同学们还可以根据这两个结论进行其他方法的验证,比如设置面片B的ZTest Greater,但是设置面片B的RenderQueue小于面片A,那么会出现就算是ZTest跟随Z值运动Greater测试通过了,也会因为RenderQueue小于A不被渲染。

         所以说一个物体是否会被渲染以及其渲染顺序是根据ZTest和RenderQueue共同作用的结果。

         

你可能感兴趣的:(入门图形学之图形学理论)