In the d3d11 pipeline, three new stages, hull shader, tessellator, and domain shader are added to implement subdivision operations, that is, the GPU segments the low-Detail surface into a high-Detail entity. In the GPU, the low mode is converted to the high mode through tessellation. While obtaining the High-Detail model, it can effectively reduce the bandwidth consumption for transmitting vertex data from system memory to video memory.
Next, let's take a look at what these three phases are doing, what is input, and what is output? First draw a picture.
1. Hull shader stage
The hull shader stage can be divided into two independent stages, which are executed in parallel.
The first phase is executed by Per control points. In this phase, the corresponding control points are output for each control point in the patch. The so-called patch is a body element with control points. For example, if a triangle has three vertices as control points, the triangle is a patch with three control points. Of course, in the hull shader, we can also convert the input control points to generate new control points, such as three input control points, and output six control points. Note: The number of input or output control points is 1 ~ 32.
The second stage is the patch constant stage. At this time, hullshader will call a const data function, which mainly produces the tessellation factor, which determines how to segment the current patch in the TS stage.
In addition, the hullshader stage also specifies the tessellation mode used in some Ts stages, for example, the segmented patch is a triangle (topology mode), and the partition mode (which subdivision algorithm is selected) is hs_partition.
The following is a piece of hull shader code:
Struct hullinputtype
{
Float3 position: position;
Float4 color: color;
};
Struct constantoutputtype
{
Float edges [3]: sv_tessfactor;
Float inside: sv_insidetessfactor;
};
Struct hulloutputtype
{
Float3 position: position;
Float4 color: color;
};
// The patch constant function determines the tessellation factor. Each patch is executed once, so it is per patch, not per control point.
Constantoutputtype colorpatchconstantfunction (inputpatch
{
Constantoutputtype output;
// Set the subdivision factor of the three sides
Output. Edges [0] = tessellationamount;
Output. Edges [1] = tessellationamount;
Output. Edges [2] = tessellationamount;
// Set the subdivision factor in the Triangle
Output. Inside = tessellationamount;
Return output;
}
// Note that the number of input control points must be the same as that in the iasetprimitivetopology () function.
// In this example, all values are 3 input_patch_size
// The hull shader is called once per output control point, which is specified
// Outputcontrolpoints. For this sample, we take the control points from the vertex
// Shader and pass them directly off to the domain shader. In a more complex scene,
// You might perform a basis conversion from the input control points into a bezr
// Patch, such as the subd11 sample of DirectX SDK.
// The input to the hull shader comes from the vertex shader
// The output from the hull shader will go to the domain shader.
// The tessellation factor, topology, and partition mode will go to the fixed function
// Tessellator stage to calculate the uvw and domain points
[Domain ("Tri")] // triangle domain for our shader
[Partitioning ("integer")] // partitioning type according to the GUI
[Outputtopology ("triangle_cw")] // Where the generated triangles shoshould face
[Outputcontrolpoints (3)] // number of times this part of the hull shader will be called for each patch
[Patchconstantfunc ("colorpatchconstantfunction")] // The constant hull shader function
Hulloutputtype colorhullshader (inputpatch
{
Hulloutputtype output;
// Set the Control Point
Output. Position = Patch [pointid]. position;
// The output color is the input color.
Output. Color = Patch [pointid]. color;
Return output;
}
2. tessellator stage
Tessellator is a fixed pipeline stage. Its main function is to segment a domain (triangle, quadrilateral, or line) and divide them into many small objects, such as triangles, quadrilateral, or lines.
In the case of segmentation, tessellator processes patches in a normalized coordinate system. For example, the input is a quad (quadrilateral), but the quad must first be mapped to a square in the unit of 1, then, tessellator segments the square.
Tessellator is a per-patch operation. The Tess factor passed in the hull shader stage determines the number of subdivisions, and the partitioning introduced in the hull shader stage determines the subdivision algorithm used. Tessellator outputs the U, V, {w} coordinates and the topology information of the subdivided domain.
3. Domain shader stage
The domain shader stage generates the subdivided vertex positions in the patch Based on the u, v, {w} coordinates generated by the TS stage and the control points passed in by the HS stage.
Domain shader is per vertex. It must be called once for the vertex generated by each segment in ts. Its input parameters include the U, V, {w} coordinates and control points, as well as const data, such as Tess factor.
The following is a piece of domain shader code:
Struct constantoutputtype
{
Float edges [3]: sv_tessfactor;
Float inside: sv_insidetessfactor;
};
Struct hulloutputtype
{
Float3 position: position;
Float4 color: color;
};
Struct pixelinputtype
{
Float4 position: sv_position;
Float4 color: color;
};
// Call the vertex after each subdivision once
[Domain ("Tri")]
Pixelinputtype colordomainshader (constantoutputtype input, float3 uvwcoord: sv_domainlocation, const outputpatch
{
Float3 vertexposition;
Pixelinputtype output;
// Vertex Generation Based on Center of Gravity coordinates
Vertexposition = uvwcoord. x * Patch [0]. Position + uvwcoord. y * Patch [1]. Position + uvwcoord. z * Patch [2]. position;
// Calculate the position of the new vertex in the world coordinate system
Output. Position = MUL (float4 (vertexposition, 1.0f), worldmatrix );
Output. Position = MUL (output. Position, viewmatrix );
Output. Position = MUL (output. Position, projectionmatrix );
// The new vertex color is also the color combination of each Control Point
Output. Color = uvwcoord. x * Patch [0]. color + uvwcoord. y * Patch [1]. color + uvwcoord. z * Patch [2]. color;
Return output;
}