skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
impertio-studio/three.js-claude-skill-package127 installs

threejs-syntax-shaders

Use when writing custom GLSL shaders, creating ShaderMaterial or RawShaderMaterial, defining uniforms, or patching built-in materials with onBeforeCompile. Prevents the common mistake of wrong uniform format, missing needsUpdate on uniforms, or not including required defines. Covers ShaderMaterial, RawShaderMaterial, GLSL, uniforms, ShaderChunk, onBeforeCompile, defines, GLSL3. Keywords: ShaderMaterial, RawShaderMaterial, GLSL, vertex shader, fragment shader, uniform, varying, ShaderChunk, onBeforeCompile, custom shader, write shader, custom visual effect, GPU programming.

How do I install this agent skill?

npx skills add https://github.com/impertio-studio/three.js-claude-skill-package --skill threejs-syntax-shaders
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill provides instructions and reference material for writing custom Three.js shaders. It consists entirely of markdown documentation and code examples. No security risks were identified.

  • Socketpass

    No alerts

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

threejs-syntax-shaders

Quick Reference

ShaderMaterial vs RawShaderMaterial

AspectShaderMaterialRawShaderMaterial
Built-in uniformsAutomatically injectedNONE -- you MUST declare everything
Built-in attributesAutomatically declaredNONE -- you MUST declare everything
#include <chunk>SupportedNOT supported
Precision declarationAutomaticYou MUST add precision mediump float;
Use caseExtend Three.js renderingFull shader control, porting external shaders
PerformanceSlight overhead from unused built-insMinimal shader overhead

Uniform Type Map

GLSL TypeJavaScript Value
float{ value: 1.0 }
int{ value: 1 }
bool{ value: true }
vec2{ value: new THREE.Vector2() }
vec3{ value: new THREE.Vector3() } or { value: new THREE.Color() }
vec4{ value: new THREE.Vector4() }
mat3{ value: new THREE.Matrix3() }
mat4{ value: new THREE.Matrix4() }
sampler2D{ value: texture } (a THREE.Texture instance)
samplerCube{ value: cubeTexture }
float[]{ value: [1.0, 2.0, 3.0] }
vec3[]{ value: [new THREE.Vector3(), ...] }

Critical Warnings

NEVER pass a bare value as a uniform -- ALWAYS wrap it in { value: ... }. Writing uniforms: { uTime: 0.0 } silently fails; ALWAYS write uniforms: { uTime: { value: 0.0 } }.

NEVER declare built-in uniforms or attributes in a ShaderMaterial shader -- Three.js injects them automatically. Redeclaring causes a GLSL compilation error.

ALWAYS declare ALL uniforms, attributes, and precision in RawShaderMaterial shaders -- nothing is injected for you.

NEVER use gl_FragColor or texture2D() when glslVersion is THREE.GLSL3 -- use a declared out vec4 variable and texture() instead.

ALWAYS call material.needsUpdate = true after changing defines -- defines are compiled into the shader, so changes require recompilation.


ShaderMaterial

Constructor

import * as THREE from 'three';

const material = new THREE.ShaderMaterial({
  uniforms: {
    uTime: { value: 0.0 },
    uColor: { value: new THREE.Color(0x00ff00) },
    uTexture: { value: someTexture },
  },
  vertexShader: `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    uniform float uTime;
    uniform vec3 uColor;
    varying vec2 vUv;
    void main() {
      gl_FragColor = vec4(uColor * vUv.x, 1.0);
    }
  `,
  transparent: false,
  wireframe: false,
  side: THREE.FrontSide,
});

Properties

PropertyTypeDefaultDescription
uniformsObject{}{ name: { value: ... } } format
uniformsGroupsArray[]Uniform buffer objects (UBO)
vertexShaderstring--GLSL vertex shader source
fragmentShaderstring--GLSL fragment shader source
definesObject{}Preprocessor #define directives
extensionsObject{}GLSL extensions to enable
wireframebooleanfalseWireframe rendering
lightsbooleanfalsePass light uniforms to shader
fogbooleanfalsePass fog uniforms to shader
clippingbooleanfalseEnable clipping planes
glslVersionstring | nullnullnull for GLSL1, THREE.GLSL3 for GLSL 3.0 ES
defaultAttributeValuesObject--Fallback values for missing attributes

Built-in Uniforms (ShaderMaterial Only)

These are injected automatically. NEVER declare them yourself.

// Transform matrices
uniform mat4 modelMatrix;           // Object -> World
uniform mat4 modelViewMatrix;       // Object -> Camera
uniform mat4 projectionMatrix;      // Camera -> Clip
uniform mat4 viewMatrix;            // World -> Camera
uniform mat3 normalMatrix;          // Transpose inverse of modelViewMatrix

// Camera
uniform vec3 cameraPosition;        // Camera world position

// When lights: true
uniform vec3 ambientLightColor;
// Plus structured arrays for directional, point, spot, hemisphere lights

Built-in Attributes (ShaderMaterial Only)

These are injected automatically. NEVER declare them yourself.

attribute vec3 position;    // Vertex position
attribute vec3 normal;      // Vertex normal
attribute vec2 uv;          // Primary UV coordinates
attribute vec2 uv2;         // Secondary UV (for aoMap, lightMap)
attribute vec4 tangent;     // Tangent vector (if computeTangents was called)
attribute vec3 color;       // Vertex color (if geometry has color attribute)

RawShaderMaterial

Use when you need full control over the shader source. NOTHING is injected.

const material = new THREE.RawShaderMaterial({
  uniforms: {
    uModelViewMatrix: { value: new THREE.Matrix4() },
    uProjectionMatrix: { value: new THREE.Matrix4() },
  },
  vertexShader: `
    precision highp float;
    attribute vec3 position;
    uniform mat4 uModelViewMatrix;
    uniform mat4 uProjectionMatrix;
    void main() {
      gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    precision highp float;
    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
  `,
});

ALWAYS add precision highp float; (or mediump) at the top of both shaders in RawShaderMaterial. Omitting precision causes a GLSL compilation error on mobile and some desktop drivers.


ShaderChunk -- Reusing Three.js Shader Code

THREE.ShaderChunk contains all internal shader fragments. Use #include <chunk_name> in ShaderMaterial (NOT RawShaderMaterial).

Common Chunks

ChunkPurpose
<common>Shared constants and functions (PI, saturate, etc.)
<fog_pars_vertex> / <fog_vertex>Fog support (vertex)
<fog_pars_fragment> / <fog_fragment>Fog support (fragment)
<shadowmap_pars_vertex> / <shadowmap_vertex>Shadow support (vertex)
<shadowmap_pars_fragment> / <shadowmap_fragment>Shadow support (fragment)
<lights_pars_begin>Light structure declarations
<begin_vertex>Initializes transformed variable from position
<project_vertex>Applies modelViewMatrix and projectionMatrix
<normal_fragment_begin>Normal mapping setup
<color_pars_vertex> / <color_vertex>Vertex color support

Accessing Chunks Programmatically

// Read the source of any chunk
console.log(THREE.ShaderChunk.common);
console.log(THREE.ShaderChunk.fog_pars_vertex);

onBeforeCompile -- Patching Built-in Materials

Modify an existing material's shader at compile time. This preserves PBR lighting, shadows, and all built-in features.

const material = new THREE.MeshStandardMaterial({ color: 0xff0000 });

material.onBeforeCompile = (shader) => {
  shader.uniforms.uTime = { value: 0.0 };

  shader.vertexShader = shader.vertexShader.replace(
    '#include <begin_vertex>',
    `
    #include <begin_vertex>
    transformed.y += sin(transformed.x * 5.0 + uTime) * 0.5;
    `
  );

  // Store reference for uniform updates
  material.userData.shader = shader;
};

// ALWAYS override customProgramCacheKey when using onBeforeCompile
material.customProgramCacheKey = () => 'my-wavy-material';

// In animation loop
if (material.userData.shader) {
  material.userData.shader.uniforms.uTime.value = clock.getElapsedTime();
}

ALWAYS override customProgramCacheKey() when using onBeforeCompile -- without it, Three.js may reuse a cached unpatched shader program, causing your modifications to silently disappear.

ALWAYS check material.userData.shader exists before accessing uniforms -- the shader object is created lazily on first render and can be recreated when material.needsUpdate = true.


Defines -- Preprocessor Directives

const material = new THREE.ShaderMaterial({
  defines: {
    USE_FOG: '',           // #define USE_FOG
    MAX_LIGHTS: 4,         // #define MAX_LIGHTS 4
    EPSILON: '0.001',      // #define EPSILON 0.001
  },
  // ...shaders
});

Changing defines at runtime:

material.defines.MAX_LIGHTS = 8;
material.needsUpdate = true;  // REQUIRED -- triggers recompilation

GLSL3 Mode

const material = new THREE.ShaderMaterial({
  glslVersion: THREE.GLSL3,
  vertexShader: `
    in vec3 position;           // 'attribute' becomes 'in'
    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;
    out vec3 vPosition;         // 'varying' becomes 'out'

    void main() {
      vPosition = position;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    precision highp float;
    in vec3 vPosition;          // 'varying' becomes 'in'
    out vec4 fragColor;         // replaces gl_FragColor

    void main() {
      fragColor = vec4(vPosition * 0.5 + 0.5, 1.0);
    }
  `,
});

GLSL1 vs GLSL3 Syntax

GLSL1GLSL3Context
attributeinVertex shader inputs
varying (vertex)outVertex shader outputs
varying (fragment)inFragment shader inputs
gl_FragColorDeclared out vec4Fragment shader output
texture2D()texture()Texture sampling
textureCube()texture()Cube texture sampling

Uniform Update Pattern

// At creation
const material = new THREE.ShaderMaterial({
  uniforms: {
    uTime: { value: 0.0 },
    uResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
    uMouse: { value: new THREE.Vector2() },
  },
  vertexShader: '...',
  fragmentShader: '...',
});

// In animation loop -- update the .value property directly
function animate() {
  material.uniforms.uTime.value = performance.now() / 1000;
  material.uniforms.uMouse.value.set(mouseX, mouseY);
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

NEVER replace the uniform object itself (e.g., material.uniforms.uTime = { value: 5 }). ALWAYS mutate the existing .value property. Replacing the object breaks the internal reference.


Reference Links

Official Sources

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/impertio-studio/three.js-claude-skill-package/threejs-syntax-shaders">View threejs-syntax-shaders on skillZs</a>