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

64 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```glsl
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