agentleFS
JonathanBeck1JonathanBeck1/claude-studio-toolkit/skills/ether-shaders/SKILL.md

ether-shaders

Skill0 starsChanged 28 days agoMITView on GitHub

Premium shader and postprocessing stack for ether-engine WebGL. Documents the LDR-composer bloom + dither preset, the iridescent fresnel + cheap-noise vertex displacement material, the extruded-word text pipeline, and the engine-vs-site shader boundary. Use this — not ether-threejs — whenever the task is writing GLSL or tuning an existing shader, a ShaderMaterial, an iridescent fresnel material, vertex displacement, MSDF/extruded 3D text, or the bloom+dither composer (ether-threejs owns scene architecture; this owns the shader and material layer). Triggers on GLSL, fragment shader, vertex shader, custom material, dither, bloom, postprocessing, fresnel, iridescent, displacement, surface noise, extruded text, 3D type, premium material, raw GLSL import, sculpture material, ExtrudeGeometry, brand-as-form. Do NOT use when "bloom", "displacement", or "dither" appear outside a GLSL/WebGL material context, or when the existing engine postfx composer already covers the need — reference it, don't rebuild.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Default materials (MeshBasicMaterial, MeshStandardMaterial) on hero elements.

    line 57
  2. Distinctive:

    Test against the hero composer: If your material needs HDR values, the LDR composer clips them — rework to 0..1 (preferred) or use the …

    line 77
  3. Very specific:

    Run premium-review: before reporting complete.

    line 78
  4. Very specific:

    Run the premium-review subagent on any shader work before reporting complete.

    line 82
  5. Very specific:

    If the shader is scroll-bound, also invoke ether-scroll for the bridge pattern.

    line 83
  6. Very specific:

    If creating a new dimensional-type treatment, cite the extrudedWord options you chose in the commit message — future grep will find the …

    line 84

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

ether-shaders

Technique reference for the shader + postprocessing + extruded-text stack in the ether engine. Invoke before writing any shader, postprocessing change, or text-as-form work on a site built on it.

When to use

Any of:

  • Writing a new ShaderMaterial, vertex shader, or fragment shader.
  • Modifying postprocessing (bloom, dither, color grading, new effects).
  • Adding or tuning extruded text — hero treatments, chapter heads.
  • Diagnosing a banding / glow / type-ghosting / displacement-blur issue.

Invoke alongside ether-threejs (the general slop checklist) — this skill specializes, the other generalizes.

Read first

  1. The ether-threejs SKILL.md — the general "no AI-slop three.js" checklist applies first.
  2. recipes.md in this directory — nine numbered recipes.
  3. Your studio's taste doc, if the repo has one — what lands vs. what doesn't.

The engine / site boundary

  • Engine owns (ether src/):
    • postfx/composer.ts — createComposer, the one composer shape: render → your effects → (ACES when hdr) → dither, fused into a single EffectPass.
    • postfx/heroComposer.ts — three tunings of it: createHeroComposer (restrained LDR bloom for a dark scene with one bright accent), createNightComposer (hotter bloom for scenes whose light IS emissive geometry; exposes the optional hdr flag), createLightComposer (dither only — bloom on a pale ground just lifts the ground).
    • postfx/DitherEffect.ts — per-pixel hash grain applied through the sRGB transfer. Separately, shaders/dither.glsl is a standalone 8×8 Bayer chunk for your own materials; the effect does not use it.
    • primitives/ShaderQuad — backdrop plane with auto-wired uTime / uAspect.
    • text/extrudedWord — opentype → SVGLoader → ExtrudeGeometry pipeline (type as form).
    • text/msdf — msdfText, a troika-backed MSDF mesh (type as text), on its own entry so the optional peer stays optional.
  • Your site owns (src/shaders/<scene>/):
    • The hero material shaders — your identity. Site-specific until a second consumer needs them.
    • Backdrop shaders (caustics, gradients, generative fields).

The engine is brand-free by construction: it ships wiring and takes the palette as uniforms, so the site injects its own colors. Don't promote site shaders to the engine without a generalization pass (uniform-driven palettes, no hardcoded brand-token vec3s).

