--- name: dev-r3f-r3f-materials description: Material selection, shaders, and visual effects for R3F category: r3f --- # R3F Materials > "Materials define the soul of your 3D objects – choose wisely." ## When to Use This Skill Use when: - Choosing material type for objects - Creating custom shaders - Implementing visual effects - Optimizing material performance ## Quick Start ```tsx // Standard PBR material (recommended default) // Basic material (unlit, best performance) // Physical material (advanced PBR) ``` ## Decision Framework | Need | Material | Performance | | --------------- | ---------------------- | ------------- | | Unlit color | `meshBasicMaterial` | ⚡ Fastest | | Simple shading | `meshLambertMaterial` | ⚡⚡ Fast | | Stylized look | `meshToonMaterial` | ⚡⚡ Fast | | Realistic PBR | `meshStandardMaterial` | ⚡⚡⚡ Medium | | Glass/water | `meshPhysicalMaterial` | ⚡⚡⚡⚡ Slow | | Custom effects | `shaderMaterial` | Varies | | Matcap lighting | `meshMatcapMaterial` | ⚡⚡ Fast | ## Progressive Guide ### Level 1: Standard Materials ```tsx // Most common choice - good balance of quality and performance ``` ### Level 2: Textured Materials ```tsx import { useTexture } from '@react-three/drei'; function TexturedMesh() { const [colorMap, normalMap, roughnessMap] = useTexture([ '/textures/color.jpg', '/textures/normal.jpg', '/textures/roughness.jpg', ]); return ( ); } ``` ### Level 3: Matcap Materials (Fast & Stylized) ```tsx import { useMatcapTexture } from '@react-three/drei'; function MatcapMesh() { const [matcap] = useMatcapTexture('3B3C3F_DAD9D5_929290_ABACA8'); return ( ); } ``` ### Level 4: Custom Shaders ```tsx import { shaderMaterial } from '@react-three/drei'; import { extend, useFrame } from '@react-three/fiber'; const WaveShaderMaterial = shaderMaterial( { uTime: 0, uColor: new THREE.Color('hotpink') }, // Vertex shader ` uniform float uTime; varying vec2 vUv; void main() { vUv = uv; vec3 pos = position; pos.z += sin(pos.x * 4.0 + uTime) * 0.1; gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); } `, // Fragment shader ` uniform vec3 uColor; varying vec2 vUv; void main() { gl_FragColor = vec4(uColor, 1.0); } ` ); extend({ WaveShaderMaterial }); function WavyPlane() { const materialRef = useRef(); useFrame((state) => { if (materialRef.current) { materialRef.current.uTime = state.clock.elapsedTime; } }); return ( ); } ``` ### Level 5: Transparent & Glass ```tsx // Glass/water with transmission // Simple transparency ``` ## Material Comparison | Property | Basic | Lambert | Standard | Physical | | ------------ | ----- | ------- | -------- | ------------ | | Lighting | No | Diffuse | PBR | Advanced PBR | | Roughness | No | No | Yes | Yes | | Metalness | No | No | Yes | Yes | | Clearcoat | No | No | No | Yes | | Transmission | No | No | No | Yes | | GPU Cost | Low | Low | Medium | High | ## Anti-Patterns **DON'T:** - Use `meshPhysicalMaterial` everywhere (performance killer) - Create new materials every render - Forget `side={THREE.DoubleSide}` for visible interiors - Use transmission without proper scene setup - Skip texture optimization (uncompressed textures) **DO:** - Use simplest material that achieves the look - Reuse materials across similar objects - Use `meshBasicMaterial` for distant/small objects - Compress textures (WebP, basis universal) - Use material instances with drei ## Performance Tips ```tsx // Share materials across instances const sharedMaterial = useMemo( () => new THREE.MeshStandardMaterial({ color: 'red' }), [] ); // Use for many objects ... ... ``` ## Checklist Before finalizing materials: - [ ] Appropriate material type for use case - [ ] Textures are optimized (compressed, power-of-2) - [ ] Materials shared where possible - [ ] Transparent materials have `transparent: true` - [ ] Double-sided materials explicitly set - [ ] Shader uniforms use refs for animation ## Reference - [Three.js Materials](https://threejs.org/docs/#api/en/materials/Material) — Official docs - `developer/r3f/r3f-fundamentals.md` — R3F basics - `developer/performance/performance-basics.md` — Optimization