DirectX 12 曲面细分—外壳着色器

曲面细分阶段

曲面细分共包括三个阶段外壳着色器阶段HS、镶嵌化阶段tessellator、域着色器阶段DS,它们夹在顶点着色器阶段和几何着色器阶段之间,如图,下图中的细分着色器就是曲面细分阶段,它包括上面三个着色器按顺序流水进行:

渲染流水线
如果启用了曲面细分阶段,在AI(输入装配)阶段则可以提交具有若干控制点(control point)的面片(patch),D3D12支持具有1~32个控制点的面片。启动了曲面细分就需要使用新的图元拓扑类型了(下面包含了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_4_CONTROL_POINT_PATCHLIST = 36,
.
.
.
D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST = 63,
D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64,

开启曲面细分后,顶点着色器可以用来处理控制点;

曲面细分第一个阶段外壳着色器

  1. 常量外壳着色器
  2. 控制点外壳着色器

常量外壳着色器会对每个面片进行一次处理(即每个面片都会调用一次),最后再输出网格的曲面细分因子,曲面细分因子指示了再曲面细分阶段下的镶嵌处理后的份数,常量外壳着色器对面片进行的是分段,控制点外壳着色器对面片进行的是面片的弧度变化的细分。

struct PatchTess
{
float EdgeTess[4] : SV_TessFactor;
float InsideTess[2] : SV_InsideTessFactor;
// 可以在下面为每个面片附加所需的额外信息
};
PatchTess ConstantHS(InputPatch<VertexOut, 4> patch,
uint patchID : SV_PrimitiveID)
{
PatchTess pt;
// Uniformly tessellate the patch 3 times.
pt.EdgeTess[0] = 3; // 四边形面片的左侧边缘
pt.EdgeTess[1] = 3; // 四边形面片的上侧边缘
pt.EdgeTess[2] = 3; // 四边形面片的右侧边缘
pt.EdgeTess[3] = 3; // 四边形面片的下侧边缘
pt.InsideTess[0] = 3; // U轴 (四边形内部细分的列数)
pt.InsideTess[1] = 3; // V轴 (四边形内部细分的行数)
return pt;
}

上面代码中SV_TessFactor和SV_InsideTessFactor表示了几何图形边缘和内部的细分份数,常量外壳着色器输入了四边形的四个控制点以及图元ID号,InputPatch<VertexOut, 4>指定了控制点的数量与类型VertexOut是由顶点着色器控制输出的控制点类型(前面提到了,开启曲面细分后顶点着色器就用来对控制点进行操作),常量外壳着色器输出的结构体由我们自己定义可以增加额外的数据,域着色器接受来自常量外壳着色器的数据作为输入,再域着色器中可以使用这些额外的数据。镶嵌化处理过程中会根据四个边缘曲面细分因子和两个内部曲面细分因子进行镶嵌画处理。(四边形镶嵌化过程中使用了四个边缘曲面细分因子和两个内部曲面细分因子,三角形面片则使用3个边缘曲面细分因子和一个内部曲面细分因子)。

控制点外壳着色器会对每个控制点进行一次处理(即类似于顶点着色器中的对每个点调用一次),输入三个控制点(三角面片),则可以在控制点外壳着色器中增加几个控制点改变曲面的表达形式让曲面更加细致,控制点对面片的控制类似于PS中的钢笔锚点,可以改变面片的形状,比如将三个控制点转换成十个控制点我们就可以的到3次贝塞尔三角面片了,常量外壳着色器对面片进行的是分段,控制点外壳着色器对面片进行的是面片的弧度变化的细分。

struct HullOut
{
	float3 PosL : POSITION;
};
[domain(“quad”)]
[partitioning(“integer”)]
[outputtopology(“triangle_cw”)]
[outputcontrolpoints(4)]
[patchconstantfunc(“ConstantHS”)]
[maxtessfactor(64.0f)]
HullOut HS(InputPatch<VertexOut, 4> p,
uint i : SV_OutputControlPointID,
uint patchId : SV_PrimitiveID)
{
	HullOut hout;
	hout.PosL = p[i].PosL;
	return hout;
}

先说说参数吧,InputPatch<VertexOut, 4>常量外壳着色器中已经说明,SV_OutputControlPointID语义标记的表示当前正在处理的控制点的ID号(从0开始),SV_PrimitiveID标记的是该控制点所属的图元拓扑ID,在控制点外壳着色器中输入的控制点的数量可以和输出控制点的数量不一致。

各种属性的一些含义:

  1. domain:面片的类型可以为tri (三角形面片)、quad (四边形面片)、isoline (等值线)。
  2. partitioning:制定了曲面细分的细分模式。
    • integer,新的控制点/顶点的添加或移除只与曲面细分因子的整数部分有关,会忽略小数部分,所以如果使用了LOD技术时可能造成模型的突跃/突变。
    • fractional_odd或者fractional_even,细分等级会渐变,顶点会逐渐移动直到消失,而不会突然pop出来或者消失。
    • pow2,pow2因子,曲面细分因子的值为2的次方。
  3. outputtopology:通过细分所创的三角形的绕序
    • triangle_cw,顺时针方向的绕序
    • triangle_ccw,逆时针方向的绕序
    • line,针对线段曲面细分
    • point,针对点曲面细分(微软官方给出的,点怎么细分???)
  4. outputcontrolpoints:输出控制点的数量,也就是HS的执行次数,系统值SV_OutputControlPointID给出的索引标明了当前正在输出的控制点。
  5. patchconstantfunc:指定常量外壳着色器函数的名称。
  6. maxtessfactor:最大细分数量,即所用曲面细分因子的最大值,告知GPU后显卡驱动会做出相应的优化,DirectX 11硬件最大支持64,DirectX12也是64。

未经允许不得转载:他日重逢 » DirectX 12 曲面细分—外壳着色器

赞 (1) 打赏

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

隐藏
变装