FEATURE 4 — Add point lights to the scene
As a user lighting a mesh in the viewer, I want to add point lights from
the Lighting panel, tweak their color/intensity, and move them around in the
scene, so I can light the model exactly how I want for preview and screenshots.
Context
Lighting today is two fixed lights (Sun + Fill) defined by LightSettings
(GeneratePage.tsx:130), edited in the LightPopover (GeneratePage.tsx:144)
and rendered in Viewer3D.tsx:448. This adds user-placed point lights into
that same panel.
Scope
- In the existing Lighting panel (
LightPopover):
- An "Add point" button that adds a new point light.
- Below it, a small list of the added points, each row letting the user
pick its color and intensity (and remove it).
- Each point light is shown in the 3D scene as a billboard icon — a
recognizable light/bulb icon, rendered in world space at the light's
position and always facing the camera (editor-style gizmo, like Blender/Unity
light icons). It is not a plain sphere or dot.
- Point lights can be selected (click the icon) and moved in the scene
via the transform gizmo.
- They render live alongside the existing Sun + Fill lights.
Implementation
- State (
GeneratePage.tsx): add a pointLights: PointLight[] array next
to LightSettings. Each entry: { id, position:[x,y,z], color, intensity }.
- UI (
LightPopover, GeneratePage.tsx:144): add the "Add point" button
and render one row per point (color picker + intensity slider + remove),
mirroring the existing lightRow pattern.
- Viewer (
Viewer3D.tsx):
- Render the
pointLights array as <pointLight> elements (passed down like
lightSettings).
- At each light's world position, render a
<sprite> with a light/bulb
icon texture as the in-scene marker — billboard, camera-facing. Reuse the
sprite approach already used by GizmoBubbles (Viewer3D.tsx); the icon
can be drawn to a canvas (like makeAxisLabelTexture) or loaded from an
asset. Tint the icon with the light's color so it's identifiable.
- Keep the icon at a readable on-screen size regardless of zoom.
- Selection + move: clicking a light's icon selects it; attach the
transform gizmo (translate mode) to move it. Reuse the selection + gizmo
mechanism from the interactive-transform ticket so light markers and the mesh
share one selection model.
- No backend changes.
Acceptance criteria
Notes
- Cap the number of point lights (e.g. 4–6) for realtime performance.
- Light-icon selection should not conflict with mesh selection — clicking a
light selects the light, clicking the mesh selects the mesh.
- The light icon should not be affected by scene lighting (use
toneMapped={false} like the existing gizmo sprites) so it stays legible.
Estimate: M
FEATURE 4 — Add point lights to the scene
As a user lighting a mesh in the viewer, I want to add point lights from
the Lighting panel, tweak their color/intensity, and move them around in the
scene, so I can light the model exactly how I want for preview and screenshots.
Context
Lighting today is two fixed lights (Sun + Fill) defined by
LightSettings(
GeneratePage.tsx:130), edited in theLightPopover(GeneratePage.tsx:144)and rendered in
Viewer3D.tsx:448. This adds user-placed point lights intothat same panel.
Scope
LightPopover):pick its color and intensity (and remove it).
recognizable light/bulb icon, rendered in world space at the light's
position and always facing the camera (editor-style gizmo, like Blender/Unity
light icons). It is not a plain sphere or dot.
via the transform gizmo.
Implementation
GeneratePage.tsx): add apointLights: PointLight[]array nextto
LightSettings. Each entry:{ id, position:[x,y,z], color, intensity }.LightPopover,GeneratePage.tsx:144): add the "Add point" buttonand render one row per point (color picker + intensity slider + remove),
mirroring the existing
lightRowpattern.Viewer3D.tsx):pointLightsarray as<pointLight>elements (passed down likelightSettings).<sprite>with a light/bulbicon texture as the in-scene marker — billboard, camera-facing. Reuse the
sprite approach already used by
GizmoBubbles(Viewer3D.tsx); the iconcan be drawn to a canvas (like
makeAxisLabelTexture) or loaded from anasset. Tint the icon with the light's color so it's identifiable.
transform gizmo (translate mode) to move it. Reuse the selection + gizmo
mechanism from the interactive-transform ticket so light markers and the mesh
share one selection model.
Acceptance criteria
icon (not a plain dot/sphere), always facing the camera.
control; edits update both the light and its icon live.
the light follows.
Notes
light selects the light, clicking the mesh selects the mesh.
toneMapped={false}like the existing gizmo sprites) so it stays legible.Estimate: M