Shader Lab
19.Fresnel / Rim Light

Fresnel / Rim Light

Arc 4 · 3D Lighting · Lesson 19 of 35
coordinate signal color
4.00

Purpose

Fresnel is the opposite question from specular — instead of "where does the normal point at the camera," it asks "where does the normal point away from the camera," and that grazing-angle rim is what makes silhouettes pop.

Key insight

Every surface reflects more light at glancing angles than head-on. Look at a lake from above — it's transparent. Look at it across the horizon — it's a mirror. That's Fresnel. The formula flips the specular dot: where dot(normal, view) is near zero (surface edge-on to the camera), 1 - dot(normal, view) is near one. Raise that to a power to control sharpness, and you get a bright ring along the silhouette.

Rim light does two things nothing else does: it separates a character from the background regardless of actual lighting, and it suggests soft-edged materials — skin, velvet, bubbles, force fields. It's also the term living inside PBR's Fresnel later, so learning it isolated means L21 has nothing new conceptually.

Drag edge-sharpness and watch the glow pull toward the true silhouette as the exponent climbs.

Break it

Edge-sharpness to its minimum (~0.5). The whole object glows like an unlit sphere pretending to be a light. The "edge" disappears because Fresnel with no power is just a soft inverse dot — a different effect entirely.

Teaches: Fresnel needs the exponent to read as an edge. Without it, you've built a cheap ambient bloom, not a rim.

Direct Claude

"pop the silhouette" rim light on "softer halo" edge-sharpness down "thin crisp outline glow" edge-sharpness up "backlit feel" rim color cool/blue, rim intensity up "skin sheen" rim with low power, warm tint
Meta-phrase you gain here: "grazing angle" is the right description — it covers rim light, Fresnel in PBR, water at the horizon, and any effect that brightens where a surface turns edge-on to the viewer.
Combines with: L17/L18 (sits as a third term in the lighting sum), L20 (toon often quantizes rim into a hard band), L21 (PBR Fresnel is this exact math wired into the spec reflection). Also a staple of character portraits and sci-fi shielding.
the vertex + fragment shader running above
// VERTEX — normal + world position (we need view direction in frag)
varying vec3 vNormal;
varying vec3 vWorldPos;

void main() {
  vNormal = normalize(normalMatrix * normal);
  vec4 wp = modelMatrix * vec4(position, 1.0);
  vWorldPos = wp.xyz;
  gl_Position = projectionMatrix * viewMatrix * wp;
}

// FRAGMENT — Lambert + Fresnel rim (grazing-angle highlight)
uniform vec3 uLightDir;
uniform vec3 uBaseColor;
uniform vec3 uRimColor;
uniform float uEdgeSharpness;
uniform vec3 uCameraPos;

varying vec3 vNormal;
varying vec3 vWorldPos;

void main() {
  vec3 n = normalize(vNormal);
  vec3 v = normalize(uCameraPos - vWorldPos);

  float diffuse = max(0.0, dot(n, uLightDir));
  float rim = pow(1.0 - max(0.0, dot(n, v)), uEdgeSharpness);

  vec3 col = uBaseColor * (0.08 + diffuse) + uRimColor * rim;
  gl_FragColor = vec4(col, 1.0);
}