例程来自于DXSDK sample——simpleBezier11
-
原始顶点64个,float3格式,分为4个quad(平均每个Quad有16个控制点)
// Control point for a Bezier patch struct BEZIER_CONTROL_POINT { float m_vPosition[3]; }; // Simple Bezier patch for a Mobius strip // 4 patches with 16 control points each const BEZIER_CONTROL_POINT g_MobiusStrip[64] = { { 1.0f, -0.5f, 0.0f }, { 1.0f, -0.5f, 0.5f }, { 0.5f, -0.3536f, 1.354f }, ... }
-
Vert shader很简单,直接输出输入的控制点
-
struct VS_CONTROL_POINT_INPUT { float3 vPosition : POSITION; }; struct VS_CONTROL_POINT_OUTPUT { float3 vPosition : POSITION; }; VS_CONTROL_POINT_OUTPUT BezierVS( VS_CONTROL_POINT_INPUT Input ) { VS_CONTROL_POINT_OUTPUT Output; Output.vPosition = Input.vPosition; return Output; }
-
- Hull shader:主要有两个作用,传输控制点(得到VS传入的控制点,也可在此新生成新控制点);生成domain shader所需参数(SV_TessFactor,SV_InsideTessFactor)。每个Patch运行一次。
(详见:http://msdn.microsoft.com/en-us/library/windows/desktop/ff476339%28v=vs.85%29.aspx)
SV_TessFactor定义
Type | Input Topology |
float[4] | quad patch |
float[3] | tri patch |
float[2] | isoline |
SV_InsideTessFactor定义
Type | Input Topology |
float[2] | quad patch |
float | tri patch |
unused | isoline |
partitioning可以为 integer, fractional_even, fractional_odd, or pow2.用来定义Tesslator scheme
Topology可以为line, triangle_cw, triangle_ccw
struct HS_CONSTANT_DATA_OUTPUT { float Edges[4] : SV_TessFactor; float Inside[2] : SV_InsideTessFactor; }; struct HS_OUTPUT { float3 vPosition : BEZIERPOS; }; [domain("quad")] [partitioning(BEZIER_HS_PARTITION)] [outputtopology("triangle_cw")] [outputcontrolpoints(OUTPUT_PATCH_SIZE)] // HS功能1,输出控制点 [patchconstantfunc("BezierConstantHS")] // 功能2,提供patch constant data给 fixed function tessellator,特别是TessFactor,对不同domain定义不同 HS_OUTPUT BezierHS( InputPatch<VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE> p, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID ) { // VS_CONTROL_POINT_OUTPUT指定控制点的数据格式,INPUT_PATCH_SIZE指定每Patch所有的控制点个数(此为16) HS_OUTPUT Output; Output.vPosition = p[i].vPosition; return Output; } HS_CONSTANT_DATA_OUTPUT BezierConstantHS( InputPatch<VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE> ip, uint PatchID : SV_PrimitiveID ) { HS_CONSTANT_DATA_OUTPUT Output; float TessAmount = g_fTessellationFactor; Output.Edges[0] = Output.Edges[1] = Output.Edges[2] = Output.Edges[3] = TessAmount; Output.Inside[0] = Output.Inside[1] = TessAmount; return Output; }
DomainShader:根据fixed function tessellator输出的UVW,以及hull shader输出的control points,最终生成顶点数据,输出到rasterization pipeline
-
[domain("quad")] DS_OUTPUT BezierDS( HS_CONSTANT_DATA_OUTPUT input, float2 UV : SV_DomainLocation, // 从fixed function tessellator中得到 const OutputPatch<HS_OUTPUT, OUTPUT_PATCH_SIZE> bezpatch ) { // 从hullShader中得到 float4 BasisU = BernsteinBasis( UV.x ); float4 BasisV = BernsteinBasis( UV.y ); float4 dBasisU = dBernsteinBasis( UV.x ); float4 dBasisV = dBernsteinBasis( UV.y ); float3 WorldPos = EvaluateBezier( bezpatch, BasisU, BasisV ); float3 Tangent = EvaluateBezier( bezpatch, dBasisU, BasisV ); float3 BiTangent = EvaluateBezier( bezpatch, BasisU, dBasisV ); float3 Norm = normalize( cross( Tangent, BiTangent ) ); DS_OUTPUT Output; Output.vPosition = mul( float4(WorldPos,1), g_mViewProjection ); Output.vWorldPos = WorldPos; Output.vNormal = Norm; return Output; }
DomainLocation具体含义:Defines the location on the hull of the current domain point being evaluated.