What Does the Vertex Shader Do in OpenGL?
The vertex shader is the first programmable stage in the modern OpenGL graphics pipeline, responsible for processing individual vertices one at a time. Its primary job is to transform 3D model coordinates into clip space, calculate per-vertex attributes such as normals, texture coordinates, and colors, and pass processed data downstream to later pipeline stages like the rasterizer and fragment shader.
Coordinate Space Transformations
The most critical task performed by a vertex shader is transforming geometry through several coordinate spaces. Raw vertex data typically enters the shader defined in local object space (or model space). The vertex shader applies transformation matrices to position the geometry within the 3D scene and prepare it for rendering:
- Model Transformation: Scales, rotates, and translates the vertex from its local coordinate system into the global world space.
- View Transformation: Reorients world-space coordinates relative to the camera's position and orientation, producing view space (or camera space).
- Projection Transformation: Applies an orthographic or perspective projection matrix to transform view coordinates into homogeneous clip coordinates.
The culmination of this mathematical transformation is assigned
directly to the built-in output variable gl_Position, which
defines where the vertex sits within normalized device coordinates (NDC)
after prospective division.
Attribute Passthrough and Interpolation Setup
In addition to positional data, meshes contain several per-vertex
attributes that downstream pipeline stages require. The vertex shader
accepts these inputs—often declared using the in
qualifier—processes or transforms them, and writes them to output
variables (out qualifier):
- Texture Coordinates: Passes UV coordinates directly to the fragment shader or adjusts them for tiling, scrolling, or atlas offsets.
- Normals and Tangents: Transforms surface normal vectors into world or view space using a normal matrix (the transpose of the inverse model-view matrix) so lighting calculations remain physically accurate when objects scale non-uniformly.
- Vertex Colors: Outputs base color channels associated with specific vertices, useful in low-poly styling or vertex painting workflows.
Once output from the vertex shader, these attributes are automatically interpolated across the primitive surface by fixed-function hardware during rasterization.
Procedural Vertex Animation and Deformation
Because vertex shaders run independently per vertex across thousands of GPU cores, they are well-suited for high-performance procedural animation and deformation. Instead of re-uploading modified mesh buffers from the CPU every frame, the vertex shader can modify vertex coordinates dynamically on the GPU:
- Skeletal Mesh Skinning: Blends vertex positions against multiple transformation matrices according to bone weights and indices, enabling animated characters.
- Procedural Displacements: Evaluates mathematical functions—such as sine waves for water surfaces or wind simulations for vegetation—directly altering vertex heights or offsets in real time.
- Morph Targets and Shape Keys: Linearly interpolates between multiple base vertex positions to animate facial expressions and organic transitions.
Lighting and Shading Calculations
While per-fragment lighting (such as the standard Blinn-Phong model evaluated in fragment shaders) provides superior visual fidelity, vertex shaders can perform per-vertex lighting computations (historically referred to as Gouraud shading). Computing ambient, diffuse, or specular lighting at the vertex level reduces GPU load significantly because vertex counts are almost always lower than pixel counts. The resulting color values are then smoothly interpolated across the face of the rendered polygon.
Point Sprite Sizing
When rendering GL_POINTS, the vertex shader is
responsible for dictating the screen-space footprint of each point
primitive. By assigning a floating-point value to the built-in variable
gl_PointSize (with GL_PROGRAM_POINT_SIZE
enabled on the context), the vertex shader dynamically controls point
dimensions based on distance to the camera, particle lifetimes, or
custom visual parameters.