cloudai-x/threejs-skills/threejs-shaders
- community
Checking that the SKILL.md file is still in the repository.
Custom GLSL vertex and fragment shaders: uniforms, varyings, shader chunks, extending built-in materials, instanced attributes, plus the same effects as node materials with TSL on WebGPU. Use when writing a shader, a custom material or effect, moving vertices in a shader, or porting GLSL to TSL.
Install
npx vskill@latest install cloudai-x/threejs-skills/threejs-shadersSKILL.md
Three.js Shaders
Targets three.js r186. Examples use WebGLRenderer; the WebGPU and TSL section uses WebGPURenderer.
Quick Start
ShaderMaterial vs RawShaderMaterial
Every ShaderMaterial compiles as GLSL ES 3.00 — three.js always prepends #version 300 es (WebGL 1 support is gone). texture(), textureLod(), textureSize() and dFdx/fwidth work with no flags; texture2D, textureCube, attribute, varying and gl_FragColor are #define aliases, so most GLSL ES 1.00 shaders compile unchanged (not ones that name a variable texture, write gl_FragData or keep an #extension line, which fails because three.js puts declarations before your source; delete it, the features are core). Leave glslVersion unset: setting THREE.GLSL3 only removes the gl_FragColor alias, forcing you to declare your own output variable. ShaderMaterial injects the usual declarations:
RawShaderMaterial gets only #define SHADER_TYPE, #define SHADER_NAME and your defines (plus #version 300 es once glslVersion is set): no declarations and no precision statement. Always set glslVersion: THREE.GLSL3 (without it the shader is GLSL ES 1.00, which has no texture()), write precision highp float;, use in/out and declare your own output. Declare the matrices you need in the shader and never pass them through uniforms: the renderer sets modelMatrix, modelViewMatrix, projectionMatrix, viewMatrix, normalMatrix and cameraPosition for any program that declares them, and a same-named entry in uniforms is either overwritten every draw (modelMatrix, modelViewMatrix, normalMatrix) or replaces the camera's value (projectionMatrix, viewMatrix, cameraPosition).
Uniforms
The matching GLSL declarations — sample the texture with texture(mapValue, vUv):
Update a uniform by assigning .value from the frame loop (material.uniforms.floatValue.value = 2.0;); vectors and colors mutate in place (material.uniforms.vec3Value.value.set(1, 2, 3);). Never name a uniform position, normal, uv, modelViewMatrix or cameraPosition — three.js already declares those in the vertex shader, and the redeclaration is a compile error.
Output Color and Tone Mapping
THREE.Color converts hex input from sRGB to the linear working color space, so a color uniform holds linear values. A ShaderMaterial writes its output as-is: tone mapping and the output color space conversion happen only if the fragment shader ends with the two includes:
tonemapping_fragment applies renderer.toneMapping (a no-op with NoToneMapping); colorspace_fragment encodes to renderer.outputColorSpace (SRGBColorSpace by default). Without them, mid-tone colors render darker than the same hex on a built-in material. Both chunks write gl_FragColor, so they require glslVersion unset. An 8-bit RGBA texture with texture.colorSpace = THREE.SRGBColorSpace decodes to linear on sampling, so sampled colors combine correctly with the includes in place. A VideoTexture does not: three.js uploads it without sRGB decoding and decodes it only inside built-in materials, so decode it yourself with sRGBTransferEOTF(texture(videoMap, vUv)) (the ShaderMaterial prefix declares that function). Rendering into a render target, as inside an EffectComposer, both includes leave the color linear and OutputPass encodes it at the end.
Common Shader Patterns
Vertex Displacement
Fresnel
Use one space consistently. World space with cameraPosition:
normalMatrix * normal is view space — pair it with the view-space direction to the camera, never with cameraPosition. For rim lighting keep both in view space: in the vertex shader vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); vViewDir = -mvPosition.xyz; vNormal = normalMatrix * normal;, in the fragment shader float rim = pow(1.0 - max(dot(normalize(vViewDir), normalize(vNormal)), 0.0), 4.0);.
Dissolve
Instanced Meshes and Custom Attributes
Three.js declares position, normal, uv, instanceMatrix (for an InstancedMesh), instanceColor (once setColorAt has been called) and color (with vertexColors: true). Anything else — a custom per-vertex attribute, uv1 to uv3, tangent — you declare yourself with attribute (the alias for in).
For a per-vertex attribute use geometry.setAttribute("aOffset", new THREE.BufferAttribute(new Float32Array(geometry.attributes.position.count * 3), 3)); — the shader declaration is the same.
Extending Built-in Materials
onBeforeCompile rewrites the shader strings of a built-in material. It runs once per program, before includes are resolved.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/threejs-shaders/SKILL.md
Popularity
- Repository stars
- 1,846
- Repository forks
- 204
- 7-day trend score
- 38
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 21 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/cloudai-x/threejs-skills/threejs-shaders)