# Three.js & React Three Fiber für 3D Web **Meta-Description:** 3D Webentwicklung mit Three.js und React Three Fiber. WebGL/WebGPU, interaktive Szenen und Performance-Optimierung. **Keywords:** Three.js, React Three Fiber, 3D Web, WebGL, WebGPU, R3F, Drei, Interactive 3D --- ## Einführung **Three.js** dominiert die 3D-Webentwicklung mit 270x mehr Downloads als Alternativen. **React Three Fiber** (R3F) bringt die deklarative React-Syntax in die 3D-Welt – perfekt für moderne Web-Projekte mit interaktiven Visualisierungen. --- ## Architecture Overview ``` ┌─────────────────────────────────────────────────────────────┐ │ THREE.JS / R3F ARCHITECTURE │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Application Layer: │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ React Components / Hooks / State │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ R3F Layer: ▼ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ React Three Fiber (React Renderer for Three.js) │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ │ │ Canvas │ │ Hooks │ │ Events │ │ │ │ │ │ (Root) │ │ (Frame) │ │(Pointer)│ │ │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ Drei (Helpers): │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ OrbitControls | Environment | Text3D | useGLTF │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ Three.js Core: ▼ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Scene | Camera | Renderer | Lights | Geometries │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ Graphics API: ▼ │ │ ┌───────────────────┬────────────────────┐ │ │ │ WebGL 2 │ WebGPU │ │ │ │ (Supported) │ (2026 Ready) │ │ │ └───────────────────┴────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Setup & Installation ```bash # React Three Fiber + Drei (Helpers) npm install three @react-three/fiber @react-three/drei # TypeScript Types npm install -D @types/three # Optional: Post-Processing, Physics npm install @react-three/postprocessing npm install @react-three/cannon ``` ```typescript // next.config.js (für Next.js) const nextConfig = { transpilePackages: ['three'], webpack: (config) => { config.externals.push({ 'sharp': 'commonjs sharp', 'canvas': 'commonjs canvas', }); return config; } }; ``` --- ## Basic Scene mit R3F ```tsx // components/Scene.tsx 'use client'; import { Canvas } from '@react-three/fiber'; import { OrbitControls, Environment, PerspectiveCamera } from '@react-three/drei'; import { Suspense } from 'react'; export function Scene() { return ( }> ); } function LoadingBox() { return ( ); } ``` --- ## Interaktive Objekte ```tsx // components/InteractiveObjects.tsx 'use client'; import { useRef, useState } from 'react'; import { useFrame } from '@react-three/fiber'; import { MeshWobbleMaterial, RoundedBox, Text } from '@react-three/drei'; import * as THREE from 'three'; interface BoxProps { position: [number, number, number]; } export function RotatingBox({ position }: BoxProps) { const meshRef = useRef(null); const [hovered, setHovered] = useState(false); const [clicked, setClicked] = useState(false); useFrame((state, delta) => { if (meshRef.current) { meshRef.current.rotation.x += delta * 0.5; meshRef.current.rotation.y += delta * 0.3; // Hover Animation const scale = hovered ? 1.2 : 1; meshRef.current.scale.lerp(new THREE.Vector3(scale, scale, scale), 0.1); } }); return ( setClicked(!clicked)} onPointerOver={() => setHovered(true)} onPointerOut={() => setHovered(false)} > ); } export function FloatingSphere({ position }: BoxProps) { const meshRef = useRef(null); useFrame((state) => { if (meshRef.current) { // Floating Animation meshRef.current.position.y = position[1] + Math.sin(state.clock.elapsedTime) * 0.3; } }); return ( ); } export function Floor() { return ( ); } ``` --- ## 3D Model Loading (GLTF) ```tsx // components/Model.tsx 'use client'; import { useRef, useEffect } from 'react'; import { useGLTF, useAnimations, Clone } from '@react-three/drei'; import { useFrame } from '@react-three/fiber'; import * as THREE from 'three'; interface ModelProps { url: string; position?: [number, number, number]; scale?: number; animate?: boolean; } export function Model({ url, position = [0, 0, 0], scale = 1, animate = true }: ModelProps) { const group = useRef(null); const { scene, animations } = useGLTF(url); const { actions, names } = useAnimations(animations, group); useEffect(() => { // Erste Animation abspielen if (animate && names.length > 0) { actions[names[0]]?.play(); } }, [actions, names, animate]); // Shadow Setup useEffect(() => { scene.traverse((child) => { if (child instanceof THREE.Mesh) { child.castShadow = true; child.receiveShadow = true; } }); }, [scene]); return ( ); } // Preload für bessere Performance useGLTF.preload('/models/robot.glb'); // Mit Draco Compression export function CompressedModel({ url }: { url: string }) { const { scene } = useGLTF(url, true); // true = Draco Loader return ; } ``` --- ## Custom Shaders ```tsx // components/CustomShader.tsx 'use client'; import { useRef, useMemo } from 'react'; import { useFrame, extend } from '@react-three/fiber'; import { shaderMaterial } from '@react-three/drei'; import * as THREE from 'three'; // Custom Shader Material const GradientMaterial = shaderMaterial( // Uniforms { uTime: 0, uColor1: new THREE.Color('#ff0000'), uColor2: new THREE.Color('#0000ff'), uIntensity: 1.0 }, // Vertex Shader ` varying vec2 vUv; varying vec3 vPosition; void main() { vUv = uv; vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, // Fragment Shader ` uniform float uTime; uniform vec3 uColor1; uniform vec3 uColor2; uniform float uIntensity; varying vec2 vUv; varying vec3 vPosition; void main() { // Animated Gradient float mixValue = sin(vUv.y * 3.14159 + uTime) * 0.5 + 0.5; vec3 color = mix(uColor1, uColor2, mixValue); // Wave Effect float wave = sin(vPosition.x * 5.0 + uTime * 2.0) * 0.1; color += wave * uIntensity; gl_FragColor = vec4(color, 1.0); } ` ); // Extend für JSX Support extend({ GradientMaterial }); // TypeScript Declaration declare global { namespace JSX { interface IntrinsicElements { gradientMaterial: any; } } } export function ShaderSphere() { const materialRef = useRef(null); useFrame((state) => { if (materialRef.current) { materialRef.current.uTime = state.clock.elapsedTime; } }); return ( ); } ``` --- ## Post-Processing Effects ```tsx // components/PostProcessing.tsx 'use client'; import { EffectComposer, Bloom, ChromaticAberration, Vignette } from '@react-three/postprocessing'; import { BlendFunction } from 'postprocessing'; export function Effects() { return ( {/* Bloom für leuchtende Effekte */} {/* Chromatische Aberration */} {/* Vignette */} ); } // Verwendung function SceneWithEffects() { return ( ); } ``` --- ## Physics mit Cannon ```tsx // components/PhysicsScene.tsx 'use client'; import { Physics, usePlane, useBox, useSphere } from '@react-three/cannon'; import { useRef } from 'react'; import * as THREE from 'three'; export function PhysicsScene() { return ( ); } function PhysicsGround() { const [ref] = usePlane(() => ({ rotation: [-Math.PI / 2, 0, 0], position: [0, 0, 0] })); return ( ); } function PhysicsBox({ position }: { position: [number, number, number] }) { const [ref] = useBox(() => ({ mass: 1, position, args: [1, 1, 1] })); return ( ); } function PhysicsBall({ position }: { position: [number, number, number] }) { const [ref] = useSphere(() => ({ mass: 2, position, args: [0.5] })); return ( ); } ``` --- ## Performance Optimierung ```tsx // components/OptimizedScene.tsx 'use client'; import { useRef, useMemo } from 'react'; import { useFrame } from '@react-three/fiber'; import { Instances, Instance, Detailed, useGLTF } from '@react-three/drei'; import * as THREE from 'three'; // Instancing für viele gleiche Objekte export function InstancedCubes({ count = 1000 }) { const positions = useMemo(() => { return Array.from({ length: count }, () => ({ position: [ (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20 ] as [number, number, number], rotation: [ Math.random() * Math.PI, Math.random() * Math.PI, Math.random() * Math.PI ] as [number, number, number], scale: 0.5 + Math.random() * 0.5 })); }, [count]); return ( {positions.map((props, i) => ( ))} ); } // Level of Detail (LOD) export function LODModel() { return ( {/* Höchste Qualität (nah) */} {/* Mittlere Qualität */} {/* Niedrige Qualität */} {/* Sehr niedrige Qualität (weit) */} ); } // Lazy Loading import { lazy, Suspense } from 'react'; const HeavyModel = lazy(() => import('./HeavyModel')); export function LazyScene() { return ( }> ); } ``` --- ## Best Practices | Aspect | Recommendation | |--------|----------------| | **Geometry** | Instancing für viele gleiche Objekte | | **Textures** | Compressed (WebP), Power of 2 | | **Models** | Draco compression, LOD | | **Shadows** | Nur wo nötig, Shadow Map Size | | **Animations** | useFrame statt setInterval | | **State** | Zustand außerhalb des Render Loops | | **Cleanup** | dispose() für Geometries/Materials | --- ## Fazit Three.js + React Three Fiber bietet: 1. **Deklarative Syntax**: React-Komponenten für 3D 2. **Ecosystem**: Drei, Cannon, Postprocessing 3. **WebGPU Ready**: Zukunftssicher mit WebGPU Support 4. **Performance**: Instancing, LOD, Lazy Loading Die beste Kombination für 3D im Web. --- ## Bildprompts 1. "Interactive 3D scene with rotating objects, React Three Fiber demo" 2. "WebGL shader effect with gradient colors, custom material" 3. "Physics simulation with falling objects, cannon.js integration" --- ## Quellen - [React Three Fiber Documentation](https://docs.pmnd.rs/react-three-fiber) - [Three.js Journey](https://threejs-journey.com/) - [Drei Helpers](https://github.com/pmndrs/drei) - [What's New in Three.js 2026](https://www.utsubo.com/blog/threejs-2026-what-changed)