如何:設計殼層著色器

殼層著色器是三個階段的前三個階段,可一起實作 鑲嵌 (其他兩個階段是鑲嵌器和網域著色器) 。 本主題說明如何設計殼層著色器。

殼層著色器需要兩個函式,主要殼層著色器和修補程式常數函式。 殼層著色器會在每個控制點上實作計算;殼層著色器也會呼叫修補程式常數函式,以在每個修補程式上實作計算。

設計殼層著色器之後,請參閱 如何:建立殼層著色器 ,以瞭解如何建立殼層著色器。

設計殼層著色器

  1. 定義殼層著色器輸入控制項和輸出控制點。

    // 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;
    };
    
  2. 定義輸出修補常數資料。

    // 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 個邊緣鑲嵌因數, (來鑲嵌邊緣) ,因為固定函數鑲嵌器必須知道要鑲嵌多少。 三角形和 isoline 定義域的必要輸出不同。

    固定函數鑲嵌器不會查看任何其他殼層著色器輸出,例如其他修補程式常數資料或任何控制點。 定義域著色器 -- 針對固定函式鑲嵌器產生的每個點叫用的網域著色器,將會看到其輸入所有殼層著色器的輸出控制點和所有輸出修補常數資料;著色器會在其位置評估修補程式。

  3. 定義修補程式常數函式。 修補程式常數函式會針對每個修補程式執行一次,以計算整個修補程式 (之常數的任何資料,而不是在殼面著色器) 中計算的個別控制點資料。

    
    #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;
    }
    

    修補程式常數函式的屬性包括:

    • 其中一個輸入會指定包含修補程式識別碼的變數,並由 SV_PrimitiveID 系統值識別, (在著色器模型 4) 中查看 語意
    • 其中一個輸入參數是輸入控制點,在此範例中 宣告 VS_CONTROL_POINT_OUTPUT。 修補程式函式可以看到每個修補程式的所有輸入控制點,在此範例中每個修補程式有 32 個控制點。
    • 函式至少必須針對以 SV_TessFactor識別的鑲嵌器階段計算每個修補程式鑲嵌因數。 四個網域需要四個邊緣鑲嵌因數,而兩個額外的因素 (由 SV_InsideTessFactor 識別,) 以鑲嵌修補程式內部。 固定函數鑲嵌器不會查看任何其他殼層著色器輸出, (例如修補常數資料或任何控制點) 。
    • 輸出通常是由 結構定義,並由此範例中的 HS_CONSTANT_DATA_OUTPUT 加以識別;結構取決於定義欄位型別,而且三角形或 isoline 定義域會有所不同。

    另一方面,會針對固定函式鑲嵌器產生的每個點叫用定義域著色器,而且必須查看輸出控制點和輸出修補程式常數資料, (兩者都從殼層著色器) 評估其位置的修補程式。

  4. 定義殼層著色器。 殼層著色器會識別修補程式的屬性,包括修補程式常數函式。 每個輸出控制點都會叫用一次殼層著色器。

    [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;
    }
    

    殼層著色器會使用下列屬性:

每個殼層著色器調用都可以看到 VS_CONTROL_POINT_OUTPUT) 識別 的所有輸入控制點 (。 在此範例中,有 32 個輸入控制點。

每個輸出控制點都會叫用一次殼層著色器,每個輸出控制點 (每個 SV_OutputControlPointID) , (以SV_PrimitiveID) 識別。 這個特定著色器的用途是計算輸出 i,此輸出定義為 BEZIER 控制點, (此範例有 16 個輸出控制點,由 outputcontrolpoints) 所定義。

殼層著色器會針對每個修補程式執行一次常式, (修補程式常數函式) 計算修補常數資料, (鑲嵌因數作為最小) 。 另外,殼層著色器會在每個修補程式上 (執行稱為 SubDToBezierConstantsHS) 的修補程式常數函式,以計算鑲嵌器階段的鑲嵌因數等修補常數資料。

如何使用 Direct3D 11

鑲嵌概觀