Hard rules

  • Follow the project's configured shader import convention — vite-plugin-glsl, ?raw (import frag from './x.frag.glsl?raw'), or inline strings. When adding a shader, use what the codebase already does; don't mix strategies without a reason.
  • optimizeDeps.exclude: ['ether'] is mandatory in your astro.config.ts (or Vite config) for a git / file: install, which ships raw .ts. esbuild's dep-scan can't parse the engine's Vite-only ?raw GLSL imports; excluding it routes those files through Vite's full plugin pipeline instead.
  • Never set preserveSymlinks: true for a file: layout — it pins the engine at its node_modules path, which Vite ignores for file-watching, so engine edits never hot-reload and it gets served as a stale cached external dep. Its one job (resolving the engine's bare three / postprocessing imports into the site's node_modules) is done correctly by resolve.dedupe: ['three', 'postprocessing', …] — set that instead. Both rules live together in astro.config.ts.
  • Three composer presets exist — pick one, don't mutate one into the other. All three are thin tunings over createComposer; if none fits, write a fourth on createComposer rather than parameterising an existing one. createHeroComposer takes PresetOptions and is LDR by design — it never passes hdr, so values clip at 1.0 deliberately as bloom containment. Only createNightComposer re-exposes hdr (NightComposerOptions), which switches on HalfFloatType buffers + an ACES ToneMappingEffect and makes toneMappingExposure live. createLightComposer is dither-only.
  • Edge AA comes from the composer's multisampling, never the context antialias flag. Post-processing renders into textures that bypass the canvas framebuffer, so context MSAA is visually dead the moment a composer runs (the quality profile sets antialias: false and carries msaaSamples instead — wire via createHeroComposer(renderer, scene, camera, { multisampling: quality.msaaSamples })).
  • Dither runs on every tier. The quality profile ships enablePostFX: true and enableDither: true on LOW, MID and HIGH alike — tiers differ only in msaaSamples (HIGH 4 / MID 2 / LOW 0). It merges into the SAME fullscreen pass as bloom (a few ALU ops — effectively free) and kills the dark-gradient banding that reads as posterized color on mobile OLED. Never gate it on tier at a call site.
  • Bloom intensity 0.06 is the hero-preset ceiling. Higher = glow-spam. Raise luminanceThreshold to gate harder if you need more visible bloom. The night preset ships 0.38 by design — its own ceiling, not a license to raise the hero's.
  • Custom ShaderMaterial only on hero elements. No MeshBasicMaterial / MeshStandardMaterial for hero content. See ether-threejs.
  • Brand tokens through uniforms. Pull colors from your site's constants module — the engine never names a color. If tokens are mirrored in CSS, update both when a color changes.
  • Wire uTime through the scene tick. Material uniforms updated from tick() or via a wrapper's tickUniforms. Never via setInterval.
  • Add precision highp float; at the top of fragment shaders explicitly — three.js prepends it by default, but stating it inline keeps the intent durable across pipeline changes.

Slop indicators (do not ship)

  • Default materials (MeshBasicMaterial, MeshStandardMaterial) on hero elements.
  • Bloom intensity > 0.1 on the hero preset, or luminanceThreshold < 0.5 (the night preset ships 0.38 by design).
  • Hardcoded vec3(...) colors in shaders.
  • Ambient particle fields with no narrative function (see ether-threejs).
  • ShaderMaterial without uTime wired through the engine's tick.
  • dat.gui left in production builds.
  • console.log inside shader hot paths.
  • ExtrudedWord with curveSegments < 6 on hero treatments.
  • Single-color iridescent rim (must be a dual-color mix by normal direction).
  • Promoting a site shader to the engine without uniformising the color palette.
  • Vertex displacement strong enough to blur bevels on letter-extrusion geometry.

Procedure for a new ShaderMaterial

  1. Confirm against the ether-threejs slop checklist first — general rules apply before specifics.
  2. Decide ownership — is the shader reusable across sites (engine) or brand-specific (site)? Default: site, until a second consumer exists.
  3. Place files — src/shaders/<scene>/<name>.{vert,frag}.glsl. Import them by the project's existing convention.
  4. Wire uniforms through your constants module — brand colors, displacement amplitudes, fresnel exponents.
  5. Tick uniforms from the scene's tick() (or a wrapping class's tickUniforms).
  6. Add precision highp float; to fragment shaders.
  7. Test against the hero composer. If your material needs HDR values, the LDR composer clips them — rework to 0..1 (preferred) or use the night preset.
  8. Run premium-review before reporting complete.

After the skill

  • Run the premium-review subagent on any shader work before reporting complete.
  • If the shader is scroll-bound, also invoke ether-scroll for the bridge pattern.
  • If creating a new dimensional-type treatment, cite the extrudedWord options you chose in the commit message — future grep will find the lineage.

Files

  • SKILL.md — this file (the script).
  • recipes.md — nine numbered technique recipes, each ending in a file + symbol citation index.
  • evals/triggers.json — should/shouldn't-trigger regression set for the description.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.