细分着色器分为三个部分:
Hull Shader Stage(外壳着色器阶段)
Tesselation Stage(细分阶段)
Domain Shader State(域着色器阶段)
Hull Shader Stage:
Constant Hull Shader
Control Point Hull Shader
Constant Hull Shader : 在该阶段需要确定一些细分因子
如细分三角形时,输出结构体为:
struct PatchTess
{
float EdgeTess[3] : SV_TessFactor;
float InsideTess : SV_InsideTessFactor;
//其他数据
}
SV_TessFactor字段用于指定如何细分边(边细分分多少部分)
由于三角形有三条边,所以需要三个SV_TessFactor字段的元素用于分别指定三条边的细分因子
SV_InsideTess是用于指定如何细分图元片
Control Point Hull Shader:
输出控制点的个数为多少,该着色器就执行多少次
形式如下:
// 输入控制点
struct VS_CONTROL_POINT_OUTPUT
{
float3 vPosition : WORLDPOS;
// TODO: 更改/添加其他资料
};
// 输出控制点
struct HS_CONTROL_POINT_OUTPUT
{
float3 vPosition : WORLDPOS;
}:
//输出修补程序常量数据
struct HS_CONSTANT_DATA_OUTPUT
{
float EdgeTessFactor[3] : SV_TessFactor; //例如,对于四象域,将为[4]
float InsideTessFactor : SV_InsideTessFactor; //例如,对于四象域,将为Inside[2]
// TODO: 更改/添加其他资料
};
#define NUM_CONTROL_POINTS 3
//修补程序常量函数
HS_CONTANT_DATA_OUTPUT CalcHSPatchConstants(
InputPatch<VS_CONTROL_POINT_OUTPUT , NUM_CONTROL_POINTS> ip , uint PatchID : SV_PrimitiveID)
{
HS_CONSTANT_DATA_OUTPUT Output;
//在此处插入代码以计算输出
Output.EdgeTessFactor[0] = Output.EdgeTessFactor[1] = Output.EdgeTessFactor[2] = Output.InsideTessFactor = 15; //例如,可改为计算动态分割因子
return Output;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("CalcHSPatchConstants")]
HS_CONTROL_POINT_OUTPUT main(
InputPatch<VS_CONTROL_POINT_OUTPUT , NUM_CONTROL_POINTS> ip ,
uint i : SV_OutputControlPointID ,
uint PatchID : SV_PrimitiveID )
{
HS_CONTROL_POINT_OUTPUT Output;
//在此处插入代码以计算输出
Output.vPosition = ip[i].vPosition;
return Output;
}
[domain("tri")]指定图元类型为三角形
[partitioning("fractional_odd")]指定细分模式
[outputtopology("triangle_cw")]指定图元拓扑结构为顺时针三角形
[outputcontrolpoints(3)]指定输出控制点个数,也决定了该函数将执行几次
[patchconstantfunc("CalcHSPatchConstants")]指定patch constant函数
Tesselation State:
该阶段由硬件完成,该阶段将会根据Constant Hull Shader Stage输出的SV_TessFactor,SV_InsideTessFactor对图元进行细分
Domain Shader
Tesselation Stage完成后输出所有新创建的顶点和三角形,该阶段就像是这些输出的顶点的顶点着色器