Threejs dynamic surface effects
Skill linegel/threejs-complete-set-of-skill/skills/threejs-dynamic-surface-effects
25 expert agent skills for ambitious Three.js WebGPU/TSL scenes — procedural oceans, clouds, planets, water optics, image pipelines, and screenshot-backed visual validation. For Claude Code, Codex, Cursor, and any skill-aware agent.
npx -y skills add linegel/threejs-complete-set-of-skill --skill threejs-dynamic-surface-effectsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
State-transition screen-space surface effects for Three.js WebGPU/TSL. Use for persistent touch, frost, or thaw history; full-field or sparse accumulation; static crystalline fields; reduced-resolution blur; or history-gated normal refraction.
SKILL.md
8.8 KB, as published. Nobody here has run it
State-Transition Dynamic Surface Effects
Own viewport-locked appearance history and its composite. Route world/object
residue to $threejs-particles-trails-and-effects, weather accumulation to
$threejs-rain-snow-and-wet-surfaces, bounded water to
$threejs-water-optics, and shared full-frame output decisions to
$threejs-image-pipeline.
When temperature, phase, loading, wetness, contact, or weather drives the appearance, close this local handoff before step 1:
- name the physical quantity and units, producer frame/origin, transform and origin generations, and projection into screen UV;
- name the source interval, cadence, sample phase, immutable producer/version, and renderer consumer;
- declare support/filter, validity, staleness, error, and missing-signal policy;
- bind the GPU resource generation, producing and consuming passes, and completion dependency;
- keep the physical source read-only and give screen history its own appearance version; reset it on incompatible clock, origin, transform, projection, or resource-generation changes.
Invoke $threejs-choose-skills when feedback or additional system owners are
required. The physical owner retains authority; screen-UV history remains
renderer-owned appearance state.
Then read external appearance signals
for local projection and reset rules.
Process
1. Define the state transition and ownership
Write one contract for:
- each history channel and its dimensionless meaning;
- the screen-space event shape, timestamp, pressure/strength, and UV origin;
- evolution terms such as decay, deposition, diffusion, or no change;
- the state clock, suspension/seek policy, and reset dependencies;
- the one history writer, composite consumer, and final output owner;
- any external physical signal and the decorative overlay kept separate from it.
For touch/frost history, a useful split is visible coverage in R and a
smoother tilt/refraction response in A; G/B remain unused or explicitly
diagnostic. The step is complete when every channel has one equation, writer,
unit domain, clock, and consumer.
2. Select update topology
Choose from the state transition rather than the visual theme:
| Transition | Update topology |
|---|---|
| Decay, diffusion, or forcing changes most texels | Full-field ping-pong compute |
| Deposits are sparse and untouched texels are invariant | Event bounds or dirty tiles |
| Sparse state also decays | Timestamped tiles with analytic catch-up on every visible/filter sample, or materialize every visible tile |
| Many events overlap | Bin events to tiles; bound/compact lists or rasterize one aggregate deposit field |
| State and inputs are unchanged | Idle: retain history and dispatch nothing |
Diffusion uses a full field or halo-expanded active domain. Read update topologies for overlap cost and diffusion stability. The step is complete when untouched texels evolve exactly as the chosen model requires and idle frames schedule no state work.
3. Make time and event integration invariant
Derive dt from two ordered samples on the same clock. Treat equal samples as
zero elapsed time. A missing previous sample, reversal, seek, invalid mapping,
or discontinuity follows the declared freeze, reset, analytic catch-up, or
bounded-substep policy.
Rasterize timestamped pointer motion as swept capsules with aspect from the history texture. Integrate decay and saturating deposition together so a held pointer and a swept gesture converge independently of render-frame count. Subdivide event intervals only when their pressure or coverage variation exceeds the declared error gate.
Read dt-correct history before implementing decay, deposition, or diffusion. The step is complete when the same timed input yields equivalent history at 30, 60, and 120 Hz and a suspension does not silently discard elapsed evolution.
4. Allocate the ping-pong graph
Use WebGPURenderer from three/webgpu, call await renderer.init(), and
require renderer.backend.isWebGPUBackend === true for this canonical path.
Route explicit WebGPU-unavailable teaching to
$threejs-compatibility-fallbacks.
Allocate two renderer-owned StorageTexture histories at the lowest measured
extent/format that passes reconstruction and quantization tests. Keep history,
scene color, blur intermediates, and static structure fields as separate
resources.
Order the graph:
immutable external appearance signals + timestamped UI events
-> write next history from previous history
-> publish/swap the completed history generation
single scene pass
-> optional separable blur at its owned reduced extent
-> static structure + current history composite
-> optional history-gated normal refraction
-> one RenderPipeline output transform
Use Fn().compute(...), storageTexture(), and textureStore() for history
updates. Enqueue with renderer.compute(...); r185 computeAsync() is not a
GPU-completion fence. Keep the steady path readback-free. Mark/rebuild the
render graph when the output node, diagnostic route, resource extent/format, or
quality branch changes.
Read resources and r185 execution before allocating or swapping textures. The step is complete when every pass reads a committed generation, no pass samples the texture it writes, and the scene is rendered once.
5. Compose blur, structure, and refraction
Generate static crystalline/noise fields once at startup or when their extent
or quality changes. Treat them as data with NoColorSpace. Use separable blur
at a pass-owned reduced resolution and alpha-aware normalization when alpha
participates. Build the composite and refraction as TSL nodes feeding
RenderPipeline.outputNode.
Keep scene and working buffers linear/HDR until the single output conversion. Use screen-period uniforms as periods; derive texel dimensions from the actual resource. Gate refraction by structural coverage and current history, define normal wrap and source-edge behavior, and apply Fresnel in linear light.
Read composite and refraction when either branch is active. The step is complete when blur extent, texture domains, UV conventions, refraction bounds, and output conversion are each owned and visible in diagnostics.
6. Close the lifecycle
Choose one resize policy: clear both histories, remap, or depth/camera-aware reprojection. Reset or reproject on incompatible clock, origin, transform, projection, resource generation, representation, or quality changes. Ordinary continuous source-version advances are sampled rather than reset.
On idle, retain persistent state and stop update work. On resume, apply the declared time policy before accepting new input. On disposal or device loss, invalidate the history generation and release both histories, blur/static resources, compute/pipeline nodes, and input/resize listeners; create a fresh generation before the next draw.
Read resize, reset, and disposal. The step is complete when resize, seek, quality change, idle/resume, disposal, and device loss each have an explicit state transition and resource result.
7. Prove state and presentation
Expose previous history, deposit, next history, dirty tiles/active texels, scene color, blur axes, static fields, pre/post-history mask, refraction offsets, final-without-refraction, and final. Add pause and single-step controls.
Measure event count, tile-list occupancy, dispatched texels, history and intermediate bytes, traffic lower bound, dispatch/draw timing, and whole-frame p50/p95. Scale by stopping idle work, choosing a valid sparse path, then reducing history/blur extent or precision after state-equivalence tests.
Read resource accounting and diagnostics and failure signatures. The skill is complete when timed inputs match across 30/60/120 Hz; full, sparse, and idle transitions behave as selected; ping-pong generations never alias; resize/reset/disposal controls pass; physical inputs remain read-only; the frame loop performs zero history readbacks; the scene renders once; output conversion has one owner; and the complete scene meets its named memory, traffic, and timing budget.