Treść z repozytorium z zachowaniem nagłówków, przykładów, kodu, tabel, linków i obrazów.
React Three Fiber shaders
Select the shader path
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.
- Use built-in materials when their properties express the effect. For custom WebGL shading, use Drei
shaderMaterialor a native<shaderMaterial>. - WebGPU uses node materials and TSL; GLSL
ShaderMaterialandonBeforeCompileare not portable to it. Read WebGPU and TSL only when that renderer is relevant. - A shader is not automatically lit, shadowed, fogged, instanced, or skinned. Choose the required features before replacing a built-in material.
Animated WebGL material
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>
)
}Uniforms and compilation
- Drei
shaderMaterialcreates uniform accessors: assignmaterial.uTime. Native ShaderMaterial usesmaterial.uniforms.uTime.value. - Keep uniform containers stable; mutate values without setting React state each frame. Do not set
material.needsUpdatefor a value-only uniform change. - Shader source, defines, and feature changes can require recompilation. Use the class's
keyfor hot reload; do not change React keys during animation. extend(Class)is available in Fiber 9. For a lowercase global element, augmentThreeElementswithThreeElement<typeof Class>; removedObject3DNodeis not a replacement for material typing.- GLSL strings are not checked by TypeScript. Render them and inspect shader compiler errors, including configurations with the actual renderer and effects.
- Shader source sits inside a JavaScript template literal, so a backtick or
${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.
Space, color, and geometry
- Keep normals, light directions, and view directions in the same coordinate space.
normalMatrix * normalis view space; do not dot it with a world-space camera direction. - CSS/hex colors passed through
Colorare converted to the linear working space. Numeric uniform vectors are already linear; avoid converting them twice. - Mark color input textures as
SRGBColorSpace; data textures useNoColorSpace. Texture sampling and output conversion must match the material/renderer pipeline. - For a WebGL shader writing directly to the canvas, apply tone mapping and output color conversion as in the example. Do not manually gamma-correct and also apply the output chunk. Let a composer own final output when rendering through one.
- Vertex deformation needs sufficient geometry subdivisions. If lighting is required, update normals consistently. For shadows, match deformation in depth/distance materials; CPU raycasts and bounds do not automatically follow GPU deformation.
- Native custom instancing shaders must account for
instanceMatrixand any per-instance attributes. Skinning and morph targets likewise require their corresponding shader logic.
Patching built-in WebGL materials
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.
Sources
- Drei shaderMaterial, Fiber type migration.
- ShaderMaterial, color management.
- Three.js migration guide — check only changes through the installed release.

