ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • The Tessellation Pipeline
    CS/게임 프로그래밍 2024. 2. 12. 02:30

    Introduction

    Tessellation

    • Connect small pieces without gaps and overlapping to form a single surface.
    • Means of representing a non-linear mathematical surface.
    • NURBS (non-uniform rational basis splines) : generalized mathematical from for smooth curved surfaces.
    • Subdivision surface; SubD
      • Recursively divided the triangle until the ideal surface is no longer well expressed.
      • Possible to approximate a smooth higher-order surface with a very large number of small triangles.

     

    Why is tessellation useful

    • The mathematical definition of a surface is sufficient with the coefficients, input parameters for the function, reducing memory  storage and I/O bandwidth.
    • Scalability : able to dynamically adjust the level of detail of the surface based on fixed inputs.
    • One code path can be applied to various configurations.
    • Should be noted that it may increase other types of costs, such as evaluating functions defining higher-order surfaces in real time.

     

    Tessellation and the Direct3D Pipeline

    Input Assembler

    • Primitive topology configured in the device : D3D11_PRIMITIVE_TOPOLOGY_n_CONTROL_POINT_PATCHLIST (n : 1~32)
    • Read $n$ indexes from the index buffer.
    • Select vertices corresponding to the indices from the vertex buffer.

     

    Vertex Shader

    • The general use in tessellation : animation
      • Vertex skinning : transform a model according to the frameworks determined by skeletal animation.
    • Perform the task of transform a model space vertex data into world space.

     

    Hull Shader

    • Main function
      • Executed once per declared control point.
      • Up to 128 scalar values (float4 * 32) can be output.
      • Total output per patch cannot exceed 3968 scalars (4KB)
    • Patch constant function
      • Executed once per each patch.
      • Calculate values shared by all control points of a given patch.
      • Logically calculate values that do not correspond to the attributes of each control point.
      • Need to ouptut an array of SV_TessFactor and SV_InsideTessFactor values.
      • Up to 128 scalar values (float4 * 32) can be output.
    • Both functions have access to all vertices
      1. that are output by the vertex shader.
      2. that are considered to belong to a given primitive.

     

    Fixed Function Tessellator

    • Everything is fixed except for SV_TessFactor and SV_InsideTessFactor.
    • The control points output by the hull shader stage are not used at all.
    • The output of the tessellator is a set of weights corresponding to the primitive topology declared in the hull shader stage.

     

    Domain Shader

    • Each call in the domain shader proceeds independently of each other.
    • Each call has access to all control points and patch-specific constants output by the hull shader stage.
    • Create entirely new, renderable vertices using
      1. points extracted from primitives provided by the tessllator and
      2. control points provided by the hull shader.

     

    Geometry Shader

    • Know nothing about the current tessellation unless the domain shader has provided the information about the control mesh to the vertex-specific attributes.

     

    Rasterizer and Pixel Shader

    • The rasterizer has no idea that tessellation occur in the previous stages.

     

    Parameters for Tessellation

    • Measures to be considered when determining the level of amplification.
    • Quality and performance : inversely proportional to each other.
    • A simple example
      • Black arrow : line segment produced by the Direct3D 11 pipeline to approximate the surface.
      • Green arrow : ideal curves for artists and designers to display on the screen.

    • Definition of tessellation parameters
    // Example of the patch constant function
    struct HS_PER_PATCH_OUTPUT
    {
        float edgeTessellation[3] : SV_TessFactor;
        float insideTessellation[1] : SV_InsideTessFactor;
    };
    
    HS_PER_PATCH_OUTPUT hsPerPatch(InputPatch<VS_OUTPUT, 3> ip, uint PatchID : SV_PrimitiveID)
    {
        HS_PER_PATCH_OUTPUT o = (HS_PER_PATCH_OUTPUT)0;
    
        o.edgeTessellation[0]
            = o.edgeTessellation[1]
            = o.edgeTessellation[2]
            = 2.0f;
        o.insideTessellation[0] = 2.0f;
        
        return o;
    }
    // Primitives for tessellation
    // Line -> SV_TessFactor : 2 / SV_InsideTessFactor : 0
    struct HS_PER_PATCH_OUTPUT
    {
        float edgeTessellation[2] : SV_TessFactor;
        // ...other values
    };
    
    // Triangle -> SV_TessFactor : 3 / SV_InsideTessFactor : 1
    struct HS_PER_PATCH_OUTPUT
    {
    	float edgeTessellation[3] : SV_TessFactor;
    	float insideTessellation[1] : SV_InsideTessFactor;
    	// ...other values
    };
    
    // Quadrilateral -> SV_TessFactor : 4 / SV_InsideTessFactor : 2
    struct HS_PER_PATCH_OUTPUT
    {
    	float edgeTessellation[4] : SV_TessFactor;
    	float insideTessellation[2] : SV_InsideTessFactor;
    	// ...other values
    };

     

    HLSL Sub-functions

    • *** : Min / Max / Avg
    • The last three parameters of the functions are for output.
    // Apply to squares with two inside tessellation coefficients independent of each other
    void ProcessQuadTessFactors***(
        float4 RawEdgeFactors,
        float InsideScale,
        float4 RoundedEdgeTessFactors,
        float2 RoundedInsideTessFactors,
        float2 UnroundedInsideTessFactors
    );
    
    // Apply to squares with two same inside tessellation coefficients
    void Process2DQuadTessFactors***(
        float4 RawEdgeFactors,
        float2 InsideScale,
        float4 RoundedEdgeTessFactors,
        float2 RoundedInsideTessFactors,
        float2 UnroundedInsideTessFactors
    );
    
    // Apply to all triangles
    void ProcessTriTessFactors***(
        float3 RawEdgeFactors,
        float InsideScale,
        float3 RoundedEdgeTessFactors,
        float RoundedInsideTessFactor,
        float UnroundedInsideTessFactor
    );

     

    Effects of Parameters

    • If any of the coefficients for the primitive are less than or equal to 0, or NaN, the primitive is excluded from processing.
    • Edge factor
      • Determine how small the edges of a primitive are to be divided.
      • The tessellation coefficients of the edges shared by the two adjacent primitives should be same.
      • Water-tightness requirements
        1. Tessellator always produce the same result for the same input.
        2. On any edge, the sample positions are symmetrical with respect to the center of the edge.
      • Force adjacent fragments to use the same tessellation coefficients for the shared edge.

    • Inside tessellation factor
      • Determine how small the inside of a primitive is to be divided.
      • The number of inside factor for quad : 2 / for triangle : 1.

    • Partitioning method
      • Partitioning method is specified as a attribute of the main function of the hull shader.
      • The value specifying the partitioning method is declared as a compile-time constant, so that it will be the same for all patches being rendered with this particular hull shader.
      • The factors are specified as float values by the constant function.
        1. integer : round up all floaintg-point values up to their nearest integer in 1 ~ 64.
        2. fractional_even : round up to the nearest even number in 2 ~ 64. (2, 4, 6, 8, 10, ...)
        3. fractional_odd : round up to the nearest odd number in 1 ~ 64. (1, 3, 5, 7, 9, ...)
        4. pow2 : round up according to the $2^n$ series. (n : 0 ~ 7)

    The result of tessellation according to partitioning method

    • LOD transitions and the risk of popping
      • Popping : a sudden jump where new geometry is added to the final output.
      • Popping can be very noticeable to the viewer.
      • Temporal considerations are important as this visual artifact is almost always caused by inputs changing through time. (across multiple frames in an animation)
      • Important to think about the selection of tessellation factors with regard to how they change through time, rather than as a single, isolated per-frame factor.

    'CS > 게임 프로그래밍' 카테고리의 다른 글

    Multithreaded Rendering  (1) 2024.03.29
    The Computation Pipeline  (0) 2024.03.19
    The Rendering Pipeline - After Tessellation  (0) 2024.02.05
    The Rendering Pipeline - Before Tessellation  (0) 2024.02.04
    The Rendering Pipeline - Background  (0) 2024.02.04
Designed by Tistory.