Initial commit: add all skills files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
87
shader-dev/reference/texture-mapping-advanced.md
Normal file
87
shader-dev/reference/texture-mapping-advanced.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Advanced Texture Mapping Detailed Reference
|
||||
|
||||
## Prerequisites
|
||||
- Screen-space derivatives (`dFdx`, `dFdy`)
|
||||
- `textureGrad()` function usage
|
||||
- Basic ray marching
|
||||
|
||||
## Triplanar vs Biplanar Cost Analysis
|
||||
|
||||
| Aspect | Triplanar | Biplanar |
|
||||
|--------|-----------|----------|
|
||||
| Texture fetches | 3 | 2 |
|
||||
| ALU operations | Lower | Higher (axis selection) |
|
||||
| Bandwidth | Higher | Lower |
|
||||
| Visual quality | Baseline | Equivalent (k≥8) |
|
||||
| Best for | Bandwidth-rich GPUs | Mobile, bandwidth-limited |
|
||||
|
||||
Modern GPUs are typically bandwidth-limited rather than ALU-limited, making biplanar the better default choice.
|
||||
|
||||
### Weight Remapping Mathematics
|
||||
|
||||
The biplanar weight formula `clamp((w - 0.5773) / (1.0 - 0.5773), 0, 1)` ensures:
|
||||
- At normals aligned with one axis: weight = 1.0 (clean projection)
|
||||
- At 45° diagonals where 2 axes are equal: smooth transition
|
||||
- At the cube diagonal (1/√3 ≈ 0.5773): weight = 0.0, but this is the point where the third (discarded) projection would be needed — biplanar's approximation error is maximal here but visually acceptable
|
||||
|
||||
### Gradient Propagation
|
||||
|
||||
Using `textureGrad()` instead of `texture()` is essential because:
|
||||
1. Axis selection (`ma`, `me`) creates UV discontinuities at projection boundaries
|
||||
2. Hardware `texture()` computes mip from implicit derivatives, which spike at discontinuities → visible seams
|
||||
3. `textureGrad()` with manually propagated `dFdx(p)`, `dFdy(p)` bypasses this, keeping gradients smooth across boundaries
|
||||
|
||||
## Ray Differential Mathematics
|
||||
|
||||
### Problem Statement
|
||||
In rasterization, `dFdx`/`dFdy` of texture coordinates work naturally because adjacent pixels map to nearby surface points. In ray marching, adjacent pixels may hit completely different objects → broken mip selection.
|
||||
|
||||
### Solution: Tangent Plane Intersection
|
||||
|
||||
Given:
|
||||
- Primary ray hits surface at `pos` with normal `nor`
|
||||
- Neighbor pixel ray `rd_neighbor` originates from `ro_neighbor`
|
||||
|
||||
The neighbor ray's intersection with the tangent plane at `pos`:
|
||||
```
|
||||
t_neighbor = dot(pos - ro_neighbor, nor) / dot(rd_neighbor, nor)
|
||||
pos_neighbor = ro_neighbor + rd_neighbor * t_neighbor
|
||||
```
|
||||
|
||||
The difference `pos_neighbor - pos` gives the world-space footprint of one pixel at the hit point.
|
||||
|
||||
### For Perspective Cameras (Common Case)
|
||||
```
|
||||
ro is the same for all pixels, only rd varies:
|
||||
dposdx = t * (rdx * dot(rd, nor) / dot(rdx, nor) - rd)
|
||||
dposdy = t * (rdy * dot(rd, nor) / dot(rdy, nor) - rd)
|
||||
```
|
||||
Where `rdx = rd + dFdx(rd)` and `rdy = rd + dFdy(rd)`.
|
||||
|
||||
### Chain Rule for Texture Coordinates
|
||||
If texture mapping function is `uv = f(pos)`:
|
||||
```
|
||||
duvdx = Jacobian(f) × dposdx
|
||||
duvdy = Jacobian(f) × dposdy
|
||||
```
|
||||
For simple planar mapping `uv = pos.xz`:
|
||||
```
|
||||
duvdx = dposdx.xz
|
||||
duvdy = dposdy.xz
|
||||
```
|
||||
|
||||
## Texture Repetition Theory
|
||||
|
||||
### Why Tiling is Visible
|
||||
Human vision excels at detecting:
|
||||
1. **Periodic patterns**: Regular grid alignment
|
||||
2. **Unique features**: Distinctive spots/marks that repeat identically
|
||||
3. **Phase alignment**: All tiles start at the same phase
|
||||
|
||||
### Breaking Repetition
|
||||
Each method targets different cues:
|
||||
- **Random offset** (Method A): Breaks phase alignment, 4 fetches
|
||||
- **Voronoi blend**: Breaks grid structure entirely, 9 fetches (expensive)
|
||||
- **Virtual pattern** (Method B): Breaks unique features cheaply, 2 fetches
|
||||
|
||||
Method B is preferred for real-time use — the low-frequency index variation is cache-friendly and the two texture fetches share locality.
|
||||
Reference in New Issue
Block a user