
Webgpu Threejs Tsl
Ship WebGPU compute shaders in Three.js TSL without silent failures from JavaScript variable reassignment inside GPU kernels.
Overview
webgpu-threejs-tsl is an agent skill for the Build phase that documents correct Three.js TSL compute-shader patterns and the property-assignment rules GPU kernels require.
Install
npx skills add https://github.com/dgreenheck/webgpu-claude-skill --skill webgpu-threejs-tslWhat is this skill?
- Documents the critical split between TSL node property assignment (.y, .assign) versus JS variable reassignment inside I
- Provides working Fn() compute shader patterns for vec3 clamping and buffer element updates
- Explains why scalar floats lack .x/.y setters and how that breaks incremental updates in compute passes
- Table of works-vs-fails patterns for node.y, .assign(), and buffer.element(i).assign(v)
- Oriented to parallel GPU data processing via TSL rather than raw WGSL-only workflows
- 4-row works-vs-fails pattern table for TSL assignment semantics
Adoption & trust: 596 installs on skills.sh; 981 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent-generated TSL compute shader compiles but buffer values never update because reassignment inside If() blocks bypasses TSL’s node graph.
Who is it for?
Solo builders adding WebGPU compute simulations, particle fields, or GPU-side data transforms in a Three.js TSL codebase.
Skip if: Teams only doing CSS UI, REST-only backends with no WebGL/WebGPU, or projects standardized on raw WGSL without TSL.
When should I use this skill?
Implementing or debugging Three.js TSL compute shaders where buffer or vec3 updates inside If() blocks behave incorrectly.
What do I get? / Deliverables
After applying the skill, compute passes use property assignment and .assign() so GPU buffer writes match the logic you intended.
- Corrected TSL Fn().compute() shader patterns
- Buffer and vec3 update code that respects node property assignment
Recommended Skills
Journey fit
Graphics and parallel GPU work happen while building the interactive product surface, not during launch or ops. TSL compute shaders, node graphs, and buffer updates are frontend/WebGPU implementation concerns tied to Three.js rendering code.
How it compares
Reference skill for TSL node semantics—not a general Three.js scene-setup or React component generator.
Common Questions / FAQ
Who is webgpu-threejs-tsl for?
Indie and solo developers using Claude Code or Cursor to build WebGPU-backed Three.js apps who need compute shaders written in TSL rather than hand-maintained WGSL.
When should I use webgpu-threejs-tsl?
During Build (frontend) when implementing Fn().compute() kernels, fixing stuck buffer data, or reviewing agent output before you ship a WebGPU feature; also when debugging GPU passes in Ship (testing) after visual regressions.
Is webgpu-threejs-tsl safe to install?
It is documentation-style procedural knowledge with no mandated shell or network calls in the excerpt; review the Security Audits panel on this Prism page before trusting any third-party skill repo.
SKILL.md
READMESKILL.md - Webgpu Threejs Tsl
# TSL Compute Shaders Compute shaders run on the GPU for parallel processing of data. TSL makes them accessible through JavaScript. ## CRITICAL: TSL Node Property Assignment vs JS Variable Reassignment **TSL can intercept property assignments on nodes, but NOT JavaScript variable reassignment.** ### What Works vs What Doesn't | Pattern | Works? | Why | |---------|--------|-----| | `node.y = value` | ✅ | Property setter - TSL intercepts | | `node.x.assign(value)` | ✅ | TSL method call | | `buffer.element(i).assign(v)` | ✅ | TSL method call | | `variable = variable.add(1)` | ❌ | JS variable reassignment - TSL can't see it | ### This WORKS (property assignment on vec3): ```javascript // ✅ CORRECT - Property assignment on node object const computeShader = Fn(() => { const result = vec3(position); If(result.y.greaterThan(limit), () => { result.y = limit; // TSL intercepts property setters! }); return result; })(); ``` ### This does NOT work (JS variable reassignment): ```javascript // ❌ WRONG - JavaScript variable reassignment inside If() const computeShader = Fn(() => { let value = buffer.element(index).toFloat(); // Scalar float - no .x/.y properties If(condition, () => { value = value.add(1.0); // JS reassigns variable to NEW node - TSL can't track this! }); buffer.element(index).assign(value); // Uses ORIGINAL node, not the add result! })().compute(count); ``` **Why it fails:** `value = value.add(1.0)` creates a new TSL node and reassigns the JavaScript variable to point to it. But TSL can't intercept JavaScript variable assignment - it can only intercept property setters and method calls on TSL node objects. Since `value` is a scalar float (no `.x`/`.y` properties), you can't use property assignment. ### Solution 1: Use `select()` for Conditional Values ```javascript // ✅ CORRECT - Use select() for inline conditionals import { select } from 'three/tsl'; const computeShader = Fn(() => { const currentValue = buffer.element(index).toFloat(); // select(condition, valueIfTrue, valueIfFalse) const newValue = select( condition, currentValue.add(1.0), // If true currentValue // If false ); buffer.element(index).assign(newValue); })().compute(count); ``` ### Solution 2: Use `.assign()` Directly on Buffer Elements Inside If() ```javascript // ✅ CORRECT - Direct buffer assignment inside If() works const computeShader = Fn(() => { const element = buffer.element(index); If(condition, () => { // Direct assignment to buffer element works! element.assign(element.add(1.0)); }); })().compute(count); ``` ### Solution 3: Use `.toVar()` for Mutable Variables ```javascript // ✅ CORRECT - Use .toVar() for variables that need mutation const computeShader = Fn(() => { // .toVar() creates a proper GPU variable that can be reassigned const value = buffer.element(index).toFloat().toVar(); If(condition, () => { value.assign(value.add(1.0)); // This works with .toVar()! }); buffer.element(index).assign(value); })().compute(count); ``` ### Quick Reference: When to Use What | Pattern | Use Case | |---------|----------| | `select(cond, a, b)` | Simple conditional value selection | | `element.assign()` inside `If()` | Direct buffer writes | | `.toVar()` + `assign()` | Complex logic with multiple conditionals | | Regular `If()` with direct assigns | Multiple buffer element updates | ### Example: Correct Stamp/Fade Pattern ```javascript // ✅ CORRECT implementation of conditional stamping const computeShader = Fn(() => { const currentFoam = foamBuffer.element(index).toFloat(); // Calculate distance const dist = worldPos.distance(stampPos); const radius = float(50.0); // Calculate falloff (will be 0 outside radius due to select) const falloff = float(1.0).sub(dist.div(radius)); // Use select() - returns falloff if inside radius, 0 if outside const foamToAdd = select(dist.lessThan(radius), falloff, float(0.0)); // Combine an