How Do GLSL Exponential Functions Work?
GLSL provides a dedicated suite of built-in exponential functions
designed to handle powers, logarithms, roots, and base-\(e\) calculations efficiently on graphics
hardware. This article explores how functions such as pow,
exp, log, exp2,
log2, sqrt, and inversesqrt
operate under the hood, their component-wise vector handling, undefined
domain constraints, and underlying GPU hardware considerations.
Core Exponential Functions in GLSL
The OpenGL Shading Language (GLSL) defines standard math functions
across scalar floats and floating-point vectors (vec2,
vec3, vec4). When applied to vectors, all
operations execute component-wise.
Power and Roots
pow(x, y): Computes \(x^y\). The result is undefined if \(x < 0.0\), or if \(x == 0.0\) and \(y \le 0.0\). In practical GPU implementations,pow(x, y)is frequently evaluated asexp2(y * log2(x)), which explains why negative bases produce undefined results orNaN.sqrt(x): Returns the square root of \(x\), \(\sqrt{x}\). The value of \(x\) must be non-negative (\(x \ge 0.0\)).inversesqrt(x): Computes the reciprocal square root, \(1 / \sqrt{x}\). It requires \(x > 0.0\). Graphics hardware often optimizes vector normalization routines via dedicated reciprocal square root hardware pipelines.
Natural Exponents and Logarithms
exp(x): Computes the natural exponential function \(e^x\).log(x): Computes the natural logarithm \(\ln(x)\). The argument must satisfy \(x > 0.0\).
Base-2 Exponents and Logarithms
exp2(x): Computes \(2^x\). Base-2 operations map directly to native instructions in almost all modern GPU architectures.log2(x): Computes the base-2 logarithm \(\log_2(x)\). The input requires \(x > 0.0\).
Vector Processing and Component-Wise Execution
GLSL exponential functions are overloaded across primitive types and vector sizes:
// Scalar computation
float intensity = pow(0.5, 2.2);
// Vector computation (applied per-component)
vec3 color = vec3(0.2, 0.4, 0.8);
vec3 gammaCorrected = pow(color, vec3(1.0 / 2.2));
// Vector normalization using inversesqrt
vec3 normal = vec3(1.0, 2.0, 3.0);
vec3 normalized = normal * inversesqrt(dot(normal, normal));Because execution occurs on each vector component independently, passing mismatched vector dimensions causes compile-time errors unless combined with a matching scalar or vector overload.
GPU Hardware Architecture and Precision
GPUs execute exponential instructions using Special Function Units (SFUs) alongside standard Arithmetic Logic Units (ALUs).
- Base-2 Transformation: GPUs natively calculate
log2andexp2via SFU lookup tables and interpolation. Functions likeexp(x)orpow(x, y)are compiled into scaled base-2 instructions:
\[\text{exp}(x) = 2^{x \cdot \log_2(e)}\]
\[\text{pow}(x, y) = 2^{y \cdot \log_2(x)}\]
- Precision and Precision Qualifiers: In GLSL ES
(OpenGL ES / WebGL), qualifiers like
lowp,mediump, andhighpdetermine the precision of SFU evaluations.mediumporlowpexponential functions can introduce noticeable color banding in operations like gamma correction or specular highlight attenuation. - Handling Out-of-Range Inputs: Passing negative or
zero values where strictly positive inputs are required leads to
NaN(Not a Number) orInf(Infinity), causing visual artifacts like black or white pixel dropouts. Clamping inputs viamax(val, 0.0001)prevents domain violations before callingpoworlog.