GL_OES_geometry_shader

Supported Hardware

Series6XT

Valid APIs

OpenGL ES 3.1

Description

Geometry Shaders are a new programmable pipeline step that sits in the current OpenGL ES pipeline directly after primitive assembly, and before clipping, culling etc. This stage allows access to the vertices in the primitive constructed by the earlier phases, in order to interpret them and re-emit new geometry. For example, the vertex shader and primitive assembly could output single point primitives, and the geometry shader could convert this into a set of triangles for further processing. Geometry shaders can be used for a form of tessellation, but this is considered superseded by OES_tessellation_shader. Geometry shaders can also discard primitives.

Note

Adjacency Primitives

As well as the standard GL primitives, this extension adds four new primitive types: LINES_ADJACENCY, LINE_STRIP_ADJACENCY, TRIANGLES_ADJACENCY and TRIANGLE_STRIP_ADJACENCY. These new types function the same as their non-adjacency counterparts everywhere except the geometry shader. In the geometry shader, these modes allow access to neighbouring vertices for each vertex. These neighbouring vertices can be useful as control points to bound any transformations done on input geometry.

Layered Rendering

For use cases such as stereoscopic (or other multi-view) rendering, it is often desirable to do some vertex shading only once, rather than repeating it over and over for each view. Geometry shader functionality described so far can allow this by using multiple invocations to transform geometry from different angles, but each view may need to be output to a separate render target. To handle this use case, this extension adds functionality called layered rendering, which allows framebuffers to be created with multiple layers. The geometry shader can then choose which layer its outputs will be sent to via the special gl_Layer output value.

Inputs

Geometry shader inputs come in the form of Shader IO blocks - including the built-in inputs. Built-in inputs match the built-in vertex shader outputs, but are passed through a built-in io block: gl_in. This is to distinguish them from output values.

Note: This block does not include point size unless OES_geometry_point_size is supported and enabled.

Each io block is actually an array of blocks, and each is either implicitly (or explicitly) sized to the number of vertices available for each primitive type (e.g. 1 for a point, 2 for a line, 3 for a triangle, etc.).

As well as the built-in block for vertex shader outputs, two additional values are provided:

  • gl_PrimitiveIDIn, which is a counter that describes how many primitives have been processed by the shader during this render.
  • gl_InvocationID, which indicates how many times this shader has been invoked using Multiple Invocations.

Outputs

Geometry shader outputs are the same as inputs, except for the built-in values, which are not part of an io block - instead they are free variables in the same way as they are in a vertex shader. gl_PrimitiveID is also provided as a modifiable output value that is passed on towards the fragment shader.

Registry Link

https://www.khronos.org/registry/gles/extensions/OES/OES_geometry_shader.txt

Example

// Create a Geometry Shader 
GLuint geometryShader = glCreateShader(GL_GEOMETRY_SHADER_OES); 

#extension GL_OES_geometry_shader : require 
#extension GL_OES_shader_io_blocks : require 

// Take in point primitives. 
layout(points) in; 
// Output up to 1 line primitive - needs at least two vertices (one line). 
layout(lines, max_vertices = 2) out; 
void main() 
{ 
	// Emit the first vertex for the output primitive - below the original point 
	gl_Position = gl_in[0].gl_Position + vec4(0.0,-0.1, 0.0, 0.0); 
	EmitVertex(); 
	// Emit the second vertex for the output primitive - above the original point 
	gl_Position = gl_in[0].gl_Position + vec4( 0.0, 0.1, 0.0, 0.0); 
	EmitVertex(); 
	// End the (line) primitive 
	EndPrimitive(); 
}