如何:设计外壳着色器
外壳着色器是三个阶段中的第一个阶段,它们协同工作以实现 细化 , (另外两个阶段是细化器和域着色器) 。 本主题演示如何设计外壳着色器。
外壳着色器需要两个函数:main外壳着色器,以及补丁常量函数。 外壳着色器在每个控制点上实现计算;外壳着色器还调用补丁常量函数,该函数在每个补丁上实现计算。
设计外壳着色器后,请参阅 如何:创建外壳着色器 ,了解如何创建外壳着色器。
设计外壳着色器
定义外壳着色器输入控制和输出控制点。
// Input control point struct VS_CONTROL_POINT_OUTPUT { float3 vPosition : WORLDPOS; float2 vUV : TEXCOORD0; float3 vTangent : TANGENT; }; // Output control point struct BEZIER_CONTROL_POINT { float3 vPosition : BEZIERPOS; };
定义输出修补常量数据。
// Output patch constant data. struct HS_CONSTANT_DATA_OUTPUT { float Edges[4] : SV_TessFactor; float Inside[2] : SV_InsideTessFactor; float3 vTangent[4] : TANGENT; float2 vUV[4] : TEXCOORD; float3 vTanUCorner[4] : TANUCORNER; float3 vTanVCorner[4] : TANVCORNER; float4 vCWts : TANWEIGHTS; };
对于四边形域, SV_TessFactor 定义 4 个边缘分割因子, (细化) 边缘,因为固定函数细化器需要知道要细化多少。 三角形域和等线域所需的输出不同。
固定函数细化器不查看任何其他外壳着色器输出,例如其他修补常量数据或任何控制点。 域着色器(针对固定函数细化器生成的每个点调用)将视为其输入,即外壳着色器的所有输出控制点和所有输出补丁常量数据;着色器在其位置评估修补程序。
定义修补程序常量函数。 修补常量函数为每个补丁执行一次,以计算整个补丁 (的任何数据,而不是每个控制点数据(在外壳着色器) 中计算)。
#define MAX_POINTS 32 // Patch Constant Function HS_CONSTANT_DATA_OUTPUT SubDToBezierConstantsHS( InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint PatchID : SV_PrimitiveID ) { HS_CONSTANT_DATA_OUTPUT Output; // Insert code to compute Output here return Output; }
修补程序常量函数的属性包括:
- 一个输入指定包含修补程序 ID 的变量,由 SV_PrimitiveID 系统值标识, (在着色器模型 4) 中看到 语义 。
- 一个输入参数是输入控制点,在本示例中 VS_CONTROL_POINT_OUTPUT 中声明。 补丁函数可以查看每个修补程序的所有输入控制点,在此示例中,每个修补程序有 32 个控制点。
- 作为最小值,函数必须计算使用 SV_TessFactor 标识的细化器阶段的每补丁细化因子。 四边形域需要四个边缘分割因子, (SV_InsideTessFactor) 标识的另外两个因素来分割补丁内部。 固定函数细化器不会查看任何其他外壳着色器输出 (,例如修补常量数据或) 的任何控制点。
- 输出通常由 结构定义,在此示例中由 HS_CONSTANT_DATA_OUTPUT 标识;结构取决于域类型,对于三角形或等线域,结构会有所不同。
另一方面,针对固定函数细化器生成的每个点调用域着色器,并且需要从外壳着色器) 查看输出控制点和输出补丁常量数据 (,以评估其位置的补丁。
定义外壳着色器。 外壳着色器标识补丁的属性,包括补丁常量函数。 为每个输出控制点调用一次外壳着色器。
[domain("quad")] [partitioning("integer")] [outputtopology("triangle_cw")] [outputcontrolpoints(16)] [patchconstantfunc("SubDToBezierConstantsHS")] BEZIER_CONTROL_POINT SubDToBezierHS( InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID ) { VS_CONTROL_POINT_OUTPUT Output; // Insert code to compute Output here. return Output; }
外壳着色器使用以下属性:
- 域属性。
- 分区属性。
- 输出拓扑属性。
- outputcontrolpoints 属性。
- patchconstantfunc 属性。 外壳着色器计算输出控制点,在此示例中有 16 个输出贝塞尔控制点。
每个外壳着色器调用都可以看到 (VS_CONTROL_POINT_OUTPUT) 标识的所有输入控制点。 在此示例中,有 32 个输入控制点。
每个输出控制点调用一次外壳着色器, (使用 SV_PrimitiveID) 标识的每个补丁 (SV_OutputControlPointID) 。 此特定着色器的目的是计算输出 i,该输出被定义为 BEZIER 控制点, (此示例具有由 outputcontrolpoints) 定义的 16 个输出控制点。
外壳着色器 (补丁常量函数) 每个补丁运行一次例程,以最小) 计算修补常量数据 (细化因子。 另外,外壳着色器在每个补丁上运行一个名为 SubDToBezierConstantsHS) (修补程序常量函数,以计算修补常量数据,例如细化器阶段的细化因子。
相关主题