OpenGL Cheatsheet
The Rendering Pipeline
Use this OpenGL reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Pipeline Overview
Data flows from CPU → GPU through a fixed sequence of stages. Programmable stages are written in GLSL; fixed-function stages are configured with GL state calls.
CPU (vertex data, uniforms) │ ▼ [Vertex Shader] ← programmable │ ▼ [Tessellation Control] ← programmable (optional, GL 4.0+) │ ▼ [Tessellation Evaluation]← programmable (optional, GL 4.0+) │ ▼ [Geometry Shader] ← programmable (optional) │ ▼ [Primitive Assembly + Clipping] ← fixed │ ▼ [Rasterization] ← fixed │ ▼ [Fragment Shader] ← programmable │ ▼ [Per-Fragment Tests] ← fixed (scissor, stencil, depth) │ ▼ [Blending / Framebuffer Write] ← semi-programmable (blend eq)
Vertex Shader
Runs once per vertex. Must write gl_Position.
#version 460 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aUV; uniform mat4 uMVP; out vec2 vUV; void main() { vUV = aUV; gl_Position = uMVP * vec4(aPos, 1.0); }
Vertex shader built-ins
| Built-in | Type | R/W | Description |
|---|---|---|---|
gl_Position | vec4 | W | Clip-space position (required) |
gl_PointSize | float | W | Point sprite size (px); needs GL_PROGRAM_POINT_SIZE |
gl_VertexID | int | R | Index of the current vertex |
gl_InstanceID | int | R | Instance index (instanced rendering) |
gl_BaseVertex | int | R | basevertex from glDrawElementsBaseVertex |
gl_BaseInstance | int | R | baseinstance from glDrawArraysInstancedBaseInstance |
Tessellation Shaders (GL 4.0+)
Two-stage: control decides the tessellation level; evaluation computes final position.
// Tessellation Control Shader #version 460 core layout(vertices = 3) out; // output patch size (3 = triangle) void main() { gl_TessLevelOuter[0] = 4.0; gl_TessLevelOuter[1] = 4.0; gl_TessLevelOuter[2] = 4.0; gl_TessLevelInner[0] = 4.0; gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; }
// Tessellation Evaluation Shader #version 460 core layout(triangles, equal_spacing, ccw) in; void main() { vec3 p = gl_TessCoord.x * gl_in[0].gl_Position.xyz + gl_TessCoord.y * gl_in[1].gl_Position.xyz + gl_TessCoord.z * gl_in[2].gl_Position.xyz; gl_Position = vec4(p, 1.0); }
TES layout qualifiers
| Qualifier | Options |
|---|---|
| Primitive | triangles, quads, isolines |
| Spacing | equal_spacing, fractional_even_spacing, fractional_odd_spacing |
| Winding | cw, ccw |
| Point mode | point_mode (emit a point per tessellated vertex) |
Geometry Shader
Runs per-primitive. Can emit different primitive types or amplify geometry.
#version 460 core layout(triangles) in; // input primitive layout(triangle_strip, max_vertices = 3) out; // output in vec2 vUV[]; // arrays — one element per input vertex out vec2 gUV; void main() { for (int i = 0; i < 3; i++) { gUV = vUV[i]; gl_Position = gl_in[i].gl_Position; EmitVertex(); } EndPrimitive(); }
Geometry shader input/output layout tokens
| Stage | Input tokens | Output tokens |
|---|---|---|
| Input | points, lines, lines_adjacency, triangles, triangles_adjacency | — |
| Output | — | points, line_strip, triangle_strip |
Fragment Shader
Runs once per rasterized fragment (candidate pixel). Writes to output variables.
#version 460 core in vec2 vUV; uniform sampler2D uTex; out vec4 FragColor; // location 0 by default void main() { FragColor = texture(uTex, vUV); }
Fragment shader built-ins
| Built-in | Type | Description |
|---|---|---|
gl_FragCoord | vec4 | Window-space coords (x, y, z=depth, w=1/clip-w) |
gl_FrontFacing | bool | True if front face |
gl_FragDepth | float | Override depth write (disables early-Z) |
gl_SampleID | int | Sample index (requires multisampled FBO) |
gl_SamplePosition | vec2 | Sub-pixel sample location |
gl_ClipDistance[i] | float[] | User clip planes (set in vertex stage) |
Compute Shader (GL 4.3+)
Not part of the graphics pipeline — dispatched separately.
#version 460 core layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; layout(rgba32f, binding = 0) uniform image2D uOutput; void main() { ivec2 coord = ivec2(gl_GlobalInvocationID.xy); imageStore(uOutput, coord, vec4(1.0)); }
glUseProgram(computeProgram); glDispatchCompute(width / 16, height / 16, 1); // groups, not invocations glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); // before reading output
Compute built-ins
| Built-in | Type | Description |
|---|---|---|
gl_NumWorkGroups | uvec3 | Total groups dispatched |
gl_WorkGroupID | uvec3 | This group's index |
gl_LocalInvocationID | uvec3 | Thread index within group |
gl_GlobalInvocationID | uvec3 | WorkGroupID * WorkGroupSize + LocalInvocationID |
gl_LocalInvocationIndex | uint | Flattened local index |
gl_WorkGroupSize | uvec3 | From layout qualifier |
Fixed-Function: Primitive Assembly
// Specify how vertices are wound for face culling glFrontFace(GL_CCW); // GL_CCW (default) or GL_CW // Cull faces glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // GL_BACK (default), GL_FRONT, GL_FRONT_AND_BACK
Fixed-Function: Rasterization
glLineWidth(2.0f); // line width in pixels (≥1.0) glPointSize(5.0f); // when GL_PROGRAM_POINT_SIZE is disabled glEnable(GL_PROGRAM_POINT_SIZE); // let vertex shader set gl_PointSize // Polygon offset (for shadow maps / decals) glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(factor, units); // depth bias = factor * maxSlope + units * r // Wireframe / point mode glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // default glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // vertices only
Pipeline Object (Separate Shader Stages, GL 4.1+)
Allows mixing shader stages from different programs.
// Create separable program GLuint prog = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertSrc); // Build pipeline GLuint pipeline; glGenProgramPipelines(1, &pipeline); glBindProgramPipeline(pipeline); glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertProg); glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fragProg);
Stage bit flags
| Flag | Stage |
|---|---|
GL_VERTEX_SHADER_BIT | Vertex |
GL_TESS_CONTROL_SHADER_BIT | Tessellation control |
GL_TESS_EVALUATION_SHADER_BIT | Tessellation evaluation |
GL_GEOMETRY_SHADER_BIT | Geometry |
GL_FRAGMENT_SHADER_BIT | Fragment |
GL_COMPUTE_SHADER_BIT | Compute |
GL_ALL_SHADER_BITS | All stages |
Gotcha:
glUseProgram(0)is needed to reactivate a pipeline object after callingglUseProgramwith a monolithic program. The two APIs compete.