Camera-projection math as the shaders derive it from the projection matrix.
The point, line and splat shaders need a handful of view-dependent scales:
a point's pixel size per world radius, a line's pixel width per world width,
a splat's screen centre and the Jacobian that projects its covariance. All of
them are functions of the projection matrix P and the viewport, and the
shaders read P directly (GLSL projectionMatrix, TSL
cameraProjectionMatrix), which three sets per camera per draw. Deriving
them there, instead of pushing CPU-computed copies as uniforms, keeps them
correct for every camera the scene is drawn with: a cube-capture face (fov
−90, so P is flipped), an asymmetric frustum (setViewOffset, an XR eye), a
zoomed perspective camera, or an embedder's own camera.
This module is the CPU mirror of that shader math, for tests: it states the
formulas once, in a form the unit tests can check against the fov-based
formulas the CPU used to push as uniforms (kept as local references in
projection-math.test.ts) and against finite differences of the projection
itself.
Conventions: P is a THREE.Matrix4 elements array (column-major, so row r
of column c is P[c * 4 + r]); c is a view-space point; res is the
viewport size in pixels. Size terms use |P11| because a flipped projection
(CubeCamera) mirrors positions but must not negate sizes; positions and the
Jacobian keep the sign, and a splat's 2D covariance J Σ Jᵀ is invariant under
that flip.
Camera-projection math as the shaders derive it from the projection matrix.
The point, line and splat shaders need a handful of view-dependent scales: a point's pixel size per world radius, a line's pixel width per world width, a splat's screen centre and the Jacobian that projects its covariance. All of them are functions of the projection matrix P and the viewport, and the shaders read P directly (GLSL
projectionMatrix, TSLcameraProjectionMatrix), which three sets per camera per draw. Deriving them there, instead of pushing CPU-computed copies as uniforms, keeps them correct for every camera the scene is drawn with: a cube-capture face (fov −90, so P is flipped), an asymmetric frustum (setViewOffset, an XR eye), a zoomed perspective camera, or an embedder's own camera.This module is the CPU mirror of that shader math, for tests: it states the formulas once, in a form the unit tests can check against the fov-based formulas the CPU used to push as uniforms (kept as local references in
projection-math.test.ts) and against finite differences of the projection itself.Conventions:
Pis a THREE.Matrix4elementsarray (column-major, so row r of column c isP[c * 4 + r]);cis a view-space point;resis the viewport size in pixels. Size terms use |P11| because a flipped projection (CubeCamera) mirrors positions but must not negate sizes; positions and the Jacobian keep the sign, and a splat's 2D covariance J Σ Jᵀ is invariant under that flip.