From 5ac9d8b9b72d60884a52d208ced94a6e352ce89b Mon Sep 17 00:00:00 2001 From: Krishna-hehe Date: Fri, 13 Feb 2026 16:57:23 +0530 Subject: [PATCH] add comprehensive Three.js skill with interaction, polish, and production patterns Systematic guide covering r128 CDN setup, raycasting/custom controls, visual polish (shadows, environment maps, tone mapping), and modern production practices (GSAP, scroll interactions, build tools). Follows test-fixing skill structure with step-by-step workflows and troubleshooting. --- skills/threejs-skills/SKILL.md | 637 ++++++++++++++++++++++++++++++++- 1 file changed, 626 insertions(+), 11 deletions(-) diff --git a/skills/threejs-skills/SKILL.md b/skills/threejs-skills/SKILL.md index 29408eaa..3a27a00e 100644 --- a/skills/threejs-skills/SKILL.md +++ b/skills/threejs-skills/SKILL.md @@ -1,22 +1,637 @@ --- name: threejs-skills -description: "Three.js skills for creating 3D elements and interactive experiences" -source: "https://github.com/CloudAI-X/threejs-skills" -risk: safe +description: 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. --- -# Threejs Skills +# Three.js Skills -## Overview +Systematically create high-quality 3D scenes and interactive experiences using Three.js best practices. -Three.js skills for creating 3D elements and interactive experiences +## When to Use -## When to Use This Skill +- Requests 3D visualizations or graphics ("create a 3D model", "show in 3D") +- Wants interactive 3D experiences ("rotating cube", "explorable scene") +- Needs WebGL or canvas-based rendering +- Asks for animations, particles, or visual effects +- Mentions Three.js, WebGL, or 3D rendering +- Wants to visualize data in 3D space -Use this skill when you need to work with three.js skills for creating 3d elements and interactive experiences. +## Core Setup Pattern -## Instructions +### 1. Essential Three.js Imports -This skill provides guidance and patterns for three.js skills for creating 3d elements and interactive experiences. +Always use the correct CDN version (r128): -For more information, see the [source repository](https://github.com/CloudAI-X/threejs-skills). +```javascript +import * as THREE from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js'; +``` + +**CRITICAL**: Do NOT use example imports like `THREE.OrbitControls` - they won't work on the CDN. + +### 2. Scene Initialization + +Every Three.js artifact needs these core components: + +```javascript +// Scene - contains all 3D objects +const scene = new THREE.Scene(); + +// Camera - defines viewing perspective +const camera = new THREE.PerspectiveCamera( + 75, // Field of view + window.innerWidth / window.innerHeight, // Aspect ratio + 0.1, // Near clipping plane + 1000 // Far clipping plane +); +camera.position.z = 5; + +// Renderer - draws the scene +const renderer = new THREE.WebGLRenderer({ antialias: true }); +renderer.setSize(window.innerWidth, window.innerHeight); +document.body.appendChild(renderer.domElement); +``` + +### 3. Animation Loop + +Use requestAnimationFrame for smooth rendering: + +```javascript +function animate() { + requestAnimationFrame(animate); + + // Update object transformations here + mesh.rotation.x += 0.01; + mesh.rotation.y += 0.01; + + renderer.render(scene, camera); +} +animate(); +``` + +## Systematic Development Process + +### 1. Define the Scene + +Start by identifying: + +- **What objects** need to be rendered +- **Camera position** and field of view +- **Lighting setup** required +- **Interaction model** (static, rotating, user-controlled) + +### 2. Build Geometry + +Choose appropriate geometry types: + +**Basic Shapes:** +- `BoxGeometry` - cubes, rectangular prisms +- `SphereGeometry` - spheres, planets +- `CylinderGeometry` - cylinders, tubes +- `PlaneGeometry` - flat surfaces, ground planes +- `TorusGeometry` - donuts, rings + +**IMPORTANT**: Do NOT use `CapsuleGeometry` (introduced in r142, not available in r128) + +**Alternatives for capsules:** +- Combine `CylinderGeometry` + 2 `SphereGeometry` +- Use `SphereGeometry` with adjusted parameters +- Create custom geometry with vertices + +### 3. Apply Materials + +Choose materials based on visual needs: + +**Common Materials:** +- `MeshBasicMaterial` - unlit, flat colors (no lighting needed) +- `MeshStandardMaterial` - physically-based, realistic (needs lighting) +- `MeshPhongMaterial` - shiny surfaces with specular highlights +- `MeshLambertMaterial` - matte surfaces, diffuse reflection + +```javascript +const material = new THREE.MeshStandardMaterial({ + color: 0x00ff00, + metalness: 0.5, + roughness: 0.5 +}); +``` + +### 4. Add Lighting + +**If using lit materials** (Standard, Phong, Lambert), add lights: + +```javascript +// Ambient light - general illumination +const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); +scene.add(ambientLight); + +// Directional light - like sunlight +const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); +directionalLight.position.set(5, 5, 5); +scene.add(directionalLight); +``` + +**Skip lighting** if using `MeshBasicMaterial` - it's unlit by design. + +### 5. Handle Responsiveness + +Always add window resize handling: + +```javascript +window.addEventListener('resize', () => { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + renderer.setSize(window.innerWidth, window.innerHeight); +}); +``` + +## Common Patterns + +### Rotating Object + +```javascript +function animate() { + requestAnimationFrame(animate); + mesh.rotation.x += 0.01; + mesh.rotation.y += 0.01; + renderer.render(scene, camera); +} +``` + +### Custom Camera Controls (OrbitControls Alternative) + +Since `THREE.OrbitControls` isn't available on CDN, implement custom controls: + +```javascript +let isDragging = false; +let previousMousePosition = { x: 0, y: 0 }; + +renderer.domElement.addEventListener('mousedown', () => { + isDragging = true; +}); + +renderer.domElement.addEventListener('mouseup', () => { + isDragging = false; +}); + +renderer.domElement.addEventListener('mousemove', (event) => { + if (isDragging) { + const deltaX = event.clientX - previousMousePosition.x; + const deltaY = event.clientY - previousMousePosition.y; + + // Rotate camera around scene + const rotationSpeed = 0.005; + camera.position.x += deltaX * rotationSpeed; + camera.position.y -= deltaY * rotationSpeed; + camera.lookAt(scene.position); + } + + previousMousePosition = { x: event.clientX, y: event.clientY }; +}); + +// Zoom with mouse wheel +renderer.domElement.addEventListener('wheel', (event) => { + event.preventDefault(); + camera.position.z += event.deltaY * 0.01; + camera.position.z = Math.max(2, Math.min(20, camera.position.z)); // Clamp +}); +``` + +### Raycasting for Object Selection + +Detect mouse clicks and hovers on 3D objects: + +```javascript +const raycaster = new THREE.Raycaster(); +const mouse = new THREE.Vector2(); +const clickableObjects = []; // Array of meshes that can be clicked + +// Update mouse position +window.addEventListener('mousemove', (event) => { + mouse.x = (event.clientX / window.innerWidth) * 2 - 1; + mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; +}); + +// Detect clicks +window.addEventListener('click', () => { + raycaster.setFromCamera(mouse, camera); + const intersects = raycaster.intersectObjects(clickableObjects); + + if (intersects.length > 0) { + const clickedObject = intersects[0].object; + // Handle click - change color, scale, etc. + clickedObject.material.color.set(0xff0000); + } +}); + +// Hover effect in animation loop +function animate() { + requestAnimationFrame(animate); + + raycaster.setFromCamera(mouse, camera); + const intersects = raycaster.intersectObjects(clickableObjects); + + // Reset all objects + clickableObjects.forEach(obj => { + obj.scale.set(1, 1, 1); + }); + + // Highlight hovered object + if (intersects.length > 0) { + intersects[0].object.scale.set(1.2, 1.2, 1.2); + document.body.style.cursor = 'pointer'; + } else { + document.body.style.cursor = 'default'; + } + + renderer.render(scene, camera); +} +``` + +### Particle System + +```javascript +const particlesGeometry = new THREE.BufferGeometry(); +const particlesCount = 1000; +const posArray = new Float32Array(particlesCount * 3); + +for (let i = 0; i < particlesCount * 3; i++) { + posArray[i] = (Math.random() - 0.5) * 10; +} + +particlesGeometry.setAttribute( + 'position', + new THREE.BufferAttribute(posArray, 3) +); + +const particlesMaterial = new THREE.PointsMaterial({ + size: 0.02, + color: 0xffffff +}); + +const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial); +scene.add(particlesMesh); +``` + +### User Interaction (Mouse Movement) + +```javascript +let mouseX = 0; +let mouseY = 0; + +document.addEventListener('mousemove', (event) => { + mouseX = (event.clientX / window.innerWidth) * 2 - 1; + mouseY = -(event.clientY / window.innerHeight) * 2 + 1; +}); + +function animate() { + requestAnimationFrame(animate); + camera.position.x = mouseX * 2; + camera.position.y = mouseY * 2; + camera.lookAt(scene.position); + renderer.render(scene, camera); +} +``` + +### Loading Textures + +```javascript +const textureLoader = new THREE.TextureLoader(); +const texture = textureLoader.load('texture-url.jpg'); + +const material = new THREE.MeshStandardMaterial({ + map: texture +}); +``` + +## Best Practices + +### Performance + +- **Reuse geometries and materials** when creating multiple similar objects +- **Use `BufferGeometry`** for custom shapes (more efficient) +- **Limit particle counts** to maintain 60fps (start with 1000-5000) +- **Dispose of resources** when removing objects: + ```javascript + geometry.dispose(); + material.dispose(); + texture.dispose(); + ``` + +### Visual Quality + +- Always set `antialias: true` on renderer for smooth edges +- Use appropriate camera FOV (45-75 degrees typical) +- Position lights thoughtfully - avoid overlapping multiple bright lights +- Add ambient + directional lighting for realistic scenes + +### Code Organization + +- Initialize scene, camera, renderer at the top +- Group related objects (e.g., all particles in one group) +- Keep animation logic in the animate function +- Separate object creation into functions for complex scenes + +### Common Pitfalls to Avoid + +- ❌ Using `THREE.OrbitControls` - not available on CDN +- ❌ Using `THREE.CapsuleGeometry` - requires r142+ +- ❌ Forgetting to add objects to scene with `scene.add()` +- ❌ Using lit materials without adding lights +- ❌ Not handling window resize +- ❌ Forgetting to call `renderer.render()` in animation loop + +## Example Workflow + +User: "Create an interactive 3D sphere that responds to mouse movement" + +1. **Setup**: Import Three.js (r128), create scene/camera/renderer +2. **Geometry**: Create `SphereGeometry(1, 32, 32)` for smooth sphere +3. **Material**: Use `MeshStandardMaterial` for realistic look +4. **Lighting**: Add ambient + directional lights +5. **Interaction**: Track mouse position, update camera +6. **Animation**: Rotate sphere, render continuously +7. **Responsive**: Add window resize handler +8. **Result**: Smooth, interactive 3D sphere ✓ + +## Troubleshooting + +**Black screen / Nothing renders:** +- Check if objects added to scene +- Verify camera position isn't inside objects +- Ensure renderer.render() is called +- Add lights if using lit materials + +**Poor performance:** +- Reduce particle count +- Lower geometry detail (segments) +- Reuse materials/geometries +- Check browser console for errors + +**Objects not visible:** +- Check object position vs camera position +- Verify material has visible color/properties +- Ensure camera far plane includes objects +- Add lighting if needed + +## Advanced Techniques + +### Visual Polish for Portfolio-Grade Rendering + +**Shadows:** + +```javascript +// Enable shadows on renderer +renderer.shadowMap.enabled = true; +renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Soft shadows + +// Light that casts shadows +const directionalLight = new THREE.DirectionalLight(0xffffff, 1); +directionalLight.position.set(5, 10, 5); +directionalLight.castShadow = true; + +// Configure shadow quality +directionalLight.shadow.mapSize.width = 2048; +directionalLight.shadow.mapSize.height = 2048; +directionalLight.shadow.camera.near = 0.5; +directionalLight.shadow.camera.far = 50; + +scene.add(directionalLight); + +// Objects cast and receive shadows +mesh.castShadow = true; +mesh.receiveShadow = true; + +// Ground plane receives shadows +const groundGeometry = new THREE.PlaneGeometry(20, 20); +const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x808080 }); +const ground = new THREE.Mesh(groundGeometry, groundMaterial); +ground.rotation.x = -Math.PI / 2; +ground.receiveShadow = true; +scene.add(ground); +``` + +**Environment Maps & Reflections:** + +```javascript +// Create environment map from cubemap +const loader = new THREE.CubeTextureLoader(); +const envMap = loader.load([ + 'px.jpg', 'nx.jpg', // positive x, negative x + 'py.jpg', 'ny.jpg', // positive y, negative y + 'pz.jpg', 'nz.jpg' // positive z, negative z +]); + +scene.environment = envMap; // Affects all PBR materials +scene.background = envMap; // Optional: use as skybox + +// Or apply to specific materials +const material = new THREE.MeshStandardMaterial({ + metalness: 1.0, + roughness: 0.1, + envMap: envMap +}); +``` + +**Tone Mapping & Output Encoding:** + +```javascript +// Improve color accuracy and HDR rendering +renderer.toneMapping = THREE.ACESFilmicToneMapping; +renderer.toneMappingExposure = 1.0; +renderer.outputEncoding = THREE.sRGBEncoding; + +// Makes colors more vibrant and realistic +``` + +**Fog for Depth:** + +```javascript +// Linear fog +scene.fog = new THREE.Fog(0xcccccc, 10, 50); // color, near, far + +// Or exponential fog (more realistic) +scene.fog = new THREE.FogExp2(0xcccccc, 0.02); // color, density +``` + +### Custom Geometry from Vertices + +```javascript +const geometry = new THREE.BufferGeometry(); +const vertices = new Float32Array([ + -1, -1, 0, + 1, -1, 0, + 1, 1, 0 +]); +geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); +``` + +### Post-Processing Effects + +While advanced post-processing may not be available in r128 CDN, basic effects can be achieved with shaders and render targets. + +### Group Objects + +```javascript +const group = new THREE.Group(); +group.add(mesh1); +group.add(mesh2); +group.rotation.y = Math.PI / 4; +scene.add(group); +``` + +## Summary + +Three.js artifacts require systematic setup: +1. Import correct CDN version (r128) +2. Initialize scene, camera, renderer +3. Create geometry + material = mesh +4. Add lighting if using lit materials +5. Implement animation loop +6. Handle window resize +7. Avoid r128 incompatible features + +Follow these patterns for reliable, performant 3D experiences. + +## Modern Three.js & Production Practices + +While this skill focuses on CDN-based Three.js (r128) for artifact compatibility, here's what you'd do in production environments: + +### Modular Imports with Build Tools + +```javascript +// In production with npm/vite/webpack: +import * as THREE from 'three'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'; +``` + +**Benefits:** +- Tree-shaking (smaller bundle sizes) +- Access to full example library (OrbitControls, loaders, etc.) +- Latest Three.js features (r150+) +- TypeScript support + +### Animation Libraries (GSAP Integration) + +```javascript +// Smooth timeline-based animations +import gsap from 'gsap'; + +// Instead of manual animation loops: +gsap.to(mesh.position, { + x: 5, + duration: 2, + ease: 'power2.inOut' +}); + +// Complex sequences: +const timeline = gsap.timeline(); +timeline + .to(mesh.rotation, { y: Math.PI * 2, duration: 2 }) + .to(mesh.scale, { x: 2, y: 2, z: 2, duration: 1 }, '-=1'); +``` + +**Why GSAP:** +- Professional easing functions +- Timeline control (pause, reverse, scrub) +- Better than manual lerping for complex animations + +### Scroll-Based Interactions + +```javascript +// Sync 3D animations with page scroll +let scrollY = window.scrollY; + +window.addEventListener('scroll', () => { + scrollY = window.scrollY; +}); + +function animate() { + requestAnimationFrame(animate); + + // Rotate based on scroll position + mesh.rotation.y = scrollY * 0.001; + + // Move camera through scene + camera.position.y = -(scrollY / window.innerHeight) * 10; + + renderer.render(scene, camera); +} +``` + +**Advanced scroll libraries:** +- ScrollTrigger (GSAP plugin) +- Locomotive Scroll +- Lenis smooth scroll + +### Performance Optimization in Production + +```javascript +// Level of Detail (LOD) +const lod = new THREE.LOD(); +lod.addLevel(highDetailMesh, 0); // Close up +lod.addLevel(mediumDetailMesh, 10); // Medium distance +lod.addLevel(lowDetailMesh, 50); // Far away +scene.add(lod); + +// Instanced meshes for many identical objects +const geometry = new THREE.BoxGeometry(); +const material = new THREE.MeshStandardMaterial(); +const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000); + +// Set transforms for each instance +const matrix = new THREE.Matrix4(); +for (let i = 0; i < 1000; i++) { + matrix.setPosition(Math.random() * 100, Math.random() * 100, Math.random() * 100); + instancedMesh.setMatrixAt(i, matrix); +} +``` + +### Modern Loading Patterns + +```javascript +// In production, load 3D models: +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; + +const loader = new GLTFLoader(); +loader.load('model.gltf', (gltf) => { + scene.add(gltf.scene); + + // Traverse and setup materials + gltf.scene.traverse((child) => { + if (child.isMesh) { + child.castShadow = true; + child.receiveShadow = true; + } + }); +}); +``` + +### When to Use What + +**CDN Approach (Current Skill):** +- Quick prototypes and demos +- Educational content +- Artifacts and embedded experiences +- No build step required + +**Production Build Approach:** +- Client projects and portfolios +- Complex applications +- Need latest features (r150+) +- Performance-critical applications +- Team collaboration with version control + +### Recommended Production Stack + +``` +Three.js (latest) + Vite/Webpack +├── GSAP (animations) +├── React Three Fiber (optional - React integration) +├── Drei (helper components) +├── Leva (debug GUI) +└── Post-processing effects +``` + +This skill provides CDN-compatible foundations. In production, you'd layer on these modern tools for professional results.