first commit

This commit is contained in:
2026-10-06 12:16:46 +09:00
commit 619d980098
415 changed files with 22283 additions and 0 deletions
@@ -0,0 +1,206 @@
# Surface reflection implementation report
## Status and scope
Implemented Task 1 from `.superpowers/sdd/surface-reflection/task-1-brief.md`.
The change is limited to the final non-`REGION_ATLAS` reflection composition in
`src/shaders/mosaic.frag` plus one source/math regression script. Existing
uniforms were sufficient, so `src/main.ts` was not changed.
The exact pre-edit shader is preserved at
`docs/qa-surface-reflection/baseline-mosaic.frag`.
Baseline SHA-256:
```text
CEE5F75C7A62A9146CBE451C661C2E0066EE57EB8963A7B0F56C281873F37E35
```
## Implementation
Changed files:
- `src/shaders/mosaic.frag`
- `scripts/test-surface-reflection.mjs`
- `docs/qa-surface-reflection/baseline-mosaic.frag` (pre-edit snapshot)
- `docs/qa-surface-reflection/implementation-report.md`
The existing rectangular reflection remains intact and is now named
`specGloss`. A separate broad reflection is added after color-plane
simplification and before `#include <colorspace_fragment>`.
Final coefficients and rationale:
- Surface reflection edge weight: `mix(0.35, 1.0, edgeWeight)`. This keeps the
existing refraction `edgeWeight` and `strength` path unchanged while reducing
reflection at pane edges without removing it entirely.
- Existing rectangular reflection strength: `.12`, unchanged.
- Broad reflection strength: `.035`, intentionally low relative to the
rectangular lobe.
- Broad spatial footprint: `smoothstep(vec2(.15), vec2(1.75), windowCoord)`,
wider and softer than the existing `.45` to `1.15` rectangular mask.
- View/surface response: `pow(max(dot(nCurved, v), 0.), 2.)`, using the same
signed curved normal that drives refraction and the existing reflection.
- Both reflection amplitudes use the same `clamp(uGlossStrength, 0., 1.)`
gate, so gloss `0` makes both contributions exactly zero.
No environment texture, render pass, render target, dependency, palette input,
history input, UI, camera, placement, framing, or other glass-mode change was
added.
## TDD evidence
Focused regression: `scripts/test-surface-reflection.mjs`.
The assertions are source/math-only and do not claim to execute GLSL or prove
browser visuals.
### RED
Command:
```text
node scripts/test-surface-reflection.mjs
```
Exact result against the pre-edit shader:
```text
exit_code=1
node:internal/modules/run_main:107
triggerUncaughtException(
^
AssertionError [ERR_ASSERTION]: both surface reflection terms must share a clamped gloss gate
at file:///D:/project/behind_glass/scripts/test-surface-reflection.mjs:11:8 {
generatedMessage: false,
actual: '#ifndef REGION_ATLAS\n' +
' color.a=1.;\n' +
' vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color;\n' +
' #include <colorspace_fragment>\n',
expected: /float glossStrength=clamp\(uGlossStrength,0\.,1\.\);/,
operator: 'match'
}
```
This failed for the intended reason: the pre-edit shader had one reflection
term, no shared gloss gate, no broad reflection, and no separate surface edge
weight.
### GREEN
Command:
```text
node scripts/test-surface-reflection.mjs
```
Exact result after the minimal shader edit:
```text
exit_code=0
surface reflection source/math regression passed
```
The final regression checks zero-gloss gating, `.35` to `1.0` surface-weight
bounds, preservation of the refraction edge weight, normal/view and light-hit
spatial dependence, non-atlas placement, and ordering before color-space
conversion.
## Automated verification
All six existing scripts from `docs/qa-window-immersion/verification.md` were
run with `node --experimental-strip-types` after implementation.
```text
=== node --experimental-strip-types scripts/test-camera-history.mjs ===
Camera/history checks passed: default/max clamp, model reset keys, ping-pong and disposal, premultiplied color, cadence 0.999955/0.999955/0.999955, 70ms settling.
=== node --experimental-strip-types scripts/test-region-axis-split.mjs ===
Region axis-split checks passed: SSE axis/cut/pair scoring, vertical/horizontal cuts 2/6, observed side-label pairs, checkerboard model, single-label fallback, metadata round-trip, confidence blending, dark eye/nose protection, and edge-independent color strength.
=== node --experimental-strip-types scripts/test-mosaic-depth-distance.mjs ===
Mosaic depth-region projection checks passed: 21 perspective reconstructions, 12 original-depth UV mappings across camera/zoom-pan/depthScale, near-depth gate, distance-independent color application, and invalid-surface guards.
=== node --experimental-strip-types scripts/test-mosaic-continuity.mjs ===
Mosaic projected-UV continuity passed: 493760 Jacobians, 87200 seam convergence checks, center/edge anchors, and view-dependent within-cell displacement.
=== node --experimental-strip-types scripts/test-region-atlas-dark-sampling.mjs ===
Region atlas dark sampling source/math-only regression passed: phase-offset narrow feature, far/invalid/uniform invariants, and four-probe bounded scoring contract.
=== node --experimental-strip-types scripts/test-window-reveal-coverage.mjs ===
Window reveal coverage passed: 146 previous-frame misses sealed across 2 aspects, 3 depth scales, 17 view offsets (including neutral) and 49 aperture samples; geometry reuse/disposal verified.
```
Build command:
```text
npm.cmd run build
```
Result: exit code `0`; TypeScript and Vite production build succeeded. Vite
reported the existing large-chunk advisory for the main and AI-depth assets.
## Visual comparison and limitations
No browser or GPU visual capture was performed in this implementation task.
The preserved shader baseline is available at
`docs/qa-surface-reflection/baseline-mosaic.frag`; use it for the
same-viewport dog1 comparison with the brief's fixed values, including gloss
0, 0.30, and 0.40, curvature -1/0/+1, camera 0.90, portrait, and indoor
checks.
The automated regression does not prove grass highlight appearance, adjacent
cell coherence, edge leakage, eye/nose readability, mobile behavior, or GPU
shader compilation. Those remain visual/browser verification items. No claim
of GPU, mobile, or visual success is made here.
## Round 1/5 regression hardening
Addressed both Astra findings without changing production scope. The focused
script now extracts individual GLSL statements instead of using unrestricted
cross-statement matching, compares `edgeWeight`, `strength`, and `sceneHit`
against the preserved pre-edit shader, inspects the effective atlas branch,
and verifies simplification before final composition and composition before
color-space conversion. It evaluates the extracted `specGloss`,
`broadReflection`, and final mix expressions for gloss-zero output plus
representative spatial/view variation. It also applies an in-memory constant
50% final-mix mutation and requires the covering assertions to reject it.
Exact covering command:
```text
node scripts/test-surface-reflection.mjs
```
Exact output:
```text
exit_code=0
surface reflection source/math regression passed; constant-output mutation rejected
```
Only the focused regression was rerun because this round changed no
production file; the six existing checks and build remain covered by the prior
verification record above.
## Round 2/5 atlas exclusion hardening
Addressed the remaining atlas-exclusion finding without changing production
code. `scripts/test-surface-reflection.mjs` now walks all `REGION_ATLAS`
preprocessor branches, retains the complete effective source for the macro
defined, and compares that source with the preserved baseline. It also inserts
an in-memory gloss-dependent white reflection immediately after the earlier
atlas `atlasCenterColor` sample and requires the covering assertions to reject
that mutation. This remains a source/math regression and is not GPU visual
verification.
Exact covering command:
```text
node scripts/test-surface-reflection.mjs
```
Exact output:
```text
exit_code=0
surface reflection source/math regression passed; constant-output and atlas-reflection mutations rejected
```
No full suite or build was rerun because the production shader remained
unchanged.