Cara: Mendesain Hull Shader

Shader lambung adalah tahap pertama dari tiga tahap yang bekerja sama untuk mengimplementasikan tessellation (dua tahap lainnya adalah tesselator dan shader domain). Topik ini menunjukkan cara mendesain shader lambung.

Shader lambung membutuhkan dua fungsi, shader lambung utama dan fungsi konstanta patch. Shader lambung mengimplementasikan perhitungan pada setiap titik kontrol; shader lambung juga memanggil fungsi konstanta patch yang mengimplementasikan perhitungan pada setiap patch.

Setelah Anda merancang shader lambung, lihat Cara: Membuat Hull Shader untuk mempelajari cara membuat shader lambung.

Untuk merancang shader lambung kapal

  1. Tentukan kontrol input shader lambung dan titik kontrol output.

    // 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. Tentukan data konstanta patch output.

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

    Untuk domain quad, SV_TessFactor mendefinisikan 4 faktor tesselerasi tepi (untuk tessellate tepi), karena tessellator fungsi tetap perlu tahu berapa banyak untuk tessellate. Output yang diperlukan berbeda untuk domain segitiga dan isoline.

    Tesselator fungsi tetap tidak melihat output shader lambung lainnya, seperti data konstanta patch lainnya atau titik kontrol apa pun. Shader domain -- yang dipanggil untuk setiap titik yang dihasilkan tessellator fungsi tetap -- akan melihat sebagai input semua titik kontrol output hull shader dan semua data konstanta patch output; shader mengevaluasi patch di lokasinya.

  3. Tentukan fungsi konstanta patch. Fungsi konstanta patch dijalankan sekali untuk setiap patch untuk menghitung data apa pun yang konstan untuk seluruh patch (dibandingkan dengan data titik kontrol per, yang dihitung dalam shader lambung).

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

    Properti fungsi konstanta patch meliputi:

    • Satu input menentukan variabel yang berisi id patch, dan diidentifikasi oleh nilai sistem SV_PrimitiveID (lihat semantik dalam model shader 4).
    • Salah satu parameter input adalah titik kontrol input, yang dideklarasikan dalam VS_CONTROL_POINT_OUTPUT dalam contoh ini. Fungsi patch dapat melihat semua titik kontrol input untuk setiap patch, ada 32 titik kontrol per patch dalam contoh ini.
    • Minimal, fungsi harus menghitung faktor tesselulasi per patch untuk tahap tesselator yang diidentifikasi dengan SV_TessFactor. Domain quad memerlukan empat faktor tessellation untuk tepi dan dua faktor tambahan (diidentifikasi oleh SV_InsideTessFactor) untuk memisahkan bagian dalam patch. Tesselator fungsi tetap tidak melihat output shader lambung lainnya (seperti data konstanta patch atau titik kontrol apa pun).
    • Output biasanya didefinisikan oleh struktur dan diidentifikasi oleh HS_CONSTANT_DATA_OUTPUT dalam contoh ini; struktur tergantung pada jenis domain dan akan berbeda untuk domain segitiga atau isoline.

    Shader domain di sisi lain dipanggil untuk setiap titik yang dihasilkan tesselator fungsi tetap dan perlu melihat titik kontrol output dan data konstanta patch output (keduanya dari shader lambung) untuk mengevaluasi patch di lokasinya.

  4. Tentukan shader lambung. Shader lambung mengidentifikasi properti patch termasuk fungsi konstanta patch. Shader lambung dipanggil sekali untuk setiap titik kontrol 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;
    }
    

    Shader lambung menggunakan atribut berikut:

Semua titik kontrol input (diidentifikasi oleh VS_CONTROL_POINT_OUTPUT) terlihat oleh setiap pemanggilan shader lambung. Dalam contoh ini, ada 32 titik kontrol input.

Shader lambung dipanggil sekali per titik kontrol output (diidentifikasi dengan SV_OutputControlPointID) untuk setiap patch (diidentifikasi dengan SV_PrimitiveID). Tujuan dari shader khusus ini adalah untuk menghitung output i, yang didefinisikan sebagai titik kontrol BEZIER (contoh ini memiliki 16 titik kontrol output yang ditentukan oleh outputcontrolpoints).

Shader lambung menjalankan rutinitas sekali per patch (fungsi konstanta patch) untuk menghitung data konstanta patch (faktor tesselulasi seminimal mungkin). Secara terpisah, shader lambung menjalankan fungsi konstanta patch (disebut SubDToBezierConstantsHS) pada setiap patch untuk menghitung data konstanta patch seperti faktor tessellation untuk tahap tessellator.

Cara Menggunakan Direct3D 11

Gambaran Umum Tessellation