How To: Design a Domain Shader

A domain shader is the third of three stages that work together to implement tessellation. The domain shader generates the surface geometry from the transformed control points from a hull shader and the UV coordinates. This topics shows how to design a domain shader.

A domain shader is invoked once for each point generated by the fixed function tessellator. The inputs are the UV[W] coordinates of the point on the patch, as well as all of the output data from the hull shader including control points and patch constants. The output is a vertex defined in whatever way is desired. If the output is being sent to the pixel shader, the output must include a position (denoted with a SV_Position semantic).

To design a domain shader

  1. Define the domain attribute.

    [domain("quad")]
    

    The domain is defined for a quad patch.

  2. Declare the location on the hull with the domain location system value.

    • For a quad patch, use a float2.
    • For a tri patch, use a float3 (for barycentric coordinates)
    • For an isoline, use a float2.

    Therefore, the domain location for a quad patch looks like this:

    float2 UV : SV_DomainLocation
    
  3. Define the other inputs.

    The other inputs come from the hull shader and are user defined. This includes the input control points for patch, of which there can be between 1 and 32 points, and input patch constant data.

    The control points are user defined, usually with a structure such as this one (defined in How To: Design a Hull Shader):

    const OutputPatch<BEZIER_CONTROL_POINT, 16> bezpatch
    

    The patch constant data is also user defined, and might look like this one (defined in How To: Design a Hull Shader):

    HS_CONSTANT_DATA_OUTPUT input
    
  4. Add user-defined code to compute the outputs; this makes up the body of the domain shader.

    This structure contains user-defined domain shader outputs.

    struct DS_OUTPUT
    {
        float3 vNormal    : NORMAL;
        float2 vUV        : TEXCOORD;
        float3 vTangent   : TANGENT;
        float3 vBiTangent : BITANGENT;
    
        float4 vPosition  : SV_POSITION;
    };
    

    The function takes each input UV (from the tessellator) and evaluates the Bezier patch at this position.

    [domain("quad")]
    DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input, 
                            float2 UV : SV_DomainLocation,
                            const OutputPatch<BEZIER_CONTROL_POINT, 16> bezpatch )
    {
        DS_OUTPUT Output;
    
        // Insert code to compute the output here.
    
        return Output;    
    }
    

    The function is invoked once for each point generated by the fixed function tessellator. Since this example uses a quad patch, the input domain location (SV_DomainLocation) is a float2 (UV); a tri patch would have a float3 input location (UVW barycentric coordinates), and an isoline would have a float2 input domain location.

    The other inputs for the function come from the hull shader directly. In this example it is 16 control points each one being a BEZIER_CONTROL_POINT, as well as patch constant data (HS_CONSTANT_DATA_OUTPUT). The output is a vertex containing any data desired - DS_OUTPUT in this example.

After designing a domain shader, see How To: Create a Domain Shader.

How to Use Direct3D 11

Tessellation Overview