Tessellation Evaluation Shader

From OpenGL Wiki
Jump to navigation Jump to search
Tessellation Evaluation Shader
Core in version 4.6
Core since version 4.0
Core ARB extension ARB_tessellation_shader

The Tessellation Evaluation Shader (TES) is a Shader program written in GLSL that takes the results of a Tessellation operation and computes the interpolated positions and other per-vertex data from them. These values are passed on to the next stage in the pipeline.

The (TES) takes the abstract patch generated by the tessellation primitive generation stage, as well as the actual vertex data for the entire patch, and generates a particular vertex from it. Each TES invocation generates a single vertex. It can also take per-patch data provided by the Tessellation Control Shader.

The number of times the TES is invoked can differ from implementation to implementation. It will be invoked at least once per tessellated vertex in the abstract patch, but there is no guarantee that the TES won't be invoked multiple times for the same vertex. However, like the Vertex Shader, the TES is expected to output the same value for the same vertex in the abstract patch.

Tessellation options

The presence of an active TES in a program or program pipeline is what governs whether or not the tessellation primitive generation stage will occur. Because of that, many options that control the particular form of tessellation are specified in the TES itself.

The details of what these mean for the tessellation results are described in the section on the tessellation primitive generation. This section will only describe how to specify these options, not go into detail on exactly what they do.

All of these options are input layout qualifiers. They are specified using that syntax:

layout(param1​, param2​, ...) in;

They can be specified as separate statements or all in one. However, each particular type of parameter can only be specified once (you technically can specify them multiple times, but they all must be the same).

Abstract patch type

The TES defines the type of abstract patch that will be tessellated.

The possible values for this are:

  • isolines: The patch is a rectangular block of parallel lines. The output is a series of lines.
  • triangles: The patch is a triangle. The output is a series of triangles.
  • quads: The patch is a quadrilateral. The output is a series of triangles.

The TES must provide this option.


The TES has options that control the spacing between tessellated vertices of the abstract patch. The possible values for this are:

  • equal_spacing: There will be equal distances between vertices in the abstract patch.
  • fractional_even_spacing: There will always be an even number of segments. Two of the segments will grow and shrink based on how close the tessellation level is to generating more vertices.
  • fractional_odd_spacing: As even-spacing, but there will always be an odd number of segments.

This is optional. If the TES does not specify this parameter, equal_spacing will be used.

Primitive ordering

When emitting triangles, the Winding Order can be important for face culling. The process of tessellation takes place over an abstract patch, which is not in any particular coordinate system. It is the TES's responsibility to take abstract patch coordinates and generate real clip-space (or whatever your Geometry Shader expects) positions from them.

Therefore, maintaining the proper winding order for triangles is the job of the TES. To facilitate that, the TES has the ability to control the winding order of the primitive generator. This is done via the cw and ccw parameters.

Remember that this parameter only controls the winding order of the triangles within the abstract patch. The winding order of the final triangle primitives will ultimately be based on the TES's generated positions. As such, different triangles generated from the same patch can have different final winding orders.

This parameter is optional. If the TES does not specify this parameter, ccw will be used. Since lines don't have a winding order, this parameter is useless when using the isolines patch type or point_mode rendering.

Primitive generation

Normally, the kind of Primitive emitted by the primitive generator is defined by the abstract patch type. isolines will generate a series of line-strips, while the others will generate a series of triangles.

The TES can force the primitive generator to override this and simply generate a point primitive for each vertex in the tessellated patch. A Geometry Shader could modify these and build a quad from each point, or they could simply be drawn as points.

To do this, use the layout qualifier point_mode. Obviously specifying this makes the ordering parameter unimportant.


The inputs for the TES are the per-vertex and per-patch outputs from the Tessellation Control Shader (or directly from the vertex shader if no TCS is active). Each TES invocation can access all of the outputs for a particular patch.

Per-vertex inputs from the TCS are arrays of values, indexed by a vertex index. Like TCS outputs, TES inputs can be declared without an explicit size:

in vec2 vertexTexCoord[];

The length of the array (vertexTexCoord.length()) is the size of the input patch.

Per-patch outputs from the TCS can be taken as inputs in the TES using the patch keyword:

patch in vec4 data;
V · E

Tessellation Evaluation Shaders have the following built-in inputs.

in vec3 gl_TessCoord;
in int gl_PatchVerticesIn;
in int gl_PrimitiveID;
the location within the tessellated abstract patch for this particular vertex. Every input parameter other than this one will be identical for all TES invocations within a patch.
Which components of this vec3 that have valid values depends on the abstract patch type. For isolines and quads, only the XY components have valid values. For triangles, all three components have valid values. All valid values are normalized floats (on the range [0, 1]).
the vertex count for the patch being processed. This is either the output vertex count specified by the TCS, or the patch vertex size specified by glPatchParameter if no TCS is active. Attempts to index per-vertex inputs by a value greater than or equal to gl_PatchVerticesIn results in undefined behavior.
the index of the current patch in the series of patches being processed for this draw call. Primitive restart, if used, has no effect on the primitive ID.
Note: The tessellation primitive generator will cull patches that have a zero for one of the active outer tessellation levels. The intent of the specification seems to be that gl_PrimitiveID will still be incremented for culled patches. So the primitive ID for the TES is equivalent to the ID for the TCS invocations that generated that patch. But this is not entirely clear from the spec itself.

The TES also has access to the tessellation levels provided for the patch by the TCS or by OpenGL:

patch in float gl_TessLevelOuter[4];
patch in float gl_TessLevelInner[2];

Only the outer and inner levels actually used by the abstract patch are valid. For example, if this TES uses isolines, only gl_TessLevelOuter[0] and gl_TessLevelOuter[1] will have valid values.

The TES also takes the built-in per-vertex variables output by the TCS:

in gl_PerVertex
  vec4 gl_Position;
  float gl_PointSize;
  float gl_ClipDistance[];
} gl_in[gl_MaxPatchVertices];

Note that just because gl_in is defined to have gl_MaxPatchVertices entries does not mean that you can access beyond gl_PatchVerticesIn and get reasonable values.


Each TES invocation outputs a separate vertex worth of data. Therefore, the TES outputs are scalars (you can have output arrays, but, they won't be treated specially the way per-vertex input arrays are).

User-defined outputs from the TES can have interpolation qualifiers on them.

V · E

Tessellation Evaluation Shaders have the following built-in outputs.

out gl_PerVertex {
  vec4 gl_Position;
  float gl_PointSize;
  float gl_ClipDistance[];

gl_PerVertex defines an interface block for outputs. The block is defined without an instance name, so that prefixing the names is not required.

These variables only take on the meanings below if this shader is the last active Vertex Processing stage, and if rasterization is still active (ie: GL_RASTERIZER_DISCARD is not enabled). The text below explains how the Vertex Post-Processing system uses the variables. These variables may not be redeclared with interpolation qualifiers.

the clip-space output position of the current vertex.
the pixel width/height of the point being rasterized. It only has a meaning when rendering point primitives, which in a TES requires using the point_mode​ input layout qualifier.
allows the shader to set the distance from the vertex to each User-Defined Clip Plane. A positive distance means that the vertex is inside/behind the clip plane, and a negative distance means it is outside/in front of the clip plane. Each element in the array is one clip plane. In order to use this variable, the user must manually redeclare it with an explicit size.

See also