11 Geometry Shader
R. Mukundan Department of Computer Science and Software Engineering University of Canterbury, .
OpenGL Geometry Shader
Copyright By PowCoder代写 加微信 powcoder
Vertex Shader
The geometry shader receives inputs from either TES or the vertex shader (if tessellation is not active).
The geometry shader receives inputs in arrays with values corresponding to one whole primitive.
A geometry shader can thus process an entire primitive.
layout …position; out vec3 normal; out vec4 colour;
… … …
gl_Position = …;
in vec3 normal[];
in vec4 colour[];
int nvert = gl_in[].length();
for(int i=0; i < nvert; i++) {
vec4 p = gl_in[].gl_Position; ...
Myshader.vert Myshader.geom
Geometry Shader
Prim. Assembly, Clipping, Vewport Trans.
Geometry Shader
A geometry shader runs once per input primitive. If the input is a triangle strip, then the geometry shader will be invoked for each individual triangle in the strip (as if the triangle strip were expanded out into a triangle list).
A geometry shader can change the type of the input primitive and the number of vertices. It can also be used to discard primitives.
The power of the geometry shader lies in its ability to get information about each primitive, and also to output values into multiple streams.
The geometric shader is the last shader stage before clipping and rasterization. It must emit each vertex in the clip coordinate space using the built-in variable gl_Position.
Example: Lighting calculations
• Application defines VBOs for both position and normal vector
• Vertex shader gets the position and normal vector of a vertex
• Vertex shader performs lighting calculations
• Vertex shader outputs position in clip coordinates, and the colour of the vertex
• Application defines only one VBO containing positions of vertices
• Vertex shader outputs position in world coordinates
• Geometry shader receives all vertices of the primitive
• Geometry shader computes normal vectors and performs lighting calculations
• Geometry shader outputs positions in clip coordinates, and the colours of vertices
Vertex Shader
Vertex Shader
Geometry Shader
Fragment Shader
Fragment Shader
Geometry Shader: Primitive Types
The number of vertices received by the geometry shader (gl_in[].length()) depends on the input primitive type specified by the application through glDrawArrays() or glDrawElements(). E.g. glDrawArrays(GL_QUADS,...);
The input primitve can be of any type: points, lines, line strip, triangles, quads etc.
The geometry shader can also accept a special primitive type GL_TRIANGLES_ADJACENCY
The only output primitive types that can be used in a geometry shader are points, line strip and triangle strip
Triangles and quads can be generated as special cases of a triangle strip
Geometry Shader
Geometry Shader
Input Primitive
EmitVertex(); EmitVertex(); .... EmitVertex(); EndPrimitive();
EmitVertex(); EmitVertex(); .... EmitVertex(); EndPrimitive();
EmitVertex(); EmitVertex(); EmitVertex(); EndPrimitive();
A primitive processing engine
Geometry Shader Outputs
A geometry shader has two built-in functions EmitVertex() and EndPrimitive().
In one execution of the geometry shader, it can produce multiple vertices and multiple primitives (multiple triangles as part of a triangle strip).
Each call to EmitVertex() appends one vertex at the end of the current primitive. Its position is defined by
gl_Position, and other attributes using out variables. If the geometry shader exits without calling
EmitVertex(), then it does not produce any output primitive.
VS FS Application Vertex Shader Fragment Shader
A Simple Application Without GS
Defines 2 VBOs:
1. Posns of 16 vertices
2. Texture coordinates
Converts Vertices to Clip Coordinates
Accesses a Texture and Discards Background
void main() {
gl_Position =
mvpMatrix * position;
oTexCoord = texcoord;
void main() {
col=texture(tree, oTexcoord); if (col.b > 0.5) discard; gl_FragColor = col;
glDrawArrays (GL_QUADS, 0, 16);
A Simple Application With GS
Application Vertex Shader Geometry Shader
Defines one VBO: 1. Posns of 4 points
A Pass-through Shader
Generates quads and texture coordinates
void main() {
gl_Position = position;
See next slide
glDrawArrays
(GL_POINTS, 0, 4);
A Simple Application With GS Geometry Shader
Fragment Shader
No change in Fragment shader (Slide 8)
Accesses a Texture, Discards Background
Generates quads and texture coordinates
Geometry Shader Output Example 1
Producing a triangle strip:
gl_Position = …; //Point 1 oColor = …;
EmitVertex();
gl_Position = …; //Point 2 oColor = …;
EmitVertex();
gl_Position = …; //Point 3 oColor = …;
EmitVertex();
gl_Position = …; //Point 4 oColor = …;
EmitVertex();
gl_Position = …; //Point 5 oColor = …;
EmitVertex();
gl_Position = …; //Point 6 oColor = …;
EmitVertex(); EndPrimitive();
Geometry Shader Output Example 2
Producing triangles:
gl_Position = …; //Point 1 oColor = …;
EmitVertex();
gl_Position = …; //Point 2 oColor = …;
EmitVertex();
gl_Position = …; //Point 3 oColor = …;
EmitVertex(); EndPrimitive();
gl_Position = …; //Point 4 oColor = …;
EmitVertex();
gl_Position = …; //Point 5 oColor = …;
EmitVertex();
gl_Position = …; //Point 6 oColor = …;
EmitVertex(); EndPrimitive();
Adjacency Primitives
OpenGL provides new types of adjacency primitives that contains information about vertices adjacent to the current primitive
GL_LINES_ADJACENCY: 4 vertices per primitive. The second and third vertices form the current line. The first and the fourth vertices are treated as adjacent to it.
GL_TRIANGLES_ADJACENCY: 6 vertices per primitive. First, third and fifth vertices form the current triangle.
Adjacency Primitives
When an adjacency primitive is drawn without a geometry shader, only vertices corresponding to the current primitive (line or triangle) are drawn. The adjacent vertices are discarded.
Example: 1,3,4,5,2,0,6,8,7,5,4,3
glDrawElements (GL_TRIANGLES_ADJACENCY,12,GL_UNSIGNED_INT,NULL);
Adjacency Primitives
If a geometry shader is active, it will receive all vertices of the adjacency primitive in gl_in[].gl_Position array.
We can use information about adjacent triangles to modify the attributes of the current triangle or to generate additional primitives.
Example: Crease edges can be detected by measuring the angle between surface normal vectors of adjacent triangles.
Geometry Culling
A geometry shader can discard a primitive as a whole:
#version 400
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out; uniform mat4 mvpMatrix;
void main()
… //normal vector, view vector computation ndotV= dot(normalVec, viewVec);
if(ndotV < 0) return;
for(i=0; I < gl_in.length(); i++)
gl_Position = mvpMatrix*gl_in[i].gl_Position; EmitVertex();
EndPrimitive();
Geometry Amplification
Line strip
The application generates a 2D line strip.
The geometry shader receives individual lines of the line strip: (x1, y1), (x2, y2).
The geometry shader outputs a triangle strip for each line received.
(x2, y2) (x1, y1)
glDrawArrays(GL_LINE_STRIP,...);
(x1, y1) COSC363
layout(triangle_strip)out;
(x2, y2) (x1, y1)
Geometry Amplification
layout (lines) in;
layout (triangle_strip, max_vertices = 80) out; void main()
Line strip Application
float xnew, znew;
float theta, ctheta, stheta;
= gl_in[0].gl_Position.x; = gl_in[0].gl_Position.y; = gl_in[1].gl_Position.x; = gl_in[1].gl_Position.y;
for(i = 0; i <= 36; i++) {
theta = i * 0.17453;
ctheta = cos(theta);
stheta = sin(theta);
xnew = x1 * ctheta;
znew = -x1 * stheta;
gl_Position = mvpMatrix * vec4(xnew, y1, znew, 1); EmitVertex();
xnew = x2 * ctheta;
znew = -x2 * stheta;
gl_Position = mvpMatrix * vec4(xnew, y2, znew, 1); EmitVertex();
EndPrimitive(); }
//step size = 10 degs
VS TES GS FS
The vertex shader can access only one vertex of a primitive
If the tessellation stage is active, the tessellation evaluation shader also has access to only one vertex (u, v) generated by the primitive generator
The tessellation evaluation shader repositions each vertex on a surface. To perform lighting calculations on the repositioned mesh triangle, we require surface normal vectors at the vertices.
Since the geometry shader receives all vertices of each triangle of the mesh, we can perform the lighting calculation inside the geometry shader. Useful for rendering terrains and Bezier surfaces.
Tessellation + GS
Lighting Calculations in a GS
Geometry Shader: (input: triangle)
Receives all three vertices of each triangle.
Computes the unit normal vector n of the triangle.
Performs lighting calculation
Outputs the colour values and the vertices in clip coordinates.
Lighting Calculations in a GS
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
out vec4 oColor;
vec3 vector1 = gl_in[0].gl_Position.xyz - gl_in[2].gl_Position.xyz;
vec3 vector2 = gl_in[1].gl_Position.xyz
- gl_in[2].gl_Position.xyz;
vec3 normal = normalize(cross(vector1, vector2) //Perform lighting calculation
color = ...
for(i = 0; i < gl_in.length(); i++)
gl_Position = mvpMatrix * gl_in[i].gl_Position;
oColour = color;
EmitVertex();
EndPrimitive();
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com