Difference between revisions of "Tessellation"
(Rearranged patch.) 
(→Tessellation primitive generation) 

Line 44:  Line 44:  
== Tessellation primitive generation ==  == Tessellation primitive generation ==  
−  Primitive generation is a fixedfunction stage responsible for creating a set of new primitives from the input patch. This stage is only executed if a [[#Tessellation evaluation shadertessellation evaluation shader]] (TES) is active in the current program or program pipeline. Primitive generation is affected by  +  Primitive generation is a fixedfunction stage responsible for creating a set of new primitives from the input patch. This stage is only executed if a [[#Tessellation evaluation shadertessellation evaluation shader]] (TES) is active in the current program or program pipeline. Primitive generation is affected by the following factors: 
−  * the input primitive type defined by the subsequent TES which may be one of {{codetriangles}}, {{codequads}} or {{codeisolines}}  +  * The tessellation levels, provided either by the TCS or the default values, as stated above. 
−  +  * The spacing of the tessellated vertices, as defined by the subsequent TES stage. It may be {{codeequal_spacing}}, {{codefractional_even_spacing}}, or {{codefractional_odd_spacing}}.  
+  * The input primitive type defined by the subsequent TES which may be one of {{codetriangles}}, {{codequads}} or {{codeisolines}}. The TES can also force the generation of the tessellation as a series of points by providing the {{codepoint_mode}} primitive.  
+  * The primitive generation order defined by the subsequent TES, which may be {{codecw}} or {{codeccw}}.  
−  Depending on the  +  === Abstract patch === 
+  
+  Notice that the primitive generation is not affected by the outputs of the TCS, the TCS's output patch size, any perpatch TCS outputs (besides the tessellation levels), and so forth. The primitive generation part of the tessellation stage is ''completely blind'' to the actual vertex coordinates and other patch data.  
+  
+  The purpose of the primitive generation system is to determine how many vertices to generate, in which order to generate them, and what kind of primitives to build out of them. The actual pervertex data for these vertices, such as position, color, etc, is to be generated by the TES, based on information provided by the primitive generator.  
+  
+  Because of this dichotomy, the primitive generator operates on what could be considered an "abstract patch". It doesn't look at the patch output from the TCS; it thinks only in terms of tessellating an abstract quad, triangle, or "isoline" block.  
+  
+  Depending on the abstract patch type, the primitive generator evaluates a different number of tessellation levels and applies different tessellation algorithms. Each generated vertex has a normalized position (i.e. in [0, 1]) within the abstract patch. This position has two or three coordinates (denoted (u, v, w) or (u, v)), depending on the type of the patch. The coordinates are provided to the TES via the builtin {{codein vec3 gl_TessCoord}} input.  
+  
+  === Tessellation levels ===  
+  
+  The amount of tessellation that is done over the abstract patch type is defined by inner and outer tessellation levels. These, as previously stated, are provided either by the TCS or by context parameters specified via {{apifuncglPatchParameter}}. They are a 4vector of floats defining the "outer tessellation levels" and a 2vector of floats defining the "inner tessellation levels."  
+  
+  The specific interpretation depends on the abstract patch type being used, but the general idea is this. In most cases, each tessellation level defines how many segments an edge is tessellated into; so a tessellation level of 4 means that an edge will become 4 edges (5 vertices). The "outer" tessellation levels define the tessellation for the outer edges of the primitive. This makes it possible for two or more patches to properly connect, while still having different tessellation levels within the patch. The inner tessellation levels are for the number of tessellations within the abstract patch.  
+  
+  Not all abstract patches use the same number of values in the outer/inner tessellation levels data. For example, triangles only uses one inner level and 3 outer levels. The rest are ignored.  
+  
+  The tessellation levels specified in this way are not directly used. They go through a clamping process to generate the effective tessellation levels that are used to tessellate the primitive. This process depends on the TES's spacing parameter.  
+  
+  In the below discussion, {{parammax}} is the maximum allowed tessellation level, as defined by the {{enumGL_MAX_TESS_GEN_LEVEL}}. It must be at least 64, so you have some room to play with.  
+  
+  The spacing affects the effective tessellation level as follows:  
+  
+  ; {{codeequal_spacing}}  
+  : Each tessellation level is individually clamped to the closed range [1, {{parammax}}]. Then it is rounded up to the nearest integer to give the effective tessellation level.  
+  ; {{codefractional_even_spacing}}  
+  : Each tessellation level is individually clamped to the closed range [2, {{parammax}}]. Then it is rounded up to the nearest ''even'' integer to give the effective tessellation level.  
+  ; {{codefractional_odd_spacing}}  
+  : Each tessellation level is individually clamped to the closed range [1, {{parammax}}  1]. Then it is rounded up to the nearest ''odd'' integer to give the effective tessellation level.  
+  
+  The patch can be discarded if any outer tessellation level that is used by the abstract patch type is 0 or less. It can also be discarded if it is a floatingpoint NaN. A patch that is discarded does not get tessellated, and no TES is invoked for it. It is simply swallowed by the system as though it never were.  
+  
+  This allows a TCS to effectively cull patches by passing 0 for a relevant outer tessellation level.  
+  
+  == Edge tessellation spacing ==  
+  
+  At various points in the discussion about tessellating the abstract patch, there will be statements that say to tessellate an edge of some primitive. This means to subdivide it into a series of segments. Exactly how this process works changes based on the spacing specified in the TES.  
+  
+  Given an ''effective tessellation level'', denoted by {{paramn}}, which applies to that edge, the vertices for an edge tessellated by {{paramn}} is defined as:  
+  
+  ; {{codeequal_spacing}}  
+  : The edge is divided into {{paramn}} segments. All segments will have equal length.  
+  ; {{codefractional_even_spacing}}, {{codefractional_odd_spacing}}  
+  : If {{paramn}} is 1, then no subdivision occurs. Otherwise, the edge will be divided into {{paramn}}  2 segments of equal length. There will also be 2 segments that have length equal to each other, but not necessarily to the first group. The length of these 2 segments, relative to the others, will be {{paramn}}  {{paramf}}, where {{paramf}} is the effective tessellation level value after clamping but before being rounded up.  
+  : When {{paramn}} == {{paramf}}, the length of the 2 segments will be equal to the length of the other segments. As {{paramn}}  {{paramf}} approaches 2.0, the relative length of the 2 segments approaches 0.0.  
+  : The exact location of the 2 shorter segments is not defined, but they should be placed symmetrically, on opposite sides of the subdivided edge. Also, the location must be invariant with the same {{paramf}} value (thus allowing tessellated edges to work together).  
+  
+  The purpose of the fractional spacing modes is to have smoother, more stable interpolation as tessellation levels change. This is best used if tessellation levels are based on the distance to the camera or something.  
=== Triangles ===  === Triangles ===  
−  The  +  
+  The abstract patch of the triangle tessellation is a triangle, naturally. Only the first three outer tessellation levels are used, and only the first inner tessellation level is used.  
+  
+  
+  
+  Each vertex generated and sent to the TES will be provided [http://en.wikipedia.org/wiki/Barycentric_coordinates_%28mathematics%29#Barycentric_coordinates_on_triangles Barycentric coordinates] as the {{codegl_TessCoord}} input. This defines where this vertex is located within the abstract triangle. With this coordinate, it is possible to multiply any vertex attribute from 3 vertices to compute the appropriate value from the tessellation unit.  
+  
+  Therefore, if you have three positions, you can compute the resulting position as follows:  
+  
+  <source lang="glsl">  
+  vec4 outputPos = inPos[0] * gl_TessCoord.x + inPos[1] * gl_TessCoord.y + inPos[2] * gl_TessCoord.z;  
+  </source>  
+  
+  The same math could be done for any attribute.  
=== Quads ===  === Quads ===  
Line 59:  Line 122:  
=== Isolines ===  === Isolines ===  
+  
They are only affected by the first two outer tessellation levels. The generator will create <math>n</math> independent lines, which will be subdivided into m segments with m + 1 vertices, where:  They are only affected by the first two outer tessellation levels. The generator will create <math>n</math> independent lines, which will be subdivided into m segments with m + 1 vertices, where:  
Revision as of 05:34, 20 November 2012


OpenGL Rendering Pipeline

Tessellation is the stage in the OpenGL rendering pipeline where patches of vertex data are subdivided into smaller Primitives. This process is governed by two shader stages and a fixedfunction stage.
This article is a stub. You can help the OpenGL Wiki by expanding it. 
Contents
Overview
The tessellation process is divided into three stages which form an optional part of the rendering pipeline. Two of the stages are programmable; between them is a fixed function stage. They are described below, in the order they are processed.
Patches
Tessellation stages operate on patches, a primitive type denoted by the constant GL_PATCHES. These are arrays of vertices and user defined pervertex attributes written by a vertex shader. The number of vertices per patch can be defined on the applicationlevel using:
void glPatchParameteri(GLenum pname, GLint value);
with GL_PATCH_VERTICES as target and a value which has is on the halfopen range [1, GL_MAX_PATCH_VERTICES]. The maximum number of patch vertices is implementationdependent, but will never be less than 3.
Tessellation control shader
The first step of tessellation is the optional invocation of a tessellation control shader (TCS). The TCS has two jobs:
 Determine the amount of tessellation that a primitive should have.
 Perform any special transformations on the input patch data.
The TCS can change the size of a patch, adding more vertices perpatch or providing fewer. However, a TCS cannot discard a patch (directly; it can do so indirectly), nor can it write multiple patches. Therefore, for each patch provided by the application, one patch will be provided to the next tessellation stage.
The TCS is optional. If no TCS is active in the current program or program pipeline, then the patch data is passed directly from the Vertex Shader invocations to the tessellation primitive generation step. The amount of tessellation done in this case is taken from default values set into the context. These are defined by the following function:
void glPatchParameterfv(GLenum pname, const GLfloat *values);
When pname is GL_PATCH_DEFAULT_OUTER_LEVEL, values is a 4element array of floats defining the four outer tessellation levels. When pname is GL_PATCH_DEFAULT_INNER_LEVEL, values is a 2element array of floats defining the two inner tessellation levels.
These default values correspond to the TCS perpatch output variables gl_TessLevelOuter[4] and gl_TessLevelInner[2].
Tessellation primitive generation
Primitive generation is a fixedfunction stage responsible for creating a set of new primitives from the input patch. This stage is only executed if a tessellation evaluation shader (TES) is active in the current program or program pipeline. Primitive generation is affected by the following factors:
 The tessellation levels, provided either by the TCS or the default values, as stated above.
 The spacing of the tessellated vertices, as defined by the subsequent TES stage. It may be equal_spacing, fractional_even_spacing, or fractional_odd_spacing.
 The input primitive type defined by the subsequent TES which may be one of triangles, quads or isolines. The TES can also force the generation of the tessellation as a series of points by providing the point_mode primitive.
 The primitive generation order defined by the subsequent TES, which may be cw or ccw.
Abstract patch
Notice that the primitive generation is not affected by the outputs of the TCS, the TCS's output patch size, any perpatch TCS outputs (besides the tessellation levels), and so forth. The primitive generation part of the tessellation stage is completely blind to the actual vertex coordinates and other patch data.
The purpose of the primitive generation system is to determine how many vertices to generate, in which order to generate them, and what kind of primitives to build out of them. The actual pervertex data for these vertices, such as position, color, etc, is to be generated by the TES, based on information provided by the primitive generator.
Because of this dichotomy, the primitive generator operates on what could be considered an "abstract patch". It doesn't look at the patch output from the TCS; it thinks only in terms of tessellating an abstract quad, triangle, or "isoline" block.
Depending on the abstract patch type, the primitive generator evaluates a different number of tessellation levels and applies different tessellation algorithms. Each generated vertex has a normalized position (i.e. in [0, 1]) within the abstract patch. This position has two or three coordinates (denoted (u, v, w) or (u, v)), depending on the type of the patch. The coordinates are provided to the TES via the builtin in vec3 gl_TessCoord input.
Tessellation levels
The amount of tessellation that is done over the abstract patch type is defined by inner and outer tessellation levels. These, as previously stated, are provided either by the TCS or by context parameters specified via glPatchParameter. They are a 4vector of floats defining the "outer tessellation levels" and a 2vector of floats defining the "inner tessellation levels."
The specific interpretation depends on the abstract patch type being used, but the general idea is this. In most cases, each tessellation level defines how many segments an edge is tessellated into; so a tessellation level of 4 means that an edge will become 4 edges (5 vertices). The "outer" tessellation levels define the tessellation for the outer edges of the primitive. This makes it possible for two or more patches to properly connect, while still having different tessellation levels within the patch. The inner tessellation levels are for the number of tessellations within the abstract patch.
Not all abstract patches use the same number of values in the outer/inner tessellation levels data. For example, triangles only uses one inner level and 3 outer levels. The rest are ignored.
The tessellation levels specified in this way are not directly used. They go through a clamping process to generate the effective tessellation levels that are used to tessellate the primitive. This process depends on the TES's spacing parameter.
In the below discussion, max is the maximum allowed tessellation level, as defined by the GL_MAX_TESS_GEN_LEVEL. It must be at least 64, so you have some room to play with.
The spacing affects the effective tessellation level as follows:
 equal_spacing
 Each tessellation level is individually clamped to the closed range [1, max]. Then it is rounded up to the nearest integer to give the effective tessellation level.
 fractional_even_spacing
 Each tessellation level is individually clamped to the closed range [2, max]. Then it is rounded up to the nearest even integer to give the effective tessellation level.
 fractional_odd_spacing
 Each tessellation level is individually clamped to the closed range [1, max  1]. Then it is rounded up to the nearest odd integer to give the effective tessellation level.
The patch can be discarded if any outer tessellation level that is used by the abstract patch type is 0 or less. It can also be discarded if it is a floatingpoint NaN. A patch that is discarded does not get tessellated, and no TES is invoked for it. It is simply swallowed by the system as though it never were.
This allows a TCS to effectively cull patches by passing 0 for a relevant outer tessellation level.
Edge tessellation spacing
At various points in the discussion about tessellating the abstract patch, there will be statements that say to tessellate an edge of some primitive. This means to subdivide it into a series of segments. Exactly how this process works changes based on the spacing specified in the TES.
Given an effective tessellation level, denoted by n, which applies to that edge, the vertices for an edge tessellated by n is defined as:
 equal_spacing
 The edge is divided into n segments. All segments will have equal length.
 fractional_even_spacing, fractional_odd_spacing
 If n is 1, then no subdivision occurs. Otherwise, the edge will be divided into n  2 segments of equal length. There will also be 2 segments that have length equal to each other, but not necessarily to the first group. The length of these 2 segments, relative to the others, will be n  f, where f is the effective tessellation level value after clamping but before being rounded up.
 When n == f, the length of the 2 segments will be equal to the length of the other segments. As n  f approaches 2.0, the relative length of the 2 segments approaches 0.0.
 The exact location of the 2 shorter segments is not defined, but they should be placed symmetrically, on opposite sides of the subdivided edge. Also, the location must be invariant with the same f value (thus allowing tessellated edges to work together).
The purpose of the fractional spacing modes is to have smoother, more stable interpolation as tessellation levels change. This is best used if tessellation levels are based on the distance to the camera or something.
Triangles
The abstract patch of the triangle tessellation is a triangle, naturally. Only the first three outer tessellation levels are used, and only the first inner tessellation level is used.
Each vertex generated and sent to the TES will be provided Barycentric coordinates as the gl_TessCoord input. This defines where this vertex is located within the abstract triangle. With this coordinate, it is possible to multiply any vertex attribute from 3 vertices to compute the appropriate value from the tessellation unit.
Therefore, if you have three positions, you can compute the resulting position as follows:
vec4 outputPos = inPos[0] * gl_TessCoord.x + inPos[1] * gl_TessCoord.y + inPos[2] * gl_TessCoord.z;
The same math could be done for any attribute.
Quads
For quads all six tessellation levels are used to subdivide the input rectangle into smaller triangles.
Isolines
They are only affected by the first two outer tessellation levels. The generator will create independent lines, which will be subdivided into m segments with m + 1 vertices, where:
The coordinates of the vertices are determined by subdividing the line along the axis and determining a constant value along the axis for every vertex on the current line using the formula:
As can be seen, the the generator will not create a line at v = 1. During isoline tessellation, the wcoordinate is undefined.
Tessellation evaluation shader
The tessellation primitive generator takes a primitive and tessellates it. However, it has no idea of the algorithm that you intend to use to compute the new positions/normals/texture coordinates/etc. It's a purely fixedfunction system.
The burden on computing the final position of all of the vertices in the tessellated patch falls to the tessellation evaluation shader (TES). Each TES invocation takes a coordinate representing where that vertex is within the tessellated patch, and each TES invocation can access every vertex output by the TCS as well as any perpatch data. The purpose of the TES is to actually do the hard part of tessellation: computing the position, texture coordinates, normals, and so forth, of all of the resultant vertices.
The TES is rather like a vertex shader, in that each invocation operates on a distinct vertex within the tessellated patch. Also, the TES cannot cull vertices or in any way modify them.
A TES is required to have tessellation at all.