What Does the dot Function Compute in GLSL?
The dot function in OpenGL Shading Language (GLSL)
calculates the mathematical dot product—also known as the scalar
product—between two vectors of identical dimensions. In real-time
computer graphics, this operation is one of the most fundamental vector
computations, serving as the backbone for calculating lighting angles,
surface orientations, projections, and shading falloffs.
Mathematical Definition
The dot product of two vectors \(\mathbf{a}\) and \(\mathbf{b}\) multiplies corresponding components and sums the results. For an \(n\)-dimensional vector:
\[\mathbf{a} \cdot \mathbf{b} = \sum_{i=1}^{n} a_i b_i\]
For a 3D vector (vec3), the calculation in GLSL
evaluates as:
\[\mathbf{a} \cdot \mathbf{b} = a_x b_x + a_y b_y + a_z b_z\]
The geometric definition relates the dot product to the lengths of both vectors and the cosine of the angle \(\theta\) between them:
\[\mathbf{a} \cdot \mathbf{b} = \Vert{}\mathbf{a}\Vert{} \Vert{}\mathbf{b}\Vert{} \cos\theta\]
When both input vectors are normalized to unit length (\(\Vert{}\mathbf{a}\Vert{} = 1\) and \(\Vert{}\mathbf{b}\Vert{} = 1\)), the formula simplifies directly to:
\[\mathbf{a} \cdot \mathbf{b} = \cos\theta\]
GLSL Syntax and Supported Types
The dot function accepts floating-point vectors
(vec2, vec3, vec4) as well as
double-precision floating-point vectors (dvec2,
dvec3, dvec4). Both arguments must have the
exact same type and dimension, and the function returns a single scalar
value (float or double).
// Example vector declarations
vec3 normal = normalize(vNormal);
vec3 lightDir = normalize(uLightPosition - vPosition);
// Compute scalar dot product
float NdotL = dot(normal, lightDir);Interpreting the Output
When evaluating normalized vectors, the return value of
dot(a, b) falls strictly within the range \([-1.0, 1.0]\):
- \(1.0\): The vectors point in the exact same direction (\(\theta = 0^\circ\)).
- \(0.0\): The vectors are orthogonal or perpendicular to each other (\(\theta = 90^\circ\)).
- \(-1.0\): The vectors point in directly opposite directions (\(\theta = 180^\circ\)).
- Positive value (\(> 0.0\)): The vectors point generally toward the same hemisphere (\(\theta < 90^\circ\)).
- Negative value (\(< 0.0\)): The vectors point away from each other into opposite hemispheres (\(\theta > 90^\circ\)).
Common Use Cases in Shaders
1. Lambertian Diffuse Lighting
Diffuse illumination relies on Lambert's cosine law, where surface brightness is proportional to the cosine of the angle between the surface normal \(\mathbf{N}\) and the incident light direction \(\mathbf{L}\). Because lighting cannot be negative, results are clamped to zero:
float diffuse = max(dot(normal, lightDirection), 0.0);2. Specular Highlights
In the Blinn-Phong reflection model, specular reflection is determined by taking the dot product between the surface normal \(\mathbf{N}\) and the halfway vector \(\mathbf{H}\) between the view direction and light direction:
float specular = pow(max(dot(normal, halfVector), 0.0), shininess);3. Vector Length and Distance
The squared length of a vector can be computed using a dot product with itself, which avoids an expensive square root operation when comparing relative distances:
float lengthSquared = dot(v, v);
float len = sqrt(dot(v, v)); // Equivalent to length(v)4. Fresnel and Rim Lighting Effects
Rim lighting and Fresnel equations frequently evaluate the dot product between the surface normal and the view direction (\(\mathbf{N} \cdot \mathbf{V}\)) to detect glancing angles along polygon silhouettes.