Used to build orthonormal bases (tangent, bitangent, normal = TBN matrix)
cross(a, b) = |a||b|sin(θ) * n̂
Order matters: cross(a, b) = -cross(b, a)
Normalization
normalize(v) = v / length(v)
Always normalize direction vectors before using in dot/cross products
Unnormalized normals are a common source of subtle shading bugs
Vector reflection formula
reflect(v, n) = v - 2 * dot(v, n) * n
Assumes n is unit length
Used in specular BRDF evaluation
Vector refraction (Snell’s law)
n1 * sin(θ1) = n2 * sin(θ2)
GLSL: refract(v, n, eta) where eta = n1/n2
Total internal reflection when 1 - eta² * (1 - dot(n,v)²) < 0
1.2 Coordinate Systems and Transforms
World space vs local space vs tangent space
World space: global scene coordinates
Local space: relative to an object’s origin
Tangent space: aligned to a surface normal (used for normal maps, BRDF sampling)
Building an orthonormal basis from a normal
Given N, construct T (tangent) and B (bitangent) such that {T, B, N} are mutually perpendicular unit vectors
Frisvad / Duff et al. method (numerically stable):
void buildONB(vec3 N, out vec3 T, out vec3 B) { float s = sign(N.z); float a = -1.0 / (s + N.z); float b = N.x * N.y * a; T = vec3(1.0 + s * N.x * N.x * a, s * b, -s * N.x); B = vec3(b, s + N.y * N.y * a, -N.y);}
Used to transform sampled directions from tangent space to world space
Homogeneous coordinates
4D representation: (x, y, z, w) where w=1 for points, w=0 for directions
Allows translation to be expressed as matrix multiplication
w=0 vectors are unaffected by translation — correct for normals and ray directions
Normal transform rule
Normals do NOT transform with the model matrix M
They transform with the inverse-transpose: N_world = transpose(inverse(M)) * N_local
If M is orthogonal (rotation only), then inverse(M) = transpose(M) so it simplifies to just M