GLSL built-in function
faceforward()
Returns N or -N, whichever points against the incoming direction I. Makes normals face the viewer for two-sided lighting.
Syntax
vec3 faceforward(vec3 N, vec3 I, vec3 Nref)
vec2 faceforward(vec2 N, vec2 I, vec2 Nref)Parameters
- N
- The normal to possibly flip.
- I
- The incoming (view) direction.
- Nref
- The reference normal used for the test, usually the same as N.
Return value
N if dot(Nref, I) < 0.0, otherwise -N.
Live example
Edit the code and the preview updates as you type.
How it works
Lighting usually assumes the normal points toward the viewer. When you see the back of a surface, such as the inside of a bowl, a leaf or a flag, the normal points away and dot(normal, light) gives the wrong answer.
faceforward(N, I, Nref) fixes that. It checks dot(Nref, I):
- negative, meaning the normal already faces the viewer: returns
N - otherwise: returns
-N
In the example the normals point away from the camera. The left half uses them as they are and stays almost dark; the right half passes them through faceforward and lights correctly.
Typical uses
- Two-sided surfaces: leaves, cloth, paper and planes seen from both sides.
- Robust lighting when you are not sure which way a computed normal points.
Common mistakes
- Passing the direction from the surface to the camera.
Iis the incoming direction, from the camera toward the surface. - Expecting it to normalize. It only flips the sign; normalize N yourself.
Related functions
dot()
Returns the dot product of two vectors. For unit vectors it measures how much they point the same way: 1.0 same direction, 0.0 perpendicular, -1.0 opposite.
reflect()
Returns the direction a ray bounces to after hitting a surface: reflect(I, N) = I - 2.0 * dot(N, I) * N.
normalize()
Returns a vector pointing in the same direction as x but with length 1.0. Keeps the direction, drops the size.