Create 3D scenes, interactive experiences, and visual effects using Three.js. Use when user requests 3D graphics, WebGL experiences, 3D visualizations, animations, or interactive 3D elements.
npx mdskills install sickn33/threejs-skills@sickn33? Sign in with GitHub to claim this listing.Comprehensive Three.js guide with excellent patterns, workarounds, and troubleshooting for CDN constraints
1---2name: threejs-skills3description: Create 3D scenes, interactive experiences, and visual effects using Three.js. Use when user requests 3D graphics, WebGL experiences, 3D visualizations, animations, or interactive 3D elements.4source: https://github.com/CloudAI-X/threejs-skills5risk: safe6---78# Three.js Skills910Systematically create high-quality 3D scenes and interactive experiences using Three.js best practices.1112## When to Use1314- Requests 3D visualizations or graphics ("create a 3D model", "show in 3D")15- Wants interactive 3D experiences ("rotating cube", "explorable scene")16- Needs WebGL or canvas-based rendering17- Asks for animations, particles, or visual effects18- Mentions Three.js, WebGL, or 3D rendering19- Wants to visualize data in 3D space2021## Core Setup Pattern2223### 1. Essential Three.js Imports2425Always use the correct CDN version (r128):2627```javascript28import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js";29```3031**CRITICAL**: Do NOT use example imports like `THREE.OrbitControls` - they won't work on the CDN.3233### 2. Scene Initialization3435Every Three.js artifact needs these core components:3637```javascript38// Scene - contains all 3D objects39const scene = new THREE.Scene();4041// Camera - defines viewing perspective42const camera = new THREE.PerspectiveCamera(43 75, // Field of view44 window.innerWidth / window.innerHeight, // Aspect ratio45 0.1, // Near clipping plane46 1000, // Far clipping plane47);48camera.position.z = 5;4950// Renderer - draws the scene51const renderer = new THREE.WebGLRenderer({ antialias: true });52renderer.setSize(window.innerWidth, window.innerHeight);53document.body.appendChild(renderer.domElement);54```5556### 3. Animation Loop5758Use requestAnimationFrame for smooth rendering:5960```javascript61function animate() {62 requestAnimationFrame(animate);6364 // Update object transformations here65 mesh.rotation.x += 0.01;66 mesh.rotation.y += 0.01;6768 renderer.render(scene, camera);69}70animate();71```7273## Systematic Development Process7475### 1. Define the Scene7677Start by identifying:7879- **What objects** need to be rendered80- **Camera position** and field of view81- **Lighting setup** required82- **Interaction model** (static, rotating, user-controlled)8384### 2. Build Geometry8586Choose appropriate geometry types:8788**Basic Shapes:**8990- `BoxGeometry` - cubes, rectangular prisms91- `SphereGeometry` - spheres, planets92- `CylinderGeometry` - cylinders, tubes93- `PlaneGeometry` - flat surfaces, ground planes94- `TorusGeometry` - donuts, rings9596**IMPORTANT**: Do NOT use `CapsuleGeometry` (introduced in r142, not available in r128)9798**Alternatives for capsules:**99100- Combine `CylinderGeometry` + 2 `SphereGeometry`101- Use `SphereGeometry` with adjusted parameters102- Create custom geometry with vertices103104### 3. Apply Materials105106Choose materials based on visual needs:107108**Common Materials:**109110- `MeshBasicMaterial` - unlit, flat colors (no lighting needed)111- `MeshStandardMaterial` - physically-based, realistic (needs lighting)112- `MeshPhongMaterial` - shiny surfaces with specular highlights113- `MeshLambertMaterial` - matte surfaces, diffuse reflection114115```javascript116const material = new THREE.MeshStandardMaterial({117 color: 0x00ff00,118 metalness: 0.5,119 roughness: 0.5,120});121```122123### 4. Add Lighting124125**If using lit materials** (Standard, Phong, Lambert), add lights:126127```javascript128// Ambient light - general illumination129const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);130scene.add(ambientLight);131132// Directional light - like sunlight133const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);134directionalLight.position.set(5, 5, 5);135scene.add(directionalLight);136```137138**Skip lighting** if using `MeshBasicMaterial` - it's unlit by design.139140### 5. Handle Responsiveness141142Always add window resize handling:143144```javascript145window.addEventListener("resize", () => {146 camera.aspect = window.innerWidth / window.innerHeight;147 camera.updateProjectionMatrix();148 renderer.setSize(window.innerWidth, window.innerHeight);149});150```151152## Common Patterns153154### Rotating Object155156```javascript157function animate() {158 requestAnimationFrame(animate);159 mesh.rotation.x += 0.01;160 mesh.rotation.y += 0.01;161 renderer.render(scene, camera);162}163```164165### Custom Camera Controls (OrbitControls Alternative)166167Since `THREE.OrbitControls` isn't available on CDN, implement custom controls:168169```javascript170let isDragging = false;171let previousMousePosition = { x: 0, y: 0 };172173renderer.domElement.addEventListener("mousedown", () => {174 isDragging = true;175});176177renderer.domElement.addEventListener("mouseup", () => {178 isDragging = false;179});180181renderer.domElement.addEventListener("mousemove", (event) => {182 if (isDragging) {183 const deltaX = event.clientX - previousMousePosition.x;184 const deltaY = event.clientY - previousMousePosition.y;185186 // Rotate camera around scene187 const rotationSpeed = 0.005;188 camera.position.x += deltaX * rotationSpeed;189 camera.position.y -= deltaY * rotationSpeed;190 camera.lookAt(scene.position);191 }192193 previousMousePosition = { x: event.clientX, y: event.clientY };194});195196// Zoom with mouse wheel197renderer.domElement.addEventListener("wheel", (event) => {198 event.preventDefault();199 camera.position.z += event.deltaY * 0.01;200 camera.position.z = Math.max(2, Math.min(20, camera.position.z)); // Clamp201});202```203204### Raycasting for Object Selection205206Detect mouse clicks and hovers on 3D objects:207208```javascript209const raycaster = new THREE.Raycaster();210const mouse = new THREE.Vector2();211const clickableObjects = []; // Array of meshes that can be clicked212213// Update mouse position214window.addEventListener("mousemove", (event) => {215 mouse.x = (event.clientX / window.innerWidth) * 2 - 1;216 mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;217});218219// Detect clicks220window.addEventListener("click", () => {221 raycaster.setFromCamera(mouse, camera);222 const intersects = raycaster.intersectObjects(clickableObjects);223224 if (intersects.length > 0) {225 const clickedObject = intersects[0].object;226 // Handle click - change color, scale, etc.227 clickedObject.material.color.set(0xff0000);228 }229});230231// Hover effect in animation loop232function animate() {233 requestAnimationFrame(animate);234235 raycaster.setFromCamera(mouse, camera);236 const intersects = raycaster.intersectObjects(clickableObjects);237238 // Reset all objects239 clickableObjects.forEach((obj) => {240 obj.scale.set(1, 1, 1);241 });242243 // Highlight hovered object244 if (intersects.length > 0) {245 intersects[0].object.scale.set(1.2, 1.2, 1.2);246 document.body.style.cursor = "pointer";247 } else {248 document.body.style.cursor = "default";249 }250251 renderer.render(scene, camera);252}253```254255### Particle System256257```javascript258const particlesGeometry = new THREE.BufferGeometry();259const particlesCount = 1000;260const posArray = new Float32Array(particlesCount * 3);261262for (let i = 0; i < particlesCount * 3; i++) {263 posArray[i] = (Math.random() - 0.5) * 10;264}265266particlesGeometry.setAttribute(267 "position",268 new THREE.BufferAttribute(posArray, 3),269);270271const particlesMaterial = new THREE.PointsMaterial({272 size: 0.02,273 color: 0xffffff,274});275276const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);277scene.add(particlesMesh);278```279280### User Interaction (Mouse Movement)281282```javascript283let mouseX = 0;284let mouseY = 0;285286document.addEventListener("mousemove", (event) => {287 mouseX = (event.clientX / window.innerWidth) * 2 - 1;288 mouseY = -(event.clientY / window.innerHeight) * 2 + 1;289});290291function animate() {292 requestAnimationFrame(animate);293 camera.position.x = mouseX * 2;294 camera.position.y = mouseY * 2;295 camera.lookAt(scene.position);296 renderer.render(scene, camera);297}298```299300### Loading Textures301302```javascript303const textureLoader = new THREE.TextureLoader();304const texture = textureLoader.load("texture-url.jpg");305306const material = new THREE.MeshStandardMaterial({307 map: texture,308});309```310311## Best Practices312313### Performance314315- **Reuse geometries and materials** when creating multiple similar objects316- **Use `BufferGeometry`** for custom shapes (more efficient)317- **Limit particle counts** to maintain 60fps (start with 1000-5000)318- **Dispose of resources** when removing objects:319 ```javascript320 geometry.dispose();321 material.dispose();322 texture.dispose();323 ```324325### Visual Quality326327- Always set `antialias: true` on renderer for smooth edges328- Use appropriate camera FOV (45-75 degrees typical)329- Position lights thoughtfully - avoid overlapping multiple bright lights330- Add ambient + directional lighting for realistic scenes331332### Code Organization333334- Initialize scene, camera, renderer at the top335- Group related objects (e.g., all particles in one group)336- Keep animation logic in the animate function337- Separate object creation into functions for complex scenes338339### Common Pitfalls to Avoid340341- ❌ Using `THREE.OrbitControls` - not available on CDN342- ❌ Using `THREE.CapsuleGeometry` - requires r142+343- ❌ Forgetting to add objects to scene with `scene.add()`344- ❌ Using lit materials without adding lights345- ❌ Not handling window resize346- ❌ Forgetting to call `renderer.render()` in animation loop347348## Example Workflow349350User: "Create an interactive 3D sphere that responds to mouse movement"3513521. **Setup**: Import Three.js (r128), create scene/camera/renderer3532. **Geometry**: Create `SphereGeometry(1, 32, 32)` for smooth sphere3543. **Material**: Use `MeshStandardMaterial` for realistic look3554. **Lighting**: Add ambient + directional lights3565. **Interaction**: Track mouse position, update camera3576. **Animation**: Rotate sphere, render continuously3587. **Responsive**: Add window resize handler3598. **Result**: Smooth, interactive 3D sphere ✓360361## Troubleshooting362363**Black screen / Nothing renders:**364365- Check if objects added to scene366- Verify camera position isn't inside objects367- Ensure renderer.render() is called368- Add lights if using lit materials369370**Poor performance:**371372- Reduce particle count373- Lower geometry detail (segments)374- Reuse materials/geometries375- Check browser console for errors376377**Objects not visible:**378379- Check object position vs camera position380- Verify material has visible color/properties381- Ensure camera far plane includes objects382- Add lighting if needed383384## Advanced Techniques385386### Visual Polish for Portfolio-Grade Rendering387388**Shadows:**389390```javascript391// Enable shadows on renderer392renderer.shadowMap.enabled = true;393renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Soft shadows394395// Light that casts shadows396const directionalLight = new THREE.DirectionalLight(0xffffff, 1);397directionalLight.position.set(5, 10, 5);398directionalLight.castShadow = true;399400// Configure shadow quality401directionalLight.shadow.mapSize.width = 2048;402directionalLight.shadow.mapSize.height = 2048;403directionalLight.shadow.camera.near = 0.5;404directionalLight.shadow.camera.far = 50;405406scene.add(directionalLight);407408// Objects cast and receive shadows409mesh.castShadow = true;410mesh.receiveShadow = true;411412// Ground plane receives shadows413const groundGeometry = new THREE.PlaneGeometry(20, 20);414const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x808080 });415const ground = new THREE.Mesh(groundGeometry, groundMaterial);416ground.rotation.x = -Math.PI / 2;417ground.receiveShadow = true;418scene.add(ground);419```420421**Environment Maps & Reflections:**422423```javascript424// Create environment map from cubemap425const loader = new THREE.CubeTextureLoader();426const envMap = loader.load([427 "px.jpg",428 "nx.jpg", // positive x, negative x429 "py.jpg",430 "ny.jpg", // positive y, negative y431 "pz.jpg",432 "nz.jpg", // positive z, negative z433]);434435scene.environment = envMap; // Affects all PBR materials436scene.background = envMap; // Optional: use as skybox437438// Or apply to specific materials439const material = new THREE.MeshStandardMaterial({440 metalness: 1.0,441 roughness: 0.1,442 envMap: envMap,443});444```445446**Tone Mapping & Output Encoding:**447448```javascript449// Improve color accuracy and HDR rendering450renderer.toneMapping = THREE.ACESFilmicToneMapping;451renderer.toneMappingExposure = 1.0;452renderer.outputEncoding = THREE.sRGBEncoding;453454// Makes colors more vibrant and realistic455```456457**Fog for Depth:**458459```javascript460// Linear fog461scene.fog = new THREE.Fog(0xcccccc, 10, 50); // color, near, far462463// Or exponential fog (more realistic)464scene.fog = new THREE.FogExp2(0xcccccc, 0.02); // color, density465```466467### Custom Geometry from Vertices468469```javascript470const geometry = new THREE.BufferGeometry();471const vertices = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0]);472geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));473```474475### Post-Processing Effects476477While advanced post-processing may not be available in r128 CDN, basic effects can be achieved with shaders and render targets.478479### Group Objects480481```javascript482const group = new THREE.Group();483group.add(mesh1);484group.add(mesh2);485group.rotation.y = Math.PI / 4;486scene.add(group);487```488489## Summary490491Three.js artifacts require systematic setup:4924931. Import correct CDN version (r128)4942. Initialize scene, camera, renderer4953. Create geometry + material = mesh4964. Add lighting if using lit materials4975. Implement animation loop4986. Handle window resize4997. Avoid r128 incompatible features500501Follow these patterns for reliable, performant 3D experiences.502503## Modern Three.js & Production Practices504505While this skill focuses on CDN-based Three.js (r128) for artifact compatibility, here's what you'd do in production environments:506507### Modular Imports with Build Tools508509```javascript510// In production with npm/vite/webpack:511import * as THREE from "three";512import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";513import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";514import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";515```516517**Benefits:**518519- Tree-shaking (smaller bundle sizes)520- Access to full example library (OrbitControls, loaders, etc.)521- Latest Three.js features (r150+)522- TypeScript support523524### Animation Libraries (GSAP Integration)525526```javascript527// Smooth timeline-based animations528import gsap from "gsap";529530// Instead of manual animation loops:531gsap.to(mesh.position, {532 x: 5,533 duration: 2,534 ease: "power2.inOut",535});536537// Complex sequences:538const timeline = gsap.timeline();539timeline540 .to(mesh.rotation, { y: Math.PI * 2, duration: 2 })541 .to(mesh.scale, { x: 2, y: 2, z: 2, duration: 1 }, "-=1");542```543544**Why GSAP:**545546- Professional easing functions547- Timeline control (pause, reverse, scrub)548- Better than manual lerping for complex animations549550### Scroll-Based Interactions551552```javascript553// Sync 3D animations with page scroll554let scrollY = window.scrollY;555556window.addEventListener("scroll", () => {557 scrollY = window.scrollY;558});559560function animate() {561 requestAnimationFrame(animate);562563 // Rotate based on scroll position564 mesh.rotation.y = scrollY * 0.001;565566 // Move camera through scene567 camera.position.y = -(scrollY / window.innerHeight) * 10;568569 renderer.render(scene, camera);570}571```572573**Advanced scroll libraries:**574575- ScrollTrigger (GSAP plugin)576- Locomotive Scroll577- Lenis smooth scroll578579### Performance Optimization in Production580581```javascript582// Level of Detail (LOD)583const lod = new THREE.LOD();584lod.addLevel(highDetailMesh, 0); // Close up585lod.addLevel(mediumDetailMesh, 10); // Medium distance586lod.addLevel(lowDetailMesh, 50); // Far away587scene.add(lod);588589// Instanced meshes for many identical objects590const geometry = new THREE.BoxGeometry();591const material = new THREE.MeshStandardMaterial();592const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000);593594// Set transforms for each instance595const matrix = new THREE.Matrix4();596for (let i = 0; i < 1000; i++) {597 matrix.setPosition(598 Math.random() * 100,599 Math.random() * 100,600 Math.random() * 100,601 );602 instancedMesh.setMatrixAt(i, matrix);603}604```605606### Modern Loading Patterns607608```javascript609// In production, load 3D models:610import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";611612const loader = new GLTFLoader();613loader.load("model.gltf", (gltf) => {614 scene.add(gltf.scene);615616 // Traverse and setup materials617 gltf.scene.traverse((child) => {618 if (child.isMesh) {619 child.castShadow = true;620 child.receiveShadow = true;621 }622 });623});624```625626### When to Use What627628**CDN Approach (Current Skill):**629630- Quick prototypes and demos631- Educational content632- Artifacts and embedded experiences633- No build step required634635**Production Build Approach:**636637- Client projects and portfolios638- Complex applications639- Need latest features (r150+)640- Performance-critical applications641- Team collaboration with version control642643### Recommended Production Stack644645```646Three.js (latest) + Vite/Webpack647├── GSAP (animations)648├── React Three Fiber (optional - React integration)649├── Drei (helper components)650├── Leva (debug GUI)651└── Post-processing effects652```653654This skill provides CDN-compatible foundations. In production, you'd layer on these modern tools for professional results.655
Full transparency — inspect the skill content before installing.