Apply Brown–Conrady distortion to UV coordinates and write the result
into out. Returns out for ergonomic chaining.
Y-convention contract (MED-27): this function IS the canonical
distortion map, defined in TOP-DOWN uv space — the picking-system's
screen convention (event.clientY / height, y=0 at the top). The
TSL mega shader consumes it natively (WebGPURenderer's fullscreen
triangle delivers top-down uv). The GLSL mega shader runs only under
WebGLRenderer, whose fullscreen triangle delivers BOTTOM-UP uv — it
therefore applies the exact y-flip conjugation internally by
negating the two odd-symmetry intrinsics (principalPoint.y and
skew) in its K matrix rather than flipping uv. Radial/focal terms
are flip-even, which is why the historical mismatch was invisible
with the default (ppy = skew = 0) presets and why textual-identity
parity tests could not catch it. The conjugation-identity test in
lens-distortion.test.ts pins the relationship: do NOT "re-sync"
the GLSL matrix verbatim to this formula.
Algorithm (must stay in sync with mega/shader.glsl.ts::applyDistortion):
Apply Brown–Conrady distortion to UV coordinates and write the result into
out. Returnsoutfor ergonomic chaining.Y-convention contract (MED-27): this function IS the canonical distortion map, defined in TOP-DOWN uv space — the picking-system's screen convention (
event.clientY / height, y=0 at the top). The TSL mega shader consumes it natively (WebGPURenderer's fullscreen triangle delivers top-down uv). The GLSL mega shader runs only under WebGLRenderer, whose fullscreen triangle delivers BOTTOM-UP uv — it therefore applies the exact y-flip conjugation internally by negating the two odd-symmetry intrinsics (principalPoint.y and skew) in its K matrix rather than flipping uv. Radial/focal terms are flip-even, which is why the historical mismatch was invisible with the default (ppy = skew = 0) presets and why textual-identity parity tests could not catch it. The conjugation-identity test inlens-distortion.test.tspins the relationship: do NOT "re-sync" the GLSL matrix verbatim to this formula.Algorithm (must stay in sync with
mega/shader.glsl.ts::applyDistortion):xd = (1 + k_x · r²) · xn(likewise y).