UUSL Tessellation
Since UUSL supports tessellation, there are additional functions, semantics and parameters for tessellation shaders.
Tessellation requires new shader types: hull (also known as control) shader and evaluation (also known as domain). Hull shaders have a *.hull extension, evaluation shaders have a *.eval extension.
The essential thing of the tessellation is SET_QUAD_DOMAIN define. It defines the type of tessellator input: if you use it the tessellator will have quads input, otherwise triangles.
Tessellation Attributes#
You should specify the tessellation attributes in both tessellation shaders (hull and evaluation). These attributes defines the type of patches, and primitive topologies.
Domain Patch Type#
If you have used the SET_QUAD_DOMAIN define, the engine will use the quad patches:
#define DOMAIN_PATCH quads
#define DOMAIN_PATCH [domain("quad")]
#define DOMAIN_PATCH_VERTICES 4
Otherwise, the engine will use triangle patches:
#define DOMAIN_PATCH triangles
#define DOMAIN_PATCH [domain("tri")]
#define DOMAIN_PATCH_VERTICES 3
Partitioning Scheme#
Partitioning scheme of the tessellator is defined by the SET_PARTITIONING function:
SET_PARTITIONING ( value VALUE ) #
Specifies the partitioning scheme the tessellator should use for dividing patches.Arguments
- value VALUE - The partitioning attribute. The value can be one of the following:
- PARTITIONING_FRAC_ODD - the tessellation factor is rounded to the next odd integer within the [min;max] range.
Equivalents
fractional_odd_spacing
[partitioning("fractional_odd")]
- PARTITIONING_FRAC_EVEN - the tessellation factor is rounded to the next even integer within the [min;max] range.
Equivalents
fractional_even_spacing
[partitioning("fractional_even")]
- PARTITIONING_POW2 - the tessellation is rounded to the next greatest power of 2, yielding the effective range [1, 2, 4, 8, 16, 32, 64].
Equivalents
[partitioning("pow2")]
- PARTITIONING_INTEGER - the tessellation factor is always rounded up to the nearest integral value, in the range within the [min;max] range.
Equivalents
[partitioning("Integer")]
- PARTITIONING_FRAC_ODD - the tessellation factor is rounded to the next odd integer within the [min;max] range.
Tessellation Output Primitive Type#
SET_TOPOLOGY_PRIMITIVE ( value VALUE ) #
Defines the output primitive type for the tessellator.Arguments
- value VALUE - The output primitive type attribute. The value can be one of the following:
- TRIANGLE_CW means clockwise-wound triangles (vertices rotate clockwise around the triangle's center).
Equivalents
cw
[outputtopology("triangle_cw")]
- TRIANGLE_CCW triangle_cw means counter-clockwise-wound triangles (vertices rotate counter-clockwise around the triangle's center).
Equivalents
ccw
[outputtopology("triangle_ccw")]
- TRIANGLE_CW means clockwise-wound triangles (vertices rotate clockwise around the triangle's center).
Tessellation Semantics#
Redefined UUSL semantics allows you to create unified input\output shader structures for both graphics APIs.
Hull (Control) Shader Semantics#
Initialization semantics for hull (control) shader:
UUSL | OpenGL | Direct3D | Description |
---|---|---|---|
INIT_CONTROL_IN(TYPE,NUM) | in TYPE s_texcoord_ ## NUM ## []; | TYPE data_ ## NUM : TEXCOORD ## NUM; | Adds (initializes) a control (hull) shader input semantic. |
INIT_CONTROL_OUT | out TYPE s_tess_texcoord_ ## NUM ## []; | TYPE data_ ## NUM : TEXCOORD ## NUM; | Adds (initializes) a control shader output data semantic. |
Here is a usage example of hull shader input and output structure:
STRUCT(CONTROL_IN)
INIT_POSITION
INIT_CONTROL_IN(float4,0)
INIT_CONTROL_IN(float3,1)
END
STRUCT(CONTROL_OUT)
INIT_POSITION
INIT_CONTROL_OUT(float4,0)
END
// end of structures
Use the following pre-defined variables to use the input\output control shader semantics:
UUSL | OpenGL | Direct3D | Description |
---|---|---|---|
OUT_PATCH_EDGE(INDEX) | edges[INDEX] | output.edges[INDEX] | Defines the tessellation amount on each edge of a patch. |
OUT_CONTROL_DATA(NUM) | s_tess_texcoord_ ## NUM ## [gl_InvocationID] | output.data_ ## NUM | An output texture coordinates variable. |
IN_CONTROL_DATA(NUM,ID) | s_texcoord_ ## NUM ## [ ## ID ## ] | input[ ## ID ## ].data_ ## NUM | An input texture coordinates variable. |
OUT_CONTROL_POSITION | gl_out[gl_InvocationID].gl_Position | output.position | An output position system-value variable. |
IN_CONTROL_POSITION(ID) | gl_in[ ## ID ## ].gl_Position | input[ ## ID ## ].position | An input position variable. |
CONTROL_POINT_ID | gl_InvocationID | --- | Contains the coordinate of the vertex within the current patch. |
If you have used the SET_QUAD_DOMAIN define, you should specify the index for this output semantic:
UUSL | OpenGL | Direct3D | Description |
---|---|---|---|
OUT_PATCH_INSIDE(INDEX) | inside[INDEX] | output.inside[INDEX] | Defines the tessellation amount within a patch surface. |
OUT_PATCH_INSIDE | inside | output.inside | Defines the tessellation amount within a patch surface. |
Evaluation (Domain) Shader Semantics#
Initialization semantics:
UUSL | OpenGL | Direct3D | Description |
---|---|---|---|
INIT_EVALUATE_IN(TYPE,NUM) | in TYPE s_tess_texcoord_ ## NUM ## []; | TYPE data_ ## NUM : TEXCOORD ## NUM; | Adds an input data semantic. |
INIT_EVALUATE_OUT(TYPE,NUM) | out TYPE s_texcoord_ ## NUM; | TYPE data_ ## NUM : TEXCOORD ## NUM; | Adds an output data semantic. |
Here is a usage example of evaluation shader input and output structure:
STRUCT(EVALUATE_IN)
INIT_POSITION
INIT_EVALUATE_IN(float4,0)
END
STRUCT(EVALUATE_OUT)
INIT_POSITION
INIT_EVALUATE_OUT(float2,0)
INIT_EVALUATE_OUT(float3,1)
INIT_EVALUATE_OUT(float3,2)
INIT_EVALUATE_OUT(float3,3)
INIT_EVALUATE_OUT(float,4)
INIT_CUSTOM_DEPTH_VERTEX_OUT
END
// end of structures
Use the following pre-defined variables to use the input\output control shader semantics:
UUSL | OpenGL | Direct3D | Description |
---|---|---|---|
OUT_EVALUATE_DATA(NUM) | s_texcoord_ ## NUM | output.data_ ## NUM | An output texture coordinates variable. |
IN_EVALUATE_PATCH_DATA(NUM,ID) | s_tess_texcoord_ ## NUM ## [ ## ID ## ] | input[ ## ID ## ].data_ ## NUM | An input patch data semantic. |
OUT_EVALUATE_POSITION(NUM,ID) | gl_Position | output.position | An output position system-value variable. |
IN_EVALUATE_PATCH_POSITION(ID) | gl_in[ ## ID ## ].gl_Position | input[ ## ID ## ].position | An input patch data position semantic value. |
DOMAIN_LOCATION | gl_TessCoord | patch_constant.coords | Contains the coordinate of the vertex within the current patch. Defines the location on the hull of the current domain point being evaluated. |
Tessellation Main Functions#
Control Shader Main Function#
Hull shader requires the main shader function and patch constant function.
Patch Constant Function#
To start and end the main function of the control patch constant data, use the following instructions:
MAIN_PATCH_CONSTANT_BEGIN(CONTROL_IN)
<your code here>
END_PATCH_CONSTANT
//end
This code is equivalent to:
//if SET_QUAD_DOMAIN defined
void patch_constant(out float edges[4], out float[2] inside) {
<your code here>
}
//else
void patch_constant(out float edges[3], out float inside) {
<your code here>
}
CONTROL_CONSTANT_OUT patch_constant(InputPatch<CONTROL_IN,DOMAIN_PATCH_VERTICES> input) {
CONTROL_CONSTANT_OUT output = (CONTROL_CONSTANT_OUT)0;
<your code here>
return output; }
//
Hull Shader Function#
To start and end the main function of the hull shader, use the following instructions:
MAIN_CONTROL_BEGIN(CONTROL_OUT, CONTROL_IN)
<your code here>
END_CONTROL
//end
This code is equivalent to:
#ifdef SET_QUAD_DOMAIN
layout(vertices = 4) out;
void main() {
if(gl_InvocationID == 0) {
float edges_factor[4];
float inside_factor[2];
patch_constant(edges_factor,inside_factor);
gl_TessLevelOuter[0] = edges_factor[0];
gl_TessLevelOuter[1] = edges_factor[1];
gl_TessLevelOuter[2] = edges_factor[2];
gl_TessLevelOuter[3] = edges_factor[3];
gl_TessLevelInner[0] = inside_factor[0];
gl_TessLevelInner[1] = inside_factor[1];
}
<your code here>
}
#else
layout(vertices = 3) out;
void main() {
if(gl_InvocationID == 0) {
float edges_factor[3];
float inside_factor;
patch_constant(edges_factor,inside_factor);
gl_TessLevelOuter[0] = edges_factor[0];
gl_TessLevelOuter[1] = edges_factor[1];
gl_TessLevelOuter[2] = edges_factor[2];
gl_TessLevelInner[0] = inside_factor;
}
<your code here>
}
#endif
DOMAIN_PATCH
[maxtessfactor(64.0f)]
[outputcontrolpoints(DOMAIN_PATCH_VERTICES)]
[patchconstantfunc("patch_constant")]
CONTROL_PARTITIONING_TYPE
CONTROL_TOPOLOGY_PRIMITIVE_TYPE
CONTROL_OUT main(InputPatch<CONTROL_IN,DOMAIN_PATCH_VERTICES> input,uint CONTROL_POINT_ID : SV_OUTPUTCONTROLPOINTID) {
CONTROL_OUT output;
<your code here>
return output; }
Evaluation Shader Main Function#
To start and end the main function of the evaluation shader, use the following instructions:
MAIN_EVALUATE_BEGIN(EVALUATE_OUT, EVALUTATE_IN)
<your code here>
END_EVALUATE
//end
This code is equivalent to:
layout(DOMAIN_PATCH,CONTROL_PARTITIONING_TYPE,CONTROL_TOPOLOGY_PRIMITIVE_TYPE) in;
void main() {
<your code here>
}
DOMAIN_PATCH
EVALUATE_OUT main(EVALUATE_CONSTANT_IN patch_constant,const OutputPatch<EVALUATE_IN,DOMAIN_PATCH_VERTICES> input) {
EVALUATE_OUT output;
<your code here>
return output; }
//