Skip to content
AI & Agents
Skill

/renderer

Architecture rules for GPU rendering with TypeGPU/WebGPU — games, data visualisation, canvases, any app that draws with the GPU. Use when adding or changing passes, shaders, buffers, textures, pipelines, frame orchestration, GPU resource lifetimes, or checks that judge rendered

BOOST
From plugin
dzhng-skills
1.3k30 skills
Install
$ npx -y skills add dzhng/skills --skill renderer --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/renderer

Context preview

The summary Claude sees to decide when to auto-load this skill.

Architecture rules for GPU rendering with TypeGPU/WebGPU — games, data visualisation, canvases, any app that draws with the GPU. Use when adding or changing passes, shaders, buffers, textures, pipelines, frame orchestration, GPU resource lifetimes, or checks that judge rendered

SKILL.md

renderer.SKILL.md
name: renderer
description: Architecture rules for GPU rendering with TypeGPU/WebGPU — games, data visualisation, canvases, any app that draws with the GPU. Use when adding or changing passes, shaders, buffers, textures, pipelines, frame orchestration, GPU resource lifetimes, or checks that judge rendered output.

GPU renderer

The stack is **TypeGPU on WebGPU**: typed schemas, bind group layouts and pipelines, with WGSL where it's clearer. Don't add a second rendering library.

For 3D models and textures, use Blender if it's available. Prefer a Blender MCP server when one is installed; otherwise run headless (`blender -b --python script.py`). Keep the scripts in the repo, so every asset is reproducible from code rather than hand-edited.

Architecture

  • **The renderer draws what it's handed.** The app builds plain frame inputs from its own state (a game observation, a query result, a document), and the renderer consumes them through one interface. It never reaches into app or domain state.
  • **One frame function orchestrates.** A single function encodes every pass in order. Read it before adding anything, and add your pass there, not beside it.
  • **Pick the phase by semantics:**
  • compute for preparation (culling, layout, instance building);
  • a depth prepass for opaque geometry, then the lit colour pass;
  • translucent content after the opaque;
  • screen-space passes on resolved targets;
  • overlays and UI last.
  • **One owner per concept:** device and capabilities, camera and projection, the depth convention, frame targets, the resource registry, the time source. A second copy (a private projection, or a struct hand-mirrored in WGSL) is a bug waiting to happen. Refactor to the shared owner.
  • **Tunable numbers live in data** (config or fixtures), validated where they're loaded. Don't scatter them as constants in passes.
  • **Update each resource at its own frequency:** every frame, on view change, on data change (upload deltas only), or once. Allocate nothing per frame on hot paths.
  • **Do CPU-side math with the pmndrs [`math`](https://github.com/pmndrs/math) package** (npm `math`, whose `API.md` lists every export): vectors, matrices, quaternions, frustum and shape culling, noise, seeded randomness.
  • Its functions take the output as their first argument and return it, so preallocated scratch keeps hot paths allocation-free.
  • Pack its results into preallocated `Float32Array`s for upload.
  • Don't hand-roll a second vector or matrix library.
  • **Picking and hit tests use the app's own shapes** and the same camera function the GPU packing uses, never a readback of drawn pixels.

Resources

  • **Every buffer and texture goes through one registry,** with scopes for size-dependent targets and slots for replaceable resources. Nothing is allocated outside it: in TypeGPU, `root.destroy()` does not free what the root created.
  • **Handle async rebuilds** (resize, pipeline swaps). Build into a new scope and swap it in whole. Free a build that's overtaken or finishes after dispose. Make every public call safe after `dispose`.
  • **Serialize the whole replacement transaction** when upload and derived-resource baking share mutable GPU buffers. Serializing upload alone still lets an older readback install stale results; retain caller errors without poisoning later requests.
  • **Add a test that counts and bytes return to baseline** after resize, rebuild and repeated reset.

Depth, blending and targets

  • **Depth is an access contract** (`read`, `read-write`, `prepassed`), and the convention is engine-wide. Prefer reverse-Z on `depth32float` (clear 0, compare `greater`). Compare direction, clear value and format change together or not at all.
  • **Opaque geometry never alpha-blends.** Translucent passes read depth and never write it.
  • **A line drawn in pieces joins by construction.** Additive pieces overlap and fade over the overlap, so the joins sum to one; blended pieces are cut square, since two over-composited fades never sum to one. Blended layers of one thing draw in layer order, not in the order their pieces were made.
  • **Dynamic light is data every material reads through one shading function.** Effects offer a bounded per-frame list of short-lived point lights; the shared shade call sums them for every lit layer. A glow sprite brightens air, never the surfaces round it, and a per-layer lighting hack drifts from the others.
  • **Overlays and UI are composited after post-processing,** unlit and ungraded. Anything that belongs in the world is drawn in the world.
  • **The depth prepass and the colour pass share one vertex stage** with an `@invariant` position, so their depth matches bit for bit.
  • **Use 4× MSAA** (the count WebGPU guarantees). Interpolate at the centroid any varying that a later screen-space test depends on.
  • **Composite each annotation as one group.** Its backing paints below its foreground strokes; selection priority moves the whole group. Fix occlusion through paint order, not by erasing intended backing coverage. Bound effect tails separately from stacking.
  • **Bound final rendered geometry, including every independent multiplier and drawn LOD.** Give shader variation bounds, CPU validation and culling one owner. View-dependent width expansion must not silently expand height; source dimensions alone cannot prove a final size cap.

TypeGPU and WebGPU gotchas

  • **Use one TypeGPU module instance in GPU probes.** Mixing a bundler-optimized import with a direct package URL (or a different cache query) duplicates internal symbols: imported shader functions can silently disappear from resolution and WGSL reports an unresolved call. Match the pass's actual module URL before changing shader code.
  • **Pin only the shared camera bind group** (`$idx(0)`). TypeGPU numbers the rest.
  • **A pipeline with no fragment stage is valid.** Use it for depth-only passes rather than writing `frag_depth`, which disables early-Z.
  • **WGSL `let` is immutable.** Reassign
Read more
Ships withdzhng-skills

AI skills for building software factories. My personal library of domain-agnostic agent skills, reused across every project.

Get the whole plugin
Stats
1,337
Stars
81
Forks
Active
Maintenance
HTML
Language
MIT
License
13h ago
Last commit
3mo ago
Created
5h ago
Added

Repo: dzhng/skills

Other skills on dzhng-skills.