Expand description
Planar reflection math: mirror a camera across a world plane and oblique-clip the projection so geometry behind the plane never leaks into the reflection.
Backend-agnostic and pure (mirrors gfx/reflection_probe.rs). A reflective flat surface (water, a mirror floor) renders the scene a second time from the camera reflected across its plane; the reflective surface then samples that render projectively. This module produces the matrices that pass needs.
Conventions match crate::gfx::projection: column-major storage
m[col][row], a right-handed view looking down -z, and a perspective
projection mapping depth to [0, 1] (Metal / D3D clip space). A plane is
[nx, ny, nz, d] with n unit-length, satisfying n . p + d = 0 for points
on it; n . p + d > 0 is the side the normal points toward.
Structs§
- Planar
Assignment - The result of grouping a list of reflection planes into a bounded number of
distinct slots:
slots[i]is the slot a plane maps to (Nonewhen the budget is exhausted by earlier distinct planes, i.e. it falls back to the probe cube), andrepresentativesis the deduplicated plane per slot (representatives.len()is the number of mirror renders the frame needs). - Planar
Matrices - The matrices a planar reflection pass needs for one mirror plane.
Constants§
- MAX_
PLANAR_ PLANES - The engine-wide capacity ceiling for distinct reflection planes: water
surfaces and glass panes combined. Each plane is a full render-resolution MSAA scene
re-render, so this bounds the per-frame planar cost and the reserved mirror
target VRAM; reflectors past the active budget fall back to the box-projected
probe cube. This is the CAPACITY every backend sizes its mirror targets / ICB
slots / resolve SRVs against, so the three
planar::MAX_PLANAR_PLANESalias it and stay in lockstep by construction. The per-frame budget passed toassign_planar_slotscan be lower (scaled down under a quality preset / GPU tier) but never higher.
Functions§
- assign_
planar_ slots - Group near-coplanar reflection planes so each distinct plane renders one mirror
pass, capped at
max_slots. Planes are matched sign-invariantly (a plane and its flip are the same surface): two planes share a slot when their unit normals are near-parallel and their offset along the normal matches. A plane coplanar with an already-assigned slot always reuses it (even past the budget); only a NEW distinct plane beyondmax_slotsoverflows toNone. Input order sets slot priority, so callers list higher-priority planes (e.g. water) first. - orient_
plane_ toward - Flip a plane so its normal points toward
point(the kept side faces the camera). The reflection matrix is sign-invariant, but the oblique near-plane clip is not: it keeps the +n side, so the normal must face the viewer or the mirror render clips the wrong half. A no-op whenpointalready lies on the +n side, which is the horizontal-water-above-camera case, so water renders identically with or without this orientation. - planar_
matrices - Build the mirror view + oblique-clipped view-projection + reflected eye for a
camera (
view/proj/cam_pos) reflecting acrossplane_world. The clip plane is nudged a hair below the surface (clip_bias, world units along the normal) so fragments exactly on the surface are not clipped by precision. - planar_
pass_ needed - Whether the transparent pass has to render its planar mirrors this frame.