DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation) (4)

程序员无法对镶嵌器这一阶段进行任何控制,因为这一步的操作全权交给硬件处理。此环节会基于常量外壳着色器程序所输出的曲面细分因子,对面片进行镶嵌化处理。

四边形面片的曲面细分示例

integer模式

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

fractional_odd模式:

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

fractional_even模式:

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

三角形面片的曲面细分示例

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

域着色器

镶嵌器阶段会输出新建的所有顶点与三角形,在此阶段所创建的顶点,都会逐一调用域着色器进行后续处理。随着曲面细分功能的开启,顶点着色器便化身为“处理每个控制点的顶点着色器”,而外壳着色器的本质则为“针对已经镶嵌化的面片进行处理的顶点着色器”。特别是,我们可以在此将经过镶嵌化处理的面片顶点投射到齐次裁剪空间。

首先是三角形面片,域着色器以曲面细分因子(还有一些来自常量外壳着色器所输出的每个面片的附加信息)、控制点外壳着色器所输出的所有面片控制点、镶嵌化处理后的顶点位置参数(以重心坐标系(alpha, beta, gamma)的形式表示)作为输入。注意,域着色器给出的并不是镶嵌化处理后的实际顶点位置,而是这些点位于面片域空间内的参数坐标。是否利用这些参数坐标及控制点来求取真正的3D顶点位置,完全取决于用户自己。下面展示了前面的例子显示的三角形所用到的域着色器代码:

struct VertexOut { float3 PosL : POSITION; }; typedef VertexOut HullOut; // Tessellation_Triangle_DS.hlsl [domain("tri")] float4 DS(TriPatchTess patchTess, float3 weights : SV_DomainLocation, const OutputPatch<HullOut, 3> tri) : SV_POSITION { // 重心坐标系插值 float3 pos = tri[0].PosL * weights[0] + tri[1].PosL * weights[1] + tri[2].PosL * weights[2]; return float4(pos, 1.0f); }

将三角形面片以重心坐标系作为输出的原因,很可能是因为贝塞尔三角形面片都是用重心坐标来定义所导致的。

而四边形面片的顶点位置参数以(u, v)的形式表示,前面例子的四边形所用的域着色器代码如下:

struct VertexOut { float3 PosL : POSITION; }; typedef VertexOut HullOut; // Tessellation_Quad_DS.hlsl [domain("quad")] float4 DS(QuadPatchTess patchTess, float2 uv : SV_DomainLocation, const OutputPatch<HullOut, 4> quad) : SV_POSITION { // 双线性插值 float3 v1 = lerp(quad[0].PosL, quad[1].PosL, uv.x); float3 v2 = lerp(quad[2].PosL, quad[3].PosL, uv.x); float3 p = lerp(v1, v2, uv.y); return float4(p, 1.0f); } 贝塞尔曲线(Bézier Curves)

这部分借用GAMES101来说明。并且这里讲的贝塞尔曲线所用的算法是由Pierre Bézier和Paul de Casteljau所提出的。

现在我们先从二阶贝塞尔曲线开始,下面有3个非共线的控制点b0b1b2

DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

接下来我们用线性插值的方式,从b0b1方向的线段使用参数t来确定其中一点,记为\(\mathbf{b_{0}^{1}}\)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgdysg.html