• Möller–Trumbore Algorithm

    • The standard algorithm — used in virtually all ray tracers
    • Fast, numerically stable, returns barycentric coordinates
    • Paper: “Fast, Minimum Storage Ray/Triangle Intersection” (1997)

  • Derivation

    • A point on a triangle: P = (1-u-v)*v0 + u*v1 + v*v2
      • u, v ≥ 0 and u + v ≤ 1 for points inside the triangle
      • u, v are barycentric coordinates
    • Ray equation: P = origin + t * direction
    • Set equal: origin + t*dir = (1-u-v)*v0 + u*v1 + v*v2
    • Rearrange: [-dir, v1-v0, v2-v0] * [t, u, v]^T = origin - v0
    • Solve with Cramer’s rule

  • Implementation


  • Back-Face Culling

    • det < 0 means ray hits the back face of the triangle
    • For opaque geometry: if (det < 1e-8) return false; (cull back faces)
    • For double-sided materials: use abs(det)
    • In Vulkan: VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR disables culling

  • Barycentric Coordinates

    • (1-u-v, u, v) — weights for vertices v0, v1, v2
    • Interpolate any vertex attribute: attr = (1-u-v)*a0 + u*a1 + v*a2
    • Normal interpolation: N = normalize((1-u-v)*n0 + u*n1 + v*n2)
    • UV interpolation: uv = (1-u-v)*uv0 + u*uv1 + v*uv2
    • In Vulkan closest-hit shader: hitAttributeEXT vec2 baryCoords;
      • baryCoords.x = u, baryCoords.y = v
      • w = 1 - u - v

  • Watertight Intersection

    • Standard Möller–Trumbore can miss edges/vertices due to floating point
    • Watertight algorithm (Woop et al. 2013) — no gaps at shared edges
    • Important for production renderers — prevents light leaking through cracks
    • Technique: transform ray to a coordinate system where it points along +Z