Vertex Shader is a programmable stage of the graphics pipeline that processes each vertex of a 3D model independently. According to Khronos Group, 2025, the vertex shader takes vertex attributes as input — coordinates, normals, color and texture coordinates — and transforms them according to the specified logic. Vertex Shader executes for each vertex independently, allowing computations to be efficiently parallelized across thousands of GPU cores.
Key Takeaways
Vertex Shader is a programmable stage of the graphics pipeline that processes each vertex of a 3D model individually. A vertex is a point in three-dimensional space containing attributes: xyz coordinates, normals, color and UV texture coordinates.
Unlike the fixed-function pipeline where transformations were performed according to a rigid algorithm, Vertex Shader gives the developer full control over vertex transformation. This allows implementing procedural animation, model deformation, skeletal skinning and any mathematical transformations on the GPU side.
The OpenGL ES graphics pipeline includes a sequence of stages from input data to the final image. Vertex Shader is located after the vertex assembly stage and before the rasterization stage. Each vertex passed from the CPU through a vertex buffer passes through the Vertex Shader exactly once, and the result is forwarded to the next stage for primitive assembly.
| Pipeline Stage | Purpose |
|---|---|
| Vertex Specification | Transfer of vertex data and attributes from VBO |
| Vertex Shader | Processing each vertex, coordinate transformation |
| Tessellation | Optional subdivision of geometry into sub-primitives |
| Geometry Shader | Optional generation or removal of primitives |
| Rasterization | Conversion of primitives into fragments for filling |
Vertex Shader receives vertex attributes from the vertex buffer (VBO) through vertex attribute pointers configured in the CPU code. The developer writes shader code in GLSL (OpenGL Shading Language) or an equivalent language, which is compiled by the GPU driver into machine instructions for the specific chip.
For each vertex, the Vertex Shader sequentially performs three operations: reading input attributes — applying transformations defined by the developer — writing results to output variables. The minimum required output is the vertex position in clip space (gl_Position). All other output data (color, normals, texture coordinates) are interpolated and passed to the next stage — the Fragment Shader.
#version 300 es
in vec3 aPosition;
in vec2 aTexCoord;
uniform mat4 uMVP;
out vec2 vTexCoord;
void main() {
gl_Position = uMVP * vec4(aPosition, 1.0);
vTexCoord = aTexCoord;
}
Vertex Shader solves a wide range of graphics pipeline tasks related to geometry transformation. Each task is implemented through mathematical operations on vectors and matrices, executed in parallel for thousands of vertices simultaneously.
The basic and most common task is multiplying vertex coordinates by model, view and projection matrices (MVP). The MVP matrix transforms a vertex from the local model space into clip space, which is then normalized and converted to screen coordinates in the automatic pipeline stages.
For animated characters, the Vertex Shader implements skeletal animation (skinning). Each vertex is bound to several bones with specific weights. Vertex blending — a weighted sum of transformations from the bound bones — allows smooth deformation of the character's skin when the skeleton moves.
The Vertex Shader can modify geometry based on time or other uniform parameters without CPU involvement. Wave deformation, Perlin noise displacement and water ripple effects — all these effects are implemented in the vertex shader without reloading geometry from RAM.
Although both types of shaders are programmable stages of the graphics pipeline, Vertex Shader and Fragment Shader solve fundamentally different tasks and operate at different stages of image processing.
| Characteristic | Vertex Shader | Fragment Shader |
|---|---|---|
| Input data | Vertex attributes from VBO | Interpolated data from VS |
| Number of invocations | Number of vertices | Number of fragments |
| Primary task | Geometry transformation | Pixel color calculation |
| Computational load | Geometry complexity | Screen resolution |
| Texture access | Limited (via texture lookup) | Full access |
The key difference is the invocation frequency. Vertex Shader is called once per vertex, while Fragment Shader is called for each fragment (pixel). In a high-resolution scene, the number of Fragment Shader invocations exceeds the number of Vertex Shader invocations by thousands of times, making pixel shader optimization even more critical.
Vertex Shader performance is critically important for real-time applications, especially in mobile development with limited power consumption. The main performance factors are the number of vertices, shader code complexity and GPU memory bandwidth.
To reduce the load on the Vertex Shader, the following approaches are used. Level of Detail (LOD) — switching to simplified model versions when the camera moves away from the object. Instancing — drawing the same geometry multiple times with different transformation matrices in a single draw call.
// Vertex Shader with instancing support
in vec3 aPosition;
in mat4 aInstanceMatrix;
uniform mat4 uViewProjection;
void main() {
vec4 worldPos = aInstanceMatrix * vec4(aPosition, 1.0);
gl_Position = uViewProjection * worldPos;
}
Vertex Shader across different graphics APIs has similar logic but different syntax and naming conventions. Let's look at implementing a basic vertex shader in GLSL for OpenGL ES 3.0 and in Metal Shading Language for iOS and macOS.
#version 300 es
in vec4 position;
in vec3 normal;
in vec2 texcoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
out vec3 vNormal;
out vec2 vTexCoord;
out vec3 vPosition;
void main() {
vec4 mvPosition = modelViewMatrix * position;
vPosition = mvPosition.xyz;
vNormal = normalMatrix * normal;
vTexCoord = texcoord;
gl_Position = projectionMatrix * mvPosition;
}
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
};
struct VertexOut {
float4 position [[position]];
float3 worldNormal;
};
vertex VertexOut
vertexMain(VertexIn in [[stage_in]],
constant float4x4& mvp [[buffer(1)]]) {
VertexOut out;
out.position = mvp * float4(in.position, 1.0);
out.worldNormal = in.normal;
return out;
}
Frequently Asked Questions
Vertex Shader is a GPU program that processes each vertex of a 3D model and transforms its coordinates into screen coordinates. Imagine a model as a mesh of points; the vertex shader moves these points according to specified mathematical rules.
Vertex Shader processes vertices and handles geometry, while Fragment Shader determines the color of each pixel. The former is called for each vertex (thousands), the latter for each pixel (millions).
Vertex Shader is written in a language corresponding to the graphics API: GLSL for OpenGL ES, Metal Shading Language for Metal API on iOS/macOS, HLSL for Direct3D. Conceptually, all of them perform the same operations on vertices.
The complexity of the vertex shader directly affects FPS: more instructions per vertex = longer processing time. Optimization includes reducing the number of vertices through LOD, using instancing and minimizing conditional branches in the shader code.
Main gaming tasks: coordinate transformation through MVP matrices, skinning of animated characters, procedural deformation of clothing and hair, morphing between facial expressions and particle effects with GPU animation.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also