Skip to main content

Module planar_reflection

Module planar_reflection 

Source
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§

PlanarAssignment
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 (None when the budget is exhausted by earlier distinct planes, i.e. it falls back to the probe cube), and representatives is the deduplicated plane per slot (representatives.len() is the number of mirror renders the frame needs).
PlanarMatrices
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_PLANES alias it and stay in lockstep by construction. The per-frame budget passed to assign_planar_slots can 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 beyond max_slots overflows to None. 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 when point already 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 across plane_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.