Files
skills/shader-dev/reference/sdf-tricks.md
shihao 6487becf60 Initial commit: add all skills files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 16:52:49 +08:00

2.6 KiB
Raw Blame History

SDF Tricks Detailed Reference

Prerequisites

  • Understanding of signed distance fields and ray marching
  • Basic SDF primitives and boolean operations
  • FBM / procedural noise fundamentals

Lipschitz Condition and FBM Detail

An SDF must satisfy the Lipschitz condition: |f(a) - f(b)| ≤ |a - b| (gradient magnitude ≤ 1). This guarantees that stepping by the SDF value is always safe — no surface exists within that radius.

When adding FBM noise to an SDF, the noise derivatives can violate Lipschitz:

  • Raw noise amplitude of 0.1 with frequency 20 has gradient ~2.0, breaking the condition
  • This causes ray marching to overshoot, creating holes and artifacts

Solutions:

  1. Amplitude limiting: Keep amplitude × frequency < 1.0 across all octaves
  2. Distance fade: d += amp * fbm(p * freq) * smoothstep(fadeStart, 0.0, d) — detail only appears near the surface where overshoot distance is small
  3. Step size reduction: Multiply ray step by 0.5-0.7, trading speed for stability

Bounding Volume Strategies

Hierarchical Bounding

For scenes with N objects, test bounding volumes in order of increasing cost:

Level 1: Scene bounding sphere (1 evaluation)
Level 2: Object group bounds (few evaluations)
Level 3: Individual object SDF (full cost)

Spatial Partitioning

For repeating structures, combine domain repetition with bounds:

float map(vec3 p) {
    vec3 q = mod(p + 2.0, 4.0) - 2.0;  // repeat every 4 units
    // Only evaluate detail if within local bounding sphere
    float bound = length(q) - 1.5;
    if (bound > 0.2) return bound;
    return detailedSDF(q);
}

Binary Search Convergence

After N iterations of binary search, the position error is initialStep / 2^N:

  • 4 iterations: 1/16 of initial step size
  • 6 iterations: 1/64 of initial step size (sub-pixel at typical resolutions)
  • 8 iterations: 1/256 (overkill for most uses)

6 iterations is the practical sweet spot — gives sub-pixel precision without wasting GPU cycles.

XOR Operation Mathematics

opXor(a, b) = max(min(a, b), -max(a, b))

This is equivalent to: union(a, b) AND NOT intersection(a, b) — the symmetric difference. Geometry exists where exactly one shape is present but not both. Useful for creating lattice structures and interlocking patterns.

Interior SDF Pattern Techniques

When the camera is inside an SDF (d < 0), the negative distance still gives useful information:

  • abs(d) gives distance to nearest surface from inside
  • Combine with repeating patterns using fract() to create infinite interior structures
  • Use max(outerSDF, innerSDF) to confine interior patterns within the outer shell