Rewrite the star field as instanced billboards
Plan step 3 promises glow and size driven by magnitude and spectral type, but the star field was a THREE.Points cloud and the WebGPU backend — the renderer this app targets — caps point primitives at a single pixel. Every one of the 8750 stars drew as an identical 1 px dot with a hard edge, discarding the magnitude sizing entirely; the class comment already admitted sizeNode only did anything on the WebGL2 fallback. Each star is now an instanced camera-facing quad on a SpriteNodeMaterial, which behaves the same on both backends. That material takes each instance's centre from positionNode rather than from an instance matrix, so position, colour and size ride on instanced buffer attributes and the mesh itself never moves. A radial falloff in opacityNode gives each star a bright core inside a soft halo. Sizes are angular rather than world-space. That keeps a star the same apparent size at any camera distance, which is both what the old screen-space points did and what is physically right: real stars are unresolvable point sources, so apparent size follows brightness, not distance. World-space quads would instead have made the whole field vanish at the camera's 2000 pc limit. Picking had to be rebuilt. Billboarding happens in the vertex shader, so the CPU-side geometry is one quad at the origin and Raycaster cannot see the star field at all. Selection is now done in screen space against the size each star is actually drawn at, which is strictly better than the fixed 1.2 pc world radius it replaces — that radius was over-permissive up close and sub-pixel at the far end of a 4000x camera range. Stars behind the camera need an explicit depth guard, because project() mirrors them back onto the screen. Two things only caught by running it. The colour attribute was declared with node type 'color', which is not a GLSL type, so the generated shader failed to compile — it has to be vec3. And the click tolerance was first written as a floor on the drawn radius, which flattened every star to one hit size, since a floor generous enough for the faintest star exceeds the brightest star's radius; adding the slop instead keeps a brighter star the easier target. Tests: 151 passing, up from 145. Verified in a real browser — shaders compile clean and the Playwright click-to-select flight passes against the new picking. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G
This commit is contained in:
@@ -27,10 +27,10 @@ npm run e2e:typecheck
|
||||
|
||||
## What's in it
|
||||
|
||||
**Galaxy view** — every HYG-catalogue star within 50 parsecs as a point field, positioned from
|
||||
real RA/Dec/parallax, coloured by spectral index and sized by magnitude. Names label the stars
|
||||
nearest the camera. Behind them sits a backdrop of notable deep-sky objects and a Milky Way
|
||||
panorama.
|
||||
**Galaxy view** — every HYG-catalogue star within 50 parsecs as instanced camera-facing
|
||||
billboards, positioned from real RA/Dec/parallax, coloured by spectral index and sized by
|
||||
magnitude. Names label the stars nearest the camera. Behind them sits a backdrop of notable
|
||||
deep-sky objects and a Milky Way panorama.
|
||||
|
||||
**System view** — selecting a star flies the camera continuously into its system rather than
|
||||
cutting to a new scene. The Sun gets the real solar-system bodies from JPL Horizons; other
|
||||
@@ -47,6 +47,11 @@ same place an in-scene click would.
|
||||
|
||||
- **Rendering** runs on Three.js `WebGPURenderer`, which falls back to a WebGL2 backend
|
||||
automatically. The render loop runs outside Angular's change detection.
|
||||
- **Stars are billboards, not points.** The WebGPU backend caps point primitives at a single
|
||||
pixel, so a points cloud renders every star as an identical dot regardless of magnitude. The
|
||||
star field is instanced quads on a `SpriteNodeMaterial` instead, which behaves the same on
|
||||
both backends. Their size is angular rather than world-space — real stars are unresolvable
|
||||
point sources, so apparent size should follow brightness, not distance.
|
||||
- **Two coordinate scales.** The galaxy view works in parsecs and the system view in AU —
|
||||
about eight orders of magnitude apart, which wrecks float precision if rendered in one unit
|
||||
space. The camera rig recentres the active star to the origin ("floating origin") and swaps
|
||||
|
||||
Reference in New Issue
Block a user