Skip to content

Add gravitational-lensing prototype (SIS thin-lens, vertex-stage)#361

Open
rulkens wants to merge 2 commits into
mainfrom
claude/skymap-gravitational-lensing-57c5cg
Open

Add gravitational-lensing prototype (SIS thin-lens, vertex-stage)#361
rulkens wants to merge 2 commits into
mainfrom
claude/skymap-gravitational-lensing-57c5cg

Conversation

@rulkens

@rulkens rulkens commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Deflect background galaxies around a foreground lens directly in the
points vertex stage, where each source's distance from the camera and
the lens is known. This makes the effect physically honest: only sources
behind the lens are bent, and the deflection scales with D_ls/D_s — the
kind of distance-dependence a screen-space post-process pinch filter
can't express (it would bend the foreground and Milky Way too).

The lens model is a singular isothermal sphere (SIS): constant Einstein
deflection theta_E, source at separation beta imaged outward to
theta = beta + theta_E, so sources near the line of sight pile into an
Einstein ring. A Gaussian envelope (~3 theta_E) localises the effect so
an idealised SIS doesn't shift the whole sky. New helper:
shaders/lib/lensing.wesl.

Prototype shortcuts (to be formalised in a spec/plan):

  • Lens centre is the camera orbit target (the thing you've zoomed into),
    not a mass-weighted cluster.
  • theta_E is a UI-exaggerated angle in degrees (real cluster Einstein
    radii are ~arcseconds, invisible at zoom).
  • Only the SIS primary image is rendered; the inner counter-image and
    NFW profiles are follow-ups.

Wiring:

  • io.wesl Uniforms gains a lensing block appended at offset 176 (struct
    grows 176 -> 208 bytes); picker in-place writes are all < 176 so they
    stay valid and picking lenses with the same params.
  • pointRenderer packs lensCenterWorld/lensEnabled/lensThetaE; threaded
    via PointDrawSettings + pointSpritesPass.
  • Toggle + exaggerated Einstein-radius slider live in the Debug panel
    (debug settings cluster), off by default. Settings auto-wake the
    renderer via the existing WAKE_ROUTES.

Tests updated for the new debug fields + PointDrawSettings; full suite
green (2978 tests). WESL link validated via the real wesl-plugin under
vitest (pointRenderer test imports points/vertex.wesl?static).

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Q7a4Pwz8yTrDtRcwGtojZb

Deflect background galaxies around a foreground lens directly in the
points vertex stage, where each source's distance from the camera and
the lens is known. This makes the effect physically honest: only sources
*behind* the lens are bent, and the deflection scales with D_ls/D_s — the
kind of distance-dependence a screen-space post-process pinch filter
can't express (it would bend the foreground and Milky Way too).

The lens model is a singular isothermal sphere (SIS): constant Einstein
deflection theta_E, source at separation beta imaged outward to
theta = beta + theta_E, so sources near the line of sight pile into an
Einstein ring. A Gaussian envelope (~3 theta_E) localises the effect so
an idealised SIS doesn't shift the whole sky. New helper:
shaders/lib/lensing.wesl.

Prototype shortcuts (to be formalised in a spec/plan):
- Lens centre is the camera orbit target (the thing you've zoomed into),
  not a mass-weighted cluster.
- theta_E is a UI-exaggerated angle in degrees (real cluster Einstein
  radii are ~arcseconds, invisible at zoom).
- Only the SIS primary image is rendered; the inner counter-image and
  NFW profiles are follow-ups.

Wiring:
- io.wesl Uniforms gains a lensing block appended at offset 176 (struct
  grows 176 -> 208 bytes); picker in-place writes are all < 176 so they
  stay valid and picking lenses with the same params.
- pointRenderer packs lensCenterWorld/lensEnabled/lensThetaE; threaded
  via PointDrawSettings + pointSpritesPass.
- Toggle + exaggerated Einstein-radius slider live in the Debug panel
  (debug settings cluster), off by default. Settings auto-wake the
  renderer via the existing WAKE_ROUTES.

Tests updated for the new debug fields + PointDrawSettings; full suite
green (2978 tests). WESL link validated via the real wesl-plugin under
vitest (pointRenderer test imports points/vertex.wesl?static).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7a4Pwz8yTrDtRcwGtojZb
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 21, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
skymap 95f4c16 Commit Preview URL

Branch Preview URL
Jun 23 2026, 10:45 PM

Extends the lensing prototype with the Navarro–Frenk–White profile and a
mode switch. NFW deflection follows the closed-form g(x)/x (Wright &
Brainerd 2000): it rises from the core, peaks near the scale radius r_s,
then falls as ~ln(x)/x — the curvature that gives real clusters an inner
radial critical curve, which SIS's constant deflection can't produce.

Computed analytically in the shader rather than via a baked 1D LUT: it's
a few transcendentals per vertex (cheap) and avoids forcing a
texture+sampler bind group onto the SHARED pick pipeline (the pick pass
reuses points/vertex.wesl). arccosh(1/x) is expanded to its log form so
only core WGSL log/acos/sqrt are needed. The shape is peak-normalised
(÷0.3122) so the strength knob reads as peak deflection in BOTH modes —
toggling SIS↔NFW keeps the ring roughly sized and only changes profile.

The behind-lens gate, D_ls/D_s distance scaling, and distance-preserving
displacement are profile-agnostic and unchanged. NFW needs no Gaussian
envelope — g(x)/x self-localises at both small and large x.

Wiring:
- lib/lensing.wesl: nfwShape() + lensDeflect() gains mode + scaleRadiusMpc.
- io.wesl: two reserved pad slots become lensMode (u32) + lensScaleRadius
  (f32) — NO struct size change (still 208 bytes), pick offsets untouched.
- New LensMode type ('sis'|'nfw'); debug settings gain lensMode +
  lensScaleRadiusMpc with slice actions, selectors, defaults.
- DebugPanel lensing section gains an SIS/NFW radio toggle and an
  NFW-only scale-radius slider (hidden in SIS mode).

Full suite green (2978 tests); typecheck + prettier clean. WESL link
validated via the real wesl-plugin under vitest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7a4Pwz8yTrDtRcwGtojZb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants