diff --git a/flow-state/.claude/launch.json b/flow-state/.claude/launch.json new file mode 100644 index 0000000..6b35578 --- /dev/null +++ b/flow-state/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "flow-state", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev"], + "port": 5180 + } + ] +} diff --git a/flow-state/HOWTO-visualizers.md b/flow-state/HOWTO-visualizers.md index 93556d1..2e83bc2 100644 --- a/flow-state/HOWTO-visualizers.md +++ b/flow-state/HOWTO-visualizers.md @@ -112,6 +112,15 @@ intentionally shrinks per track. Only declare what you genuinely use: The lint greps your shader and fails a declared trait with no evidence. Declaring `[]` (none) is valid. +### `texture` — how much surface grain your scene accepts + +Optional module field, `0..2`, default `1`. It scales `u_sigTexture` — and so +every `sigGrain(uv)` in your shader — for this scene only. Set it to `0` if your +scene is crisp line work that grain only furs up, or to something under 1 if it +should be dusted rather than dirty. It has nothing to do with the *grade's* +grain, which is a per-track treatment (see `look/grain.js`) and is off entirely +for most tracks. + ## Traps that have actually bitten here 1. **Anything multiplying `u_time` must be `rate: true`.** Phase is diff --git a/flow-state/PLAN.md b/flow-state/PLAN.md index ee44581..0d8e53d 100644 --- a/flow-state/PLAN.md +++ b/flow-state/PLAN.md @@ -579,6 +579,35 @@ Adding a scene was mostly boilerplate and round-trips, which is expensive in bot a verdict, instead of rendering the whole library to find out whether one shader is alive. - `.claude/skills/build-visualizer/` is the same procedure as a repo skill. +### Phase 10b — grain as a treatment, tempo as a governor + +Watching the library again surfaced two things no gate was asking about. + +**Grain was in every video.** It was added twice unconditionally — every scene called +`sigGrain`, and the grade added its own on top — so the only thing that varied between two +tracks was how much. That makes grain the renderer's fingerprint rather than a decision about +one video. It is now DESCRIBED (`look/grain.js`): a mode (`off` / `constant` / `swell` / +`sections` / `transient`), a cell size in pixels, a refresh rate in frames, a mask (uniform, +shadows, highlights, edges, bands) and a chroma amount. Roughly 45% of tracks get none at all; +the non-constant modes have a per-frame envelope computed in `Show._postAt` from frame and +features only, so preview and export still agree. Scene-side grain is gated the same way, and +a module can decline it outright with `texture: 0` — crisp line work should stay crisp. + +**Slow songs got fast scenes.** `motion` bias was mostly section energy with tempo as a small +correction, so a 70bpm track's drop asked for nearly as much speed as a 150bpm one. Motion is +now tempo-dominated, and every `rate: true` param is additionally scaled by a per-track +`rateScale`, so absolute animation speed follows the song rather than only the sampled +position in a range. + +Parameter sampling also commits harder: `extremity` starts at 0.5 rather than 0.25 and shapes +the draw more aggressively, because a range is the scene author's statement of what the scene +can survive and a library that samples the middle of every range shows every scene's default. + +**Gate:** a quarter to two thirds of tracks have no grain and at least four modes appear; +thirty grainy tracks produce mostly-distinct treatments; every time-varying grain reaches both +zero and full; a `texture: 0` scene gets nothing even from a maximally gritty track; and a +84bpm track's rate params sample materially below a 148bpm track's. + --- ## 10. Detachment from `party-stage` diff --git a/flow-state/index.html b/flow-state/index.html index d54ac03..51ee63c 100644 --- a/flow-state/index.html +++ b/flow-state/index.html @@ -32,9 +32,11 @@ 0:00 / 0:00 - + -