--- name: 3d-scene description: Use when building 3D scenes for web — Three.js, React Three Fiber (R3F), Spline embeds, GLTF/GLB loading, scroll-linked 3D, camera animations. Covers scene setup, model optimization, and performance budgets. arguments: - name: approach description: "Approach: r3f, threejs-vanilla, spline-embed (auto-detect if omitted)" required: false - name: interaction description: "Interaction: scroll-linked, orbit, hover, static (default: scroll-linked)" required: false --- # 3D Scene Skill ## Decision Matrix — Pick Approach | Need | Approach | Bundle Impact | Complexity | |------|----------|---------------|------------| | Product showcase with scroll | R3F + ScrollControls | ~150KB (Three.js) | Medium | | Hero 3D scene (no-code) | Spline embed | ~0KB (iframe) | Low | | Custom shaders + 3D | Three.js vanilla | ~150KB | High | | Lightweight shader-only | OGL | ~8KB | Medium | | Interactive configurator | R3F + Leva/dat.gui | ~150KB | Medium | --- ## 1. React Three Fiber (R3F) + Drei [E1] **Install:** ```bash npm i three @react-three/fiber @react-three/drei ``` ### Basic Scene ```jsx import { Canvas } from "@react-three/fiber"; import { OrbitControls, Environment, useGLTF } from "@react-three/drei"; function Model({ url }) { const { scene } = useGLTF(url); return ; } function Scene() { return ( ); } ``` ### ScrollControls (Scroll-Linked 3D) [E1] ```jsx import { Canvas, useFrame } from "@react-three/fiber"; import { ScrollControls, Scroll, useScroll } from "@react-three/drei"; function AnimatedModel() { const scroll = useScroll(); const ref = useRef(); useFrame(() => { const offset = scroll.offset; // 0 to 1 // Rotate model based on scroll ref.current.rotation.y = offset * Math.PI * 2; // Move camera/model along a path ref.current.position.y = offset * -5; }); return ( ); } function ScrollScene() { return ( {/* 3D content */} {/* HTML content overlaid */}

Section 2

Section 3

); } ``` ### useScroll Utilities ```jsx const scroll = useScroll(); // scroll.offset — 0 to 1 (overall progress) // scroll.delta — scroll speed // scroll.range(from, distance) — 0-1 within range // scroll.curve(from, distance) — bell curve within range // scroll.visible(from, distance) — boolean visibility useFrame(() => { // Animate only in section 2 (20%-40% of scroll) const sectionProgress = scroll.range(0.2, 0.2); ref.current.scale.setScalar(1 + sectionProgress * 0.5); // Fade in section 3 const visible = scroll.visible(0.4, 0.2); material.current.opacity = visible ? scroll.curve(0.4, 0.2) : 0; }); ``` ### R3F + GSAP (Alternative to ScrollControls) [E2] When you need GSAP's pin/snap with 3D: ```jsx import { useGSAP } from "@gsap/react"; import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; function GSAPModel() { const mesh = useRef(); useGSAP(() => { gsap.to(mesh.current.rotation, { y: Math.PI * 2, scrollTrigger: { trigger: "#scene-container", start: "top top", end: "+=3000", pin: true, scrub: 1, } }); }); return ...; } ``` --- ## 2. Spline Embeds [E2] **What:** No-code 3D design tool with web export. **Best for:** Quick 3D heroes, interactive product views, landing pages. ### Embed Methods ```jsx // Method 1: iframe (simplest, no bundle impact)