Unity*物理材质的制作之曲面细分

时间:2022-09-10 17:01:28

曲面细分(Tessellation)已经不是一个陌生的名词,从DX10时代的Geometry Shading演变而来的线性插值细分顶点,被微软的图形工程师认为是“掀起业界风暴的图形优化技术”,通过线性插值在两顶点相连的线中中插入数个顶点,将一个网格模型的面数瞬间提高到之前的几倍。比起单纯的使用高模,他的效率可以提高几十倍,在对顶点位置的并行处理方面,CPU执行的网格合批效率是无论如何也无法和显卡的流处理器相提并论的,因此,在使用DX11及以上API的大作中,这项技术被大量使用以大幅度提高渲染性能与游戏画面。

在一个复杂的场景中,许多模型要求拥有光滑或凹凸不平的表面,这时美工需要输出大量的高模,高精度的动态模型(如人物)每一帧都会给CPU带来灾难性的任务量,使用曲面细分可以彻底解决这个问题。Unity已经给我们提供了曲面细分的实现方案,不想深究其原理的开发者可以直接通过编写Surface Shader来实现曲面细分:

https://docs.unity3d.com/Manual/SL-SurfaceShaderTessellation.html

我们这里为了保证最高的显示性能并提供强大的功能,使用了Vertex Hull Domain Fragment Shader, 注意这里的Vertex函数是针对细分前的顶点,Hull函数负责进行顶点的插值细分,而Domain Shader则相当于每个细分后的顶点的Vertex函数,最后的Fragment函数和普通Shader中的Fragment函数无异。执行顺序大致如下:每个模型顶点执行一次Vertex函数,Vertex函数将返回值传入Hull函数,Hull函数与其分支函数负责将传入的一个面片通过添加节点切分为数块,细分后每个顶点(包括原顶点)都会执行一次Domain函数,相当于我们平时写的Vertex函数。

这里使用的Shader工作流程与Standard shader基本一致,都拥有对Albedo, Normal, Specular(Gloss), Occlusion, Detail Albedo, Detail Normal等贴图的支持,同时,在细分曲面方面还有能使表面光滑化的Phong与管理细分顶点位置的Displacement Map:

Unity*物理材质的制作之曲面细分

这个Shader较为复杂,想要深入研究的朋友可以下载自行阅读源码,Shader下载地址:https://pan.baidu.com/s/1eT0zzSu

首先创建一个普通的平面,Shader使用默认的Standard Shader:

Unity*物理材质的制作之曲面细分

Unity默认的平面由100个方形也就是200个三角形组成,从这里看面数非常稀疏,我们希望获得一个点数多且细腻的平面,但是顶点的增多无异会给本来并行能力就弱的CPU雪上加霜,所以这里使用Tessellation Shader:

Unity*物理材质的制作之曲面细分

Shader中已经进行了Editor优化,没有添加的贴图不会被计算,phong值设置为0时同样不会进行外凸计算,这里我们的测试模型实平面,所以可以将Phong设置为0,然后添加各种贴图,并且添加一对碎土贴图用作细节贴图。然后进行细分顶点位置的调整,首先需要调整的是Vertex Scale,通过改变该值可以改变细分贴图对顶点位置的影响,其次调整Vertex Offset以防点位置过高,高于原平面的定点位置可能会导致视锥剔除运算错误,模型在屏幕边缘时会直接消失,这里我们的调整办法是,将Vertex Offset设置为负数,这时顶点的位置应该要等于或略低于默认平面,这样整个模型也不会因此特别臃肿(实际制作不一定如此,需要技术美术人员进行尝试调整以确定最合适的做法),毕竟曲面细分的原则是模拟更多节点,比普通的高模还是要注意很多地方以防止穿帮的。

在本次的Demo中,每两个顶点之间进行了100次细分,也就是说面数数增加了10000倍,简简单单的一张平面就有了200万个面,如果用这种精度的模型,在一个较为复杂的室内场景中,已经会出现极其严重的卡顿甚至直接幻灯片了,而这里的材质渲染耗时与无细分的PBR Shader相差无几,由此可见曲面细分技术可以给显示性能带来革命性的提高与优化。