Unity模型正反面

        有个很常见的概念——正反面。我们经常使用这个概念,比如Unity的cull命令:

Unity - Manual: ShaderLab command: Cullhttps://docs.unity3d.com/Manual/SL-Cull.html        Unity中的正反面是由顶点顺序(winding order)决定的,Mesh的每个顶点都有一个索引,三角形包含三个顶点的索引。按照索引从大到小遍历,会产生两种情况:如果Mesh的顶点顺序是顺时针,就认为是正面;如果Mesh的顶点顺序是逆时针,就认为是反面。

         如上图,左侧三角面顶点分别是012,遍历顺序逆时针为反面。右侧三角面顶点分别是021,遍历顺序顺时针为正面。

单个面片

        Unity默认的剔除方式为Cull Back,也就是剔除背面,所以你会发现在默认情况下创建的Quad,必然有一面是可见一面不可见,就是背面被剔除。

       有时我们想要做双面渲染,比如渲染树叶这种单个面片,此时必须把Cull Mode设置为Cull Off。另外有一个值得关注的Shader参数是VFace,标识当前渲染的是模型的正面还是反面。

Unity - Manual: Shader semanticshttps://docs.unity3d.com/Manual/SL-ShaderSemantics.html

VFACE

A fragment shader can receive a variable that indicates whether the rendered surface is facing the camera, or facing away from the camera. This is useful when rendering geometry that should be visible from both sides – often used on leaves and similar thin objects. The VFACE semantic input variable will contain a positive value for front-facing triangles, and a negative value for back-facing ones.

        需要注意的是,在单个面片的情况下,模型的正反面是由模型本身决定的,与视角无关。

封闭模型

        实际上更多遇到的是非单个面片的情况,此时模型是封闭的。比如一个立方体,此时在立方体外侧看无论哪个面片都是正面,因为面片的背面在立方体里面隐藏了。但是要特别注意,此时我们说的背面不是单个面片的背面,而是不可见的外侧面(外侧和内侧是相对模型中心而言的,下同)。

         比如上面的立方体,我们能见到的只有三个外侧面,另外背部的三个外侧面就是我们说的背面。为什么要这么定义呢?因为在封闭模型的前提下,单个面片的背面永远不可见,讨论单个面片的背面是没有意义的。所以此时我们说的背面剔除就是指剔除背部的三个外侧面。

        此时的VFACE的取值也变了,可见的三个外侧面值大于0,背部的三个外侧面值小于0。此时VFACE是和视角有关的,当我们旋转视角时,每个面的正反也会发生变化。如果我们使用Cull Off或者Cull Back,那么能看到的只有正面;如果我们使用Cull Front,能看到的只有背面(实际上是背面的内侧面)。

Depth Peeling

        最后提一下深度剥离,深度剥离是一个N pass的渲染过程,每次渲染透明物体的“前面”。

        每个Pass都开启ZWrite,每次将当前面的深度写入到深度缓存,用于下一次的深度测试。

        最关键的是,整个过程都保持Cull Off,不进行任何背面/正面裁剪,这是因为此时背面/正面不再是由模型顶点顺序或者视角决定的,而是深度决定的“前面”和“后面”。举个例子,在上面的示例图中,从左到右只有第一幅图是Cull Back,后面的Passes是既不是Cull Back也不是Cull Front,而是在开启ZTest的前提下,根据当前片元的深度使用Clip函数做手动裁剪。

参考资料:

Creating a Mesh

次序无关的半透明渲染实现 - 知乎 

猜你喜欢

转载自blog.csdn.net/paserity/article/details/130118964