--- name: r3f-materials description: Three.js materials in R3F, built-in materials (Standard, Physical, Basic, etc.), ShaderMaterial with custom GLSL, uniforms binding and animation, and material properties. Use when choosing materials, creating custom shaders, or binding dynamic uniforms. --- # R3F Materials Materials define surface appearance—color, texture, reflectivity, transparency, and custom shader effects. ## Quick Start ```tsx // Built-in material // Custom shader ``` ## Built-in Materials ### Material Comparison | Material | Lighting | Use Case | Performance | |----------|----------|----------|-------------| | `MeshBasicMaterial` | None | UI, unlit, debug | Fastest | | `MeshStandardMaterial` | PBR | General 3D | Good | | `MeshPhysicalMaterial` | PBR+ | Glass, car paint | Slower | | `MeshLambertMaterial` | Diffuse | Matte surfaces | Fast | | `MeshPhongMaterial` | Specular | Shiny plastic | Fast | | `MeshToonMaterial` | Cel-shaded | Stylized | Good | | `MeshNormalMaterial` | None | Debug normals | Fastest | | `MeshDepthMaterial` | None | Depth passes | Fastest | ### MeshBasicMaterial (Unlit) ```tsx ``` ### MeshStandardMaterial (PBR) ```tsx ``` ### MeshPhysicalMaterial (Advanced PBR) ```tsx ``` ### MeshToonMaterial (Cel-shaded) ```tsx // Create gradient texture const gradientTexture = useMemo(() => { const canvas = document.createElement('canvas'); canvas.width = 4; canvas.height = 1; const ctx = canvas.getContext('2d')!; // 4-step toon shading ctx.fillStyle = '#444'; ctx.fillRect(0, 0, 1, 1); ctx.fillStyle = '#888'; ctx.fillRect(1, 0, 1, 1); ctx.fillStyle = '#bbb'; ctx.fillRect(2, 0, 1, 1); ctx.fillStyle = '#fff'; ctx.fillRect(3, 0, 1, 1); const texture = new THREE.CanvasTexture(canvas); texture.minFilter = THREE.NearestFilter; texture.magFilter = THREE.NearestFilter; return texture; }, []); ``` ## Common Properties (All Materials) ```tsx ``` ## Textures ### Loading Textures ```tsx import { useTexture } from '@react-three/drei'; function TexturedMesh() { const [colorMap, normalMap, roughnessMap] = useTexture([ '/textures/color.jpg', '/textures/normal.jpg', '/textures/roughness.jpg' ]); return ( ); } ``` ### Texture Settings ```tsx import { useTexture } from '@react-three/drei'; import * as THREE from 'three'; const texture = useTexture('/texture.jpg', (tex) => { tex.wrapS = tex.wrapT = THREE.RepeatWrapping; tex.repeat.set(4, 4); tex.anisotropy = 16; // Sharper at angles }); ``` ## ShaderMaterial Full control via GLSL vertex and fragment shaders: ```tsx import { useRef } from 'react'; import { useFrame } from '@react-three/fiber'; import * as THREE from 'three'; const vertexShader = ` varying vec2 vUv; varying vec3 vNormal; void main() { vUv = uv; vNormal = normalize(normalMatrix * normal); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const fragmentShader = ` uniform float uTime; uniform vec3 uColor; varying vec2 vUv; varying vec3 vNormal; void main() { float pulse = sin(uTime * 2.0) * 0.5 + 0.5; vec3 color = mix(uColor, vec3(1.0), pulse * 0.3); // Simple rim lighting float rim = 1.0 - dot(vNormal, vec3(0.0, 0.0, 1.0)); color += rim * 0.5; gl_FragColor = vec4(color, 1.0); } `; function CustomShaderMesh() { const materialRef = useRef(null!); useFrame(({ clock }) => { materialRef.current.uniforms.uTime.value = clock.elapsedTime; }); return ( ); } ``` ## Uniforms ### Uniform Types ```tsx uniforms={{ // Scalars uFloat: { value: 1.0 }, uInt: { value: 1 }, uBool: { value: true }, // Vectors uVec2: { value: new THREE.Vector2(1, 2) }, uVec3: { value: new THREE.Vector3(1, 2, 3) }, uVec4: { value: new THREE.Vector4(1, 2, 3, 4) }, uColor: { value: new THREE.Color('#ff0000') }, // Matrices uMat3: { value: new THREE.Matrix3() }, uMat4: { value: new THREE.Matrix4() }, // Textures uTexture: { value: texture }, uCubeTexture: { value: cubeTexture }, // Arrays uFloatArray: { value: [1.0, 2.0, 3.0] }, uVec3Array: { value: [new THREE.Vector3(), new THREE.Vector3()] } }} ``` ### Animating Uniforms ```tsx function AnimatedShader() { const materialRef = useRef(null!); useFrame(({ clock, mouse }) => { const uniforms = materialRef.current.uniforms; uniforms.uTime.value = clock.elapsedTime; uniforms.uMouse.value.set(mouse.x, mouse.y); uniforms.uResolution.value.set(window.innerWidth, window.innerHeight); }); return ( ); } ``` ### Shared Uniforms ```tsx // Create shared uniform object const globalUniforms = useMemo(() => ({ uTime: { value: 0 }, uGlobalColor: { value: new THREE.Color('#00ff00') } }), []); // Update in useFrame useFrame(({ clock }) => { globalUniforms.uTime.value = clock.elapsedTime; }); // Use in multiple materials ``` ## RawShaderMaterial No built-in uniforms/attributes—full control: ```tsx ``` ## Material Extensions ### Extend Existing Materials ```tsx import { extend } from '@react-three/fiber'; import { shaderMaterial } from '@react-three/drei'; // Create extended material const GradientMaterial = shaderMaterial( // Uniforms { uColorA: new THREE.Color('#ff0000'), uColorB: new THREE.Color('#0000ff') }, // Vertex ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, // Fragment ` uniform vec3 uColorA; uniform vec3 uColorB; varying vec2 vUv; void main() { gl_FragColor = vec4(mix(uColorA, uColorB, vUv.y), 1.0); } ` ); // Register with R3F extend({ GradientMaterial }); // Use in JSX function Gradient() { return ( ); } ``` ## Performance Tips | Technique | When to Use | |-----------|-------------| | Share materials | Multiple meshes, same appearance | | Use cheaper materials | Distant objects (Basic vs Standard) | | Limit texture size | Mobile, large scene | | Disable unneeded features | `fog={false}`, `toneMapped={false}` | ### Material Reuse ```tsx // Define once const sharedMaterial = useMemo(() => ( ), []); // Reuse (same GPU program) {items.map((item, i) => ( {sharedMaterial} ))} ``` ## File Structure ``` r3f-materials/ ├── SKILL.md ├── references/ │ ├── pbr-properties.md # PBR material deep-dive │ ├── uniform-types.md # Complete uniform reference │ └── shader-templates.md # Common shader patterns └── scripts/ ├── materials/ │ ├── gradient.ts # Gradient shader material │ ├── fresnel.ts # Fresnel/rim effect │ └── dissolve.ts # Dissolve effect └── utils/ └── uniform-helpers.ts # Uniform animation utilities ``` ## Reference - `references/pbr-properties.md` — Deep-dive into PBR material properties - `references/uniform-types.md` — All uniform types and GLSL mappings - `references/shader-templates.md` — Common shader effect patterns