Vorgehensweise: Entwerfen eines Rumpfshaders

Ein Hull-Shader ist die erste von drei Phasen, die zusammenarbeiten, um tessellation zu implementieren (die anderen beiden Phasen sind der Tessellator und ein Domänenshader). In diesem Thema erfahren Sie, wie Sie einen Rumpfshader entwerfen.

Ein Rumpfshader erfordert zwei Funktionen: den Standard Rumpfshader und eine Patchkonstantenfunktion. Der Hull-Shader implementiert Berechnungen für jeden Kontrollpunkt; Der Hull-Shader ruft auch die Patchkonstantenfunktion auf, die Berechnungen für jeden Patch implementiert.

Nachdem Sie einen Rumpfshader entworfen haben, erfahren Sie unter Vorgehensweise: Erstellen eines Hull-Shaders , wie Sie einen Rumpfshader erstellen.

So entwerfen Sie einen Rumpfshader

  1. Definieren Sie die Eingabesteuerung und Ausgabesteuerungspunkte für den Hullshader.

    // 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. Definieren von Ausgabepatchkonstantendaten.

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

    Für eine Quad-Domäne definiert SV_TessFactor vier Edge tessellationsfaktoren (um die Kanten zu tesselieren), da der feste Funktionstesellator wissen muss, wie viel tessellatet werden soll. Die erforderlichen Ausgaben unterscheiden sich für die Dreiecks- und Isoliniendomänen.

    Der feste Funktionstessellator betrachtet keine anderen Hull-Shader-Ausgaben, z. B. andere Patchkonstantendaten oder Kontrollpunkte. Der Domänenshader, der für jeden Punkt aufgerufen wird, den der feste Funktionstessellator generiert, sieht als Eingabe alle Ausgabesteuerungspunkte des Hull-Shaders und alle Ausgabepatchkonstantendaten. der Shader wertet den Patch an seiner Position aus.

  3. Definieren Sie eine Patchkonstantenfunktion. Eine Patchkonstantenfunktion wird einmal für jeden Patch ausgeführt, um alle Daten zu berechnen, die für den gesamten Patch konstant sind (im Gegensatz zu Daten pro Kontrollpunkt, die im Hull-Shader berechnet werden).

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

    Zu den Eigenschaften der Patchkonstantenfunktion gehören:

    • Eine Eingabe gibt eine Variable an, die eine Patch-ID enthält und durch den SV_PrimitiveID Systemwert identifiziert wird (siehe Semantik im Shadermodell 4).
    • Ein Eingabeparameter sind die Eingabesteuerungspunkte, die in VS_CONTROL_POINT_OUTPUT in diesem Beispiel deklariert werden. Eine Patchfunktion kann alle Eingabesteuerungspunkte für jeden Patch anzeigen. In diesem Beispiel gibt es 32 Kontrollpunkte pro Patch.
    • Die Funktion muss mindestens pro Patch Tessellationsfaktoren für die Tessellatorphase berechnen, die mit SV_TessFactor identifiziert werden. Eine Quad-Domäne erfordert vier Tessellationsfaktoren für die Kanten und zwei zusätzliche Faktoren (identifiziert durch SV_InsideTessFactor), um das Innere des Patches zu tessellieren. Der feste Funktionstessellator betrachtet keine anderen Hull-Shader-Ausgaben (z. B. die Patchkonstantendaten oder kontrollpunkte).
    • Die Ausgaben werden in der Regel durch eine -Struktur definiert und durch HS_CONSTANT_DATA_OUTPUT in diesem Beispiel identifiziert. Die Struktur hängt vom Domänentyp ab und unterscheidet sich bei Dreiecks- oder Isoliniendomänen.

    Dagegen wird für jeden Punkt, den der Tessellator für feste Funktionen generiert, ein Domänen-Shader aufgerufen und muss die Ausgabesteuerungspunkte und die Ausgabepatchkonstantendaten (beide vom Hull-Shader) anzeigen, um einen Patch an seiner Position auszuwerten.

  4. Definieren Sie einen Hull-Shader. Ein Hull-Shader identifiziert die Eigenschaften eines Patches einschließlich einer Patchkonstantenfunktion. Für jeden Ausgabesteuerungspunkt wird einmal ein Hull-Shader aufgerufen.

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

    Ein Hull-Shader verwendet die folgenden Attribute:

Alle Eingabesteuerungspunkte (identifiziert durch VS_CONTROL_POINT_OUTPUT) sind für jeden Hull-Shaderaufruf sichtbar. In diesem Beispiel gibt es 32 Eingabesteuerungspunkte.

Ein Hull-Shader wird einmal pro Ausgabesteuerungspunkt (identifiziert mit SV_OutputControlPointID) für jeden Patch aufgerufen (identifiziert mit SV_PrimitiveID). Der Zweck dieses speziellen Shaders besteht darin, ausgabe i zu berechnen, die als BEZIER-Kontrollpunkt definiert wurde (in diesem Beispiel sind 16 Ausgabesteuerungspunkte durch outputcontrolpoints definiert).

Ein Hull-Shader führt einmal pro Patch eine Routine aus (die Patchkonstantenfunktion), um Patchkonstantendaten (mindestens Tessellationsfaktoren) zu berechnen. Separat führt ein Hull-Shader eine Patchkonstantenfunktion (als SubDToBezierConstantsHS bezeichnet) auf jedem Patch aus, um Patchkonstantendaten wie Tessellationsfaktoren für die Tessellatorphase zu berechnen.

Verwenden von Direct3D 11

Übersicht über Tessellation