novolis-governance / imports-todo/internal-novolis-audit/rendering-viewbasis-ray-generation.md
Rendering — adopt `ViewBasis` for host primary rays
Policies that keep the org coherent
dotnetgovernancenovolis
What
Wire `Novolis.Math.Geometry.ViewBasis` into the Rendering host path so primary-ray direction math lives in one tested place:
| Location | Today | Target |
|---|---|---|
| `PathTracerEngine.RenderSample` | Manual `tanHalfFov`, `u`/`v`, `Normalize(Forward + u*Right + v*Up)` | `ViewBasis.FromLookAt` + `ViewBasis.PrimaryRayDirection` |
| `CameraSnapshot.LookAt` | Duplicated Gram–Schmidt-style basis build | Delegate to `ViewBasis.FromLookAt`, map to snapshot fields |
ViewBasis and RigidTransform exist in Geometry but no consumer references them yet (grep 2026-05-25).
Why
- Dogfood and trace apps already build observers via `ViewPose` (Simulation) or `CameraSnapshot.LookAt` (Rendering); the basis math is duplicated twice with slightly different epsilon handling.
- Centralizing in Math keeps Simulation free of Rendering while giving Rendering a single dependency for ray generation (allowed: Rendering → Math).
- Reduces risk that CPU path tracer and future software rasterizers diverge from Simulation pick rays (
BuildPickRayin RagdollPlay, etc.).
How
- `CameraSnapshot` (
Novolis.Rendering.Runtime)
- In
LookAt, callViewBasis.FromLookAt(position, target, up)and copyForward,Right,Upinto the record. - Keep public surface unchanged (no new package dep beyond existing Geometry).
- `PathTracerEngine` (
Novolis.Rendering.Backends.Cpu)
- Construct
var basis = new ViewBasis(camera.Forward, camera.Right, camera.Up)once per tile or frame (or addCameraSnapshot.ToViewBasis()helper on Rendering side using those fields). - Replace lines 52–54 with
ViewBasis.PrimaryRayDirection(in basis, u, v, tanHalfFov, aspect).
- Tests
- Unit test:
CameraSnapshot.LookAtvsViewBasis.FromLookAt— forward/right/up agree withinGeometryConstantsscale. - Golden pixel or direction test: one pixel center ray matches previous implementation (regression).
- Optional follow-up (apps, not platform)
- RagdollPlay
BuildPickRaycan mirrorPrimaryRayDirectionfor mouse picking consistency.
Out of scope
- Moving GGX/glass/sky shading into Math (Rendering-only).
- ILGPU device kernels (see ilgpu-bvh-slab-parity.md).
Acceptance
- No manual
Cross/Normalizebasis construction inPathTracerEnginefor primary rays. CameraSnapshotandViewBasisstay aligned under test.