11

I kept rewriting the same plumbing for every shader toy: pass uTime, uResolution, uMouse, handle DPR, update on resize. And I kept getting subtle bugs, like resolution not accounting for pixel ratio so noise scale drifted between monitors.

So I made one prompt that produces a correct, reusable fullscreen-quad shader harness with all the uniforms wired and normalized the way ShaderToy expects. Now I just paste my fragment body in. The normalization of mouse to 0..1 and flipping Y was the part I always got wrong by hand.

Sharing it. What uniforms do you consider mandatory that I might be missing?

THE PROMPT
Write a reusable three.js fullscreen-shader harness (module syntax, importmap) I can drop any fragment shader into. Provide:
- An OrthographicCamera + a single plane covering the viewport (no perspective math).
- A ShaderMaterial with uniforms: `uTime` (seconds, float), `uResolution` (vec2, in device pixels including DPR), `uMouse` (vec4: xy = normalized 0..1 with Y flipped to match GLSL, zw = last click position).
- DPR handling: cap at 2, update `uResolution` and renderer size on resize with a debounced handler.
- Pause `uTime` accumulation when the tab is hidden (visibilitychange) so animations don't jump on return.
- A clearly marked `// ---- YOUR FRAGMENT BODY HERE ----` region with a sample that just outputs `vec3(uv, 0.5)` so I can confirm the plumbing before pasting real code.
- Comment each uniform with its exact units and range.
Explain why uResolution must include devicePixelRatio and what breaks if it doesn't.
pausing uTime on visibilitychange is the kind of thing you only add after it bites you once. good to bake into the boilerplate.onepromptwonder 2 months ago
add a comment

1 Answer

7

Solid harness. Two adds I consider mandatory: uDeltaTime (frame delta in seconds) so time-based motion is framerate-independent, and uFrame (int frame counter) which is handy for temporal effects and dithering. Both are trivial to accumulate next to uTime.

THE PROMPT
Add to uniforms: `uDeltaTime: {value:0}` set from a THREE.Clock getDelta each frame, and `uFrame: {value:0}` incremented per rAF. Use uDeltaTime for any motion so it's stable across refresh rates.

Your Answer