曲面细分是Direct3D 11带来的其中一项重要的新功能。它引入了两个可编程着色器阶段以及一个固定的镶嵌处理过程。简单来说,曲面细分技术可以将几何体细分为更小的三角形,并以某种方式把这些新生成的顶点偏移到合适的位置,从而以增加三角形数量的方式丰富网格细节。但为什么不在创建网格之初就直接赋予它高模(high-poly,高面数多边形)的细节呢?以下是使用曲面细分的3个理由:
基于GPU实现动态LOD(Level of Detail,细节级别)。可以根据网格与摄像机的距离或依据其他因素来调整其细节。比如说,若网格离摄像机过远,则按高模的规格对它进行渲染将是一种浪费,因为在那个距离我们根本看不清网格的所有细节。随着物体与摄像机之间距离的拉紧,我们就能连续地对它镶嵌细分,以增加物体的细节。
物理模拟与动画特效。我们可以在低模(low-poly,低面数多边形)网格上执行物理模拟与动画特效的相关计算,再以镶嵌画处理手段来获取细节上更加丰富的网格。这种降低物理模拟与动画特效计算量的做法能够节省不少的计算资源。
节约内存。我们可以在各种存储器(磁盘、RAM、VRAM)中保存低模网格,再根据需求用GPU动态地对网格进行镶嵌细分。
曲面细分技术涉及到的三个阶段都是可选的,但如果要使用曲面细分,这三个阶段都是必须要经历的。
学习目标:
了解曲面细分所用的面片图元类型。
理解曲面细分阶段中的每个步骤都做了什么,它们所需的输入及输出又分别是哪种数据
通过编写外壳着色器与域着色器程序来对几何图形进行镶嵌化细分
熟悉不同的细分策略,以便于在镶嵌化处理的时候选择出最适当的方案。除此之外,还需要了解硬件曲面细分的性能
学习贝塞尔曲线与贝塞尔曲面的数学描述,并在曲面细分阶段将它们予以实现
DirectX11 With Windows SDK完整目录
Github项目源码
欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。
曲面细分的图元类型在进行曲面细分时,我们并不向IA(输入装配)阶段提交三角形,而是提交具有若干控制点的面片。Direct3D支持具有1~32个控制点的面片,并以下列图元类型进行描述:
D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST = 33, D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST = 34, D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST = 35, ... D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST = 63, D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64,由于可以将三角形看作是拥有3个控制点的三角形面片(D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST),所以我们依然可以提交需要镶嵌化处理的普通三角形网格。对于简单的四边形面片而言,则只需要提交4个控制点的面片(D3D_PRIMITIVE_4_CONTROL_POINT_PATCH)即可。这些面片最终也会在曲面细分阶段经过镶嵌化处理而分解为多个三角形。
注意:D3D_PRIMITIVE_TOPOLOGY枚举项描述输入装配阶段中的顶点类型,而D3D_PRIMITIVE枚举项则描述的是外壳着色器的输入图元类型。
那么,具有更多控制点的面片又有什么用处呢?控制点的概念来自于特定种类数学角度上特定曲线或曲面的构造过程。如果在类似于Adobe Illustrator这样的绘图程序中使用过贝塞尔曲线工具,那读者一定会知道要通过控制点才能描绘出曲线形状。在数学上,可以利用贝塞尔曲线来生成贝塞尔曲面。举个例子,我们可以用9个控制点或16个控制点来创建一个贝塞尔四边形面片,所用的控制点越多,我们对面片形状的控制也就越随心所欲。因此,这一切图元控制类型都是为了给这些不同种类的曲线、曲面的绘制提供支持。
曲面细分与顶点着色器在我们向渲染管线提交了面片的控制点后,它们就会被推送至顶点着色器。这样一来,在开始曲面细分的时候,顶点着色器就彻底沦为“处理控制点的着色器”。正因为如此,我们还能在曲面细分开始之前,对控制点进行一些调整。一般来说,动画与物理模拟的计算工作都会在对几何体进行镶嵌化处理之前的顶点着色器中以较低的频次进行(镶嵌化处理之后,顶点增多,处理的频次也将随之增加)。
外壳着色器外壳着色器是由两种着色器共同组成的:常量外壳着色器(Constant Hull Shader)和控制点外壳着色器(Control Point Hull Shader)
常量外壳着色器