Skip to content

Even out Studio and share lighting - #881

Merged
w1ne merged 2 commits into
developfrom
cursor/viewer-light-distribution-a1b2
Oct 7, 2026
Merged

w1ne merged 2 commits into
developfrom
cursor/viewer-light-distribution-a1b2

Conversation

@w1ne

@w1ne w1ne commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Why

Production share paints (develop after #872) are still the pre-AgX rig. The AgX / dim-light / room-environment change in a272125 was reverted inside #872 and left on feat/viewer-lighting-agx. What app.kernelcad.com actually ships, confirmed in assets/index-BP6uzJra.js:

  • NeutralToneMapping, exposure 1
  • ambient 0.5, key 0.7 at [10, 20, 10], fill 0.3 at [-5, -10, -5]
  • no RoomEnvironment on the Studio canvas

The scene is Z-up, so that key is a side light (its largest component is +Y). Metalness-1 faces have nothing to reflect, so they go black except for a white specular spike. Dark dielectrics fall under luma 20. Brushed aluminium (anisotropy: 0.8 on the published T-slot) has no vertex tangents, and that degenerate frame paints whole faces black and white.

The demo player keeps its own Neutral rig at exposure 1 and room intensity 0.3. This PR does not touch it.

New numbers

Before (prod) After
Tone mapping Neutral AgX
Exposure 1 1
Environment none RoomEnvironment 0.62, rotated +90° about X so the room ceiling is +Z
Fill ambient 0.5 hemisphere sky 0xf7f8fa, ground 0xd2d6db, intensity 1.45, from [0, 0, 1]
Key [10, 20, 10] @ 0.7 [10, -8, 22] @ 0.34
Fill light [-5, -10, -5] @ 0.3 [-12, 10, 16] @ 0.26
Anisotropy authored, including 0.8 with no map 0 unless an anisotropy map is set (metalness and roughness stay authored)

Hemisphere intensity is above 1 because three.js divides indirect light by π; the two directionals are the form. Both are overhead (+Z is the largest component) and within 1.3× of each other, so the side turned away from the key stays a shade.

AgX stays. Neutral plus the old hot key is what clipped light faces. ACES is the tone map that crushes saturated CAD hues; it was not brought back.

White-clip check

Headless Chromium (SwiftShader), the same three.js lights, AgX, and RoomEnvironment as the viewer, on the published CDN meshes. Model pixels are everything that is not the #202126 stage. Blown = luma > 245, dark = luma < 20.

T-slot OGm0lP_B v1 (aluminium-brushed, metalness 1, anisotropy 0.8):

  • prod: 72% dark, 11% blown, max luma 252
  • new lights with anisotropy left on: 12% blown, max luma 254 (the white-clip failure)
  • shipped (anisotropy cleared, no map): 0% dark, 0% blown, max luma 197, every model pixel in the mid band

4DOF arm DNSlHVFO v1 (mostly #243140 dielectric, roughness 0.55):

  • prod: mean luma 17, 80% dark, max 218
  • shipped: mean luma 136, 0% dark, 0% blown, max luma 236, 98% mid

Ortho face centers on finish swatches under the shipped rig (aluminium, brushed, stainless, nylon, delrin, white #f4f4f4, ABS, servo blue): no face mean above 235, blown fraction 0. White #f4f4f4 reads 184–216. Pinning envMap at intensity 0.62 and the same rotation matches scene.environment exactly.

OGm0lP_B — T-slot frame corner

Before (production rig):

OGm0lP_B T-slot before, production rig

After (shipped rig):

OGm0lP_B T-slot after, shipped rig

DNSlHVFO — 4DOF arm

Before (production rig):

DNSlHVFO 4DOF arm before, production rig

After (shipped rig):

DNSlHVFO 4DOF arm after, shipped rig

These are the stored meshes rendered with the viewer’s light constants, not a screenshot of the Studio chrome. The disconnected arm geometry is unchanged.

Tests

  • Viewer.test.tsx locks AgX and exposure 1
  • viewerLighting.test.ts locks the intensities, the overhead key, and the key/fill ratio
  • roomEnvironment.test.ts locks per-scene IBL, intensity 0.62, and the +Z rotation, including that one canvas cannot receive another’s texture
  • buildShapeMaterial.test.ts locks anisotropy 0 without a map, and keeps 0.8 when a map is set

Do not merge until the share-page look is approved.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 2 commits October 7, 2026 12:48
The canvas key sat on +Y in a Z-up scene, with no environment for
metals to reflect, so aluminium went black-and-white and dark
plastics fell under luma 20. AgX at exposure 1, an overhead
hemisphere plus a close key and fill, and a room environment rotated
onto +Z keep light faces shaded. Anisotropy is applied only when a
map is present, because these meshes have no tangents.

Signed-off-by: Cursor Agent <[email protected]>

Co-authored-by: Andrii Shylenko <[email protected]>
Shard 4 failed on usecase-spur-gear-pair's mechanism gate. That
check runs evaluate_script and does not load the viewer.

Signed-off-by: Cursor Agent <[email protected]>

Co-authored-by: Andrii Shylenko <[email protected]>
@cursor
cursor Bot marked this pull request as ready for review October 7, 2026 13:12
@w1ne
w1ne merged commit caa1d76 into develop Oct 7, 2026
16 checks passed
@w1ne
w1ne deleted the cursor/viewer-light-distribution-a1b2 branch October 7, 2026 13:36
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