Skip to content

Fix WebGL overlay placement and octave note-color parity#268

Merged
ford442 merged 1 commit into
mainfrom
cursor/shader-playback-audit-0626
Jun 15, 2026
Merged

Fix WebGL overlay placement and octave note-color parity#268
ford442 merged 1 commit into
mainfrom
cursor/shader-playback-audit-0626

Conversation

@ford442

@ford442 ford442 commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Audited shader pattern playback accuracy against docs/planning/trigger-sustain-tails.md and the v0.50 WGSL reference. Data packing (TRIG-001 / DURA-001) is correct — npm run test:trigger-tail and npm run test:duration-parity both pass. The main gaps were in the WebGL2 hybrid overlay layer that composites frosted LED caps on top of WebGPU shaders.

Problems found

1. WebGL overlay misplacement (circular / v0.46)

Hybrid overlay vertex shader always fetched pattern data from absolute rows 0..numRows-1. WGSL patternv0.46.wgsl pages by floor(playhead / numRows) * numRows, so once playback passed row 64 the overlay showed the wrong pattern slice while WebGPU showed the current page.

2. Inconsistent polar radii

useWebGLOverlay hard-coded outerRadius = minDim * 0.45 for all shaders. WebGPU uses 0.40 for v0.45 (non-b) to leave room for embedded UI — overlay caps were drawn outside the WGSL ring grid.

3. Missing octave brightness in WebGL overlay

WGSL v0.50+ uses octaveBrightness(note) so the same pitch class shares hue across octaves but gets brighter in higher octaves (0.65 at C-0 → 1.0 at B-9). The WebGL overlay only used pitchClassFromIndex — C-3 and C-5 looked identical.

4. Trigger + sustain tail behavior (already correct in data layer)

Per trigger-sustain-tails.md:

  • Trigger row: brilliant large node, blue top emitter flash, pitch-colored mid emitter
  • Sustain tail rows: smaller dim cap, pitch hue at ~45% brightness, no lane flooding

Packing sets PACKEDB_TRIGGER_FLAG on note-on rows and copies pitch onto tail rows (DURA-003). WebGL fragment shader already branches is_trigger vs isSustaining — the overlay was drawing the right states but wrong positions and colors.

Fixes in this PR

  • utils/geometryConstants.ts: getPolarRadii() + usesCircularRowPaging() — single source for WebGPU/WebGL radii
  • hooks/webGLShaders.ts: circular paging for v0.46; octaveBrightness() in fragment shader
  • hooks/useWebGLOverlay.ts + WebGL2PatternRenderer.ts: consume shared helpers

Still recommended (follow-up)

Area Status Notes
WGSL v0.46/v0.47/v0.48 octave brightness Missing v0.50+ has it; older LED shaders still pitch-class only
Playhead timing drift (Worklet) Open See docs/planning/accurate_playback.md — ~200ms lag vs ScriptProcessor
v0.50 default has no WebGL hybrid By design Overlay only on webglHybrid: true shaders (v0.38, v0.40, v0.45b, v0.46, …)
Visual regression screenshots Manual npm run capture:trigger-tail against preview server

Test plan

  • npm run typecheck
  • npm run test:trigger-tail
  • npm run test:duration-parity
  • Visual: load a module on patternv0.46.wgsl, seek past row 64 — overlay caps should track the paged grid
  • Visual: compare C-3 vs C-5 notes on hybrid shader — mid emitter should be same hue, different brightness
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added support for circular row paging for compatible shader versions.
  • Improvements

    • Refactored polar radius computation for improved rendering accuracy based on shader configuration.
    • Enhanced visual rendering with octave brightness adjustments for better color representation across different note ranges.

- Add getPolarRadii() and usesCircularRowPaging() shared geometry helpers
- WebGL overlay: page circular rows for v0.46 (was always showing rows 0..N)
- WebGL overlay + WebGL2 renderer: apply shader-specific outer radius (v0.45)
- WebGL fragment shader: octaveBrightness() so pitch hue dims/brights by octave
- Unify radius math between WebGPU uniforms and WebGL overlay uniforms

Co-authored-by: Noah Cohn <noahc42@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 46dd7c5d-270f-4f71-b73e-deabc9e5febd

📥 Commits

Reviewing files that changed from the base of the PR and between aa23879 and b303b26.

📒 Files selected for processing (5)
  • hooks/useWebGLOverlay.ts
  • hooks/useWebGPURender.ts
  • hooks/webGLShaders.ts
  • src/renderers/webgl2/WebGL2PatternRenderer.ts
  • utils/geometryConstants.ts

📝 Walkthrough

Walkthrough

Adds getPolarRadii and usesCircularRowPaging helpers to utils/geometryConstants.ts. Extends buildVertexShader with a useCircularPaging parameter that bakes playhead-page-aware row selection into GLSL, and adds an octaveBrightness helper to the fragment shader. All three rendering paths (WebGL2PatternRenderer, useWebGLOverlay, useWebGPURender) are updated to use the shared helpers instead of inline minDim calculations.

Changes

Circular Row Paging, Polar Radii Helper, and Octave Brightness

Layer / File(s) Summary
Geometry constants: getPolarRadii and usesCircularRowPaging
utils/geometryConstants.ts
POLAR_RINGS gains OUTER_RADIUS_V045; new getPolarRadii computes pixel radii from canvas size and shader filename patterns (v0.45/v0.45b); new usesCircularRowPaging returns true when shader filename contains v0.46.
buildVertexShader: circular paging and octave brightness
hooks/webGLShaders.ts
Adds useCircularPaging (default false) parameter; bakes USE_CIRCULAR_PAGING into GLSL so actualRow becomes playhead-page-aware and angleRow uses actualRow % int(u_rows); adds octaveBrightness(note) fragment helper and applies it to neonPalette output in both V0.21 and non-V0.21 color paths.
Renderers wired to new helpers
src/renderers/webgl2/WebGL2PatternRenderer.ts, hooks/useWebGLOverlay.ts, hooks/useWebGPURender.ts
All three renderers import getPolarRadii and (where applicable) usesCircularRowPaging; inline minDim-based innerRadius/outerRadius calculations are replaced with getPolarRadii(...) calls; useCircularPaging is derived and forwarded into buildVertexShader.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐇 Round and round the shader goes,
Where actualRow lands, only u_playhead knows.
getPolarRadii plots each ring,
And octave brightness lets the colors sing.
No more minDim scattered about—
One helper rules, there is no doubt! ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/shader-playback-audit-0626

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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