home/ atoms/ sdf-normal-finite-difference

Raymarching surface normals are estimated by sampling the SDF gradient at nearby points

Once a raymarched ray hits a surface, lighting needs the surface normal, but an SDF scene has no stored vertex normals. The normal is estimated numerically as the gradient of the distance field: evaluate the SDF at the hit point and at points offset by a tiny epsilon along each axis, and take the differences. Normalizing the resulting vector gives a unit surface normal pointing away from the surface. Smaller epsilon gives a more accurate normal but can amplify numerical noise; too large a value smooths away fine detail. This finite-difference normal is the standard technique for lighting any implicit-surface / SDF scene.

Examples

vec3 calcNormal(vec3 p) {
  vec2 e = vec2(0.001, 0.0);
  return normalize(vec3(
    map(p + e.xyy) - map(p - e.xyy),
    map(p + e.yxy) - map(p - e.yxy),
    map(p + e.yyx) - map(p - e.yyx)));
}

Assessment

Compute the normal of a raymarched sphere via finite differences and visualize it as RGB. Then shrink and enlarge epsilon and describe how the shading changes.

“To find the gradient of a surface, we need two points. We'll take a point on the surface of the sphere and subtract a small number from it to get the second point.”