A Geometry Shader is a programmable stage within the Graphics Pipeline that can alter or generate new geometric primitives. Operating after the Vertex Shader, it processes entire primitives (points, lines, or triangles) and can output new ones, changing the shape and complexity of rendered objects.
Here is a simple example of a Geometry Shader in GLSL that takes a single point and expands it into a quad:
#version 330 core
layout (points) in; // Takes points as input
layout (triangle_strip, max_vertices = 4) out; // Outputs a triangle strip with max 4 vertices
void main() {
// Get the position of the input point
vec4 pos = gl_in[0].gl_Position;
float size = 0.1; // Size of the quad
// Emit vertices to form a quad around the input point
gl_Position = pos + vec4(-size, -size, 0.0, 0.0); EmitVertex();
gl_Position = pos + vec4( size, -size, 0.0, 0.0); EmitVertex();
gl_Position = pos + vec4(-size, size, 0.0, 0.0); EmitVertex();
gl_Position = pos + vec4( size, size, 0.0, 0.0); EmitVertex();
EndPrimitive(); // Finish the quad primitive
}
Common applications for Geometry Shaders include generating point sprites from individual points, extruding volumes for Shadows, creating fur or grass patches, and dynamically tessellating geometry based on certain conditions. While powerful, Geometry Shaders can introduce significant performance overhead due to their ability to generate large amounts of new geometry, often making them less efficient than other methods like Instancing for certain tasks.