Building 3D Graphics
Quick Start
import { Canvas } from '@react-three/fiber'; import { OrbitControls, Environment } from '@react-three/drei';
export function Scene() { return ( <Canvas shadows camera={{ position: [5, 3, 5], fov: 50 }}> <ambientLight intensity={0.5} /> <directionalLight position={[10, 10, 5]} castShadow /> <mesh castShadow> <boxGeometry args={[1, 1, 1]} /> <meshStandardMaterial color="#4ecdc4" /> </mesh> <OrbitControls enableDamping /> <Environment preset="city" /> </Canvas> ); }
Features
Feature Description Guide
Scene Management Renderer, camera, controls setup with proper disposal ref/scene-manager.md
React Three Fiber Declarative 3D with React components and hooks ref/r3f-patterns.md
Custom Shaders GLSL vertex/fragment shaders with uniforms ref/shader-materials.md
Physics Rapier physics with rigid bodies and colliders ref/physics-system.md
Animation GSAP and Three.js animation mixer integration ref/animation.md
Performance LOD, instancing, frustum culling, texture optimization ref/optimization.md
Common Patterns
Animated Component with Interaction
function AnimatedBox({ position }: { position: [number, number, number] }) { const meshRef = useRef<THREE.Mesh>(null); const [hovered, setHovered] = useState(false);
useFrame((state, delta) => { if (meshRef.current) { meshRef.current.rotation.y += delta * 0.5; const scale = hovered ? 1.2 : 1; meshRef.current.scale.lerp(new THREE.Vector3(scale, scale, scale), 0.1); } });
return ( <mesh ref={meshRef} position={position} onPointerOver={() => setHovered(true)} onPointerOut={() => setHovered(false)} > <boxGeometry args={[1, 1, 1]} /> <meshStandardMaterial color={hovered ? '#ff6b6b' : '#4ecdc4'} /> </mesh> ); }
Instanced Mesh for Performance
function InstancedBoxes({ count = 1000 }: { count?: number }) { const meshRef = useRef<THREE.InstancedMesh>(null); const temp = useMemo(() => new THREE.Object3D(), []);
useEffect(() => { for (let i = 0; i < count; i++) { temp.position.set( (Math.random() - 0.5) * 50, (Math.random() - 0.5) * 50, (Math.random() - 0.5) * 50 ); temp.updateMatrix(); meshRef.current?.setMatrixAt(i, temp.matrix); } meshRef.current!.instanceMatrix.needsUpdate = true; }, [count, temp]);
return ( <instancedMesh ref={meshRef} args={[undefined, undefined, count]}> <boxGeometry args={[1, 1, 1]} /> <meshStandardMaterial /> </instancedMesh> ); }
Custom Shader Material
const GradientMaterial = shaderMaterial(
{ uTime: 0, uColorA: new THREE.Color('#ff6b6b'), uColorB: new THREE.Color('#4ecdc4') },
// Vertex shader
varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); },
// Fragment shader
uniform float uTime; uniform vec3 uColorA; uniform vec3 uColorB; varying vec2 vUv; void main() { vec3 color = mix(uColorA, uColorB, vUv.y + sin(uTime) * 0.1); gl_FragColor = vec4(color, 1.0); }
);
extend({ GradientMaterial });
Best Practices
Do Avoid
Use React Three Fiber for React apps Creating geometries/materials in render loops
Dispose geometries, materials, textures on unmount Too many dynamic lights (limit to 3-4)
Use instancing for many identical objects Skipping frustum culling in large scenes
Implement LOD for complex scenes Uncompressed high-resolution textures
Cap pixel ratio at 2: Math.min(window.devicePixelRatio, 2)
Transparent materials unless necessary
Use compressed textures (KTX2, Basis) Forgetting to update instanceMatrix after changes