What Does the GLSL Vertex Shader Stage Do?
The vertex shader is the first programmable stage in the modern OpenGL graphics pipeline, responsible for processing individual vertices provided by application vertex buffer objects. Its primary duties include transforming vertex coordinates from local model space to clip space, calculating per-vertex lighting or shading attributes, managing point sizes, and passing interpolated data forward to subsequent pipeline stages such as the fragment shader.
Coordinate Transformation
The fundamental role of a vertex shader is transforming geometry across several coordinate spaces. 3D models are defined in local object space (model coordinates), but the rendering pipeline requires coordinates in clip space so the fixed-function rasterizer knows where to draw geometry on screen.
A standard vertex shader achieves this by multiplying incoming vertex positions by a series of transformation matrices:
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;
void main()
{
gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0);
}- Model Matrix: Moves and scales vertices from local object space into the shared 3D world space.
- View Matrix: Transforms world space coordinates into camera (eye) space.
- Projection Matrix: Applies perspective or
orthographic projection, transforming camera space coordinates into
homogeneous clip space and populating the built-in
gl_Positionoutput variable.
Passing Per-Vertex Attributes
Vertex shaders receive custom per-vertex inputs called vertex attributes (such as UV texture coordinates, surface normals, tangents, and vertex colors) and prepare them for later stages:
- Interpolation Setup: By declaring
outvariables, the vertex shader outputs values that the rasterizer automatically interpolates across the surface of triangles or lines before reaching the fragment shader. - Normal Transformations: Normals must be transformed into world or view space using a specialized normal matrix (the transpose of the inverse of the model matrix) to maintain correct lighting vectors under non-uniform scaling.
Vertex-Level Lighting and Deformation
While modern rendering pipelines often compute lighting per fragment for higher visual fidelity, the vertex shader can handle various performance-critical computations:
- Gouraud Shading: Calculates lighting intensity at each vertex and interpolates the final color across the primitive, significantly reducing per-pixel computational overhead.
- Skeletal Animation (Skinning): Evaluates bone weights and bone transform matrices to dynamically deform character meshes on the GPU.
- Procedural Vertex Displacement: Generates dynamic effects such as ocean waves, terrain height displacement, or wind blowing through foliage by modifying vertex positions directly in shader code.
Point Rasterization Control
When rendering primitives using point primitives
(GL_POINTS), the vertex shader controls the rendered size
of each point by writing a floating-point value to the built-in variable
gl_PointSize. This is commonly used in particle systems to
simulate depth scaling or varying particle radii.