React Three Fiber shaders - GLSL, shaderMaterial, uniforms, custom effects. Use when creating custom visual effects, modifying vertices, writing fragment shaders, or extending built-in materials.
Inspect installed Fiber, Drei, Three.js, and renderer versions first. The example uses Fiber 9 / React 19 and WebGL. Preserve an existing project's versions.
shaderMaterial or a native <shaderMaterial>.ShaderMaterial and onBeforeCompile are not portable to it. Read WebGPU and TSL only when that renderer is relevant.Mount beneath Canvas. Keep the material class and extend call outside render; the local component avoids global JSX augmentation.
import { useRef } from 'react'
import { extend, useFrame } from '@react-three/fiber'
import { shaderMaterial } from '@react-three/drei'
import { Color } from 'three'
const WaveMaterial = shaderMaterial(
{ uTime: 0, uColor: new Color('coral') },
`uniform float uTime;
varying vec2 vUv;
void main() {
vUv = uv;
vec3 p = position;
p.z += sin(p.x * 4.0 + uTime) * 0.15;
gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
}`,
`uniform vec3 uColor;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(uColor * (0.4 + 0.6 * vUv.y), 1.0);
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`,
)
const Wave = extend(WaveMaterial)
export default function Example() {
const material = useRef<InstanceType<typeof WaveMaterial>>(null)
useFrame((_, delta) => {
if (material.current) material.current.uTime += delta
})
return (
<mesh>
<planeGeometry args={[3, 3, 32, 32]} />
<Wave ref={material} key={WaveMaterial.key} />
</mesh>
)
}
shaderMaterial creates uniform accessors: assign material.uTime. Native ShaderMaterial uses material.uniforms.uTime.value.material.needsUpdate for a value-only uniform change.key for hot reload; do not change React keys during animation.extend(Class) is available in Fiber 9. For a lowercase global element, augment ThreeElements with ThreeElement<typeof Class>; removed Object3DNode is not a replacement for material typing.${ anywhere in the GLSL, including in its comments, silently ends the string and breaks the module. Write shader comments without backticks and let the type-checker catch it rather than reading for it.normalMatrix * normal is view space; do not dot it with a world-space camera direction.Color are converted to the linear working space. Numeric uniform vectors are already linear; avoid converting them twice.SRGBColorSpace; data textures use NoColorSpace. Texture sampling and output conversion must match the material/renderer pipeline.instanceMatrix and any per-instance attributes. Skinning and morph targets likewise require their corresponding shader logic.Use onBeforeCompile only when retaining a built-in material's lighting is useful. Shader chunk names are version-sensitive: inspect the installed source, and render-test after a Three.js update.
Set the callback before first compilation. When a configuration changes generated GLSL, provide a matching customProgramCacheKey and trigger recompilation; keep animated values in uniforms. Do not assume .clone() or serialization preserves callbacks. Prefer node materials when the task already targets WebGPU.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer