diff --git a/skills/threejs-animation/SKILL.md b/skills/threejs-animation/SKILL.md index 22812157..b61cc800 100644 --- a/skills/threejs-animation/SKILL.md +++ b/skills/threejs-animation/SKILL.md @@ -12,22 +12,23 @@ source: community ```javascript import * as THREE from "three"; -// Simple procedural animation -const clock = new THREE.Clock(); +// Simple procedural animation with Timer (recommended in r183) +const timer = new THREE.Timer(); -function animate() { - const delta = clock.getDelta(); - const elapsed = clock.getElapsedTime(); +renderer.setAnimationLoop(() => { + timer.update(); + const delta = timer.getDelta(); + const elapsed = timer.getElapsed(); mesh.rotation.y += delta; mesh.position.y = Math.sin(elapsed) * 0.5; - requestAnimationFrame(animate); renderer.render(scene, camera); -} -animate(); +}); ``` +**Note:** `THREE.Timer` is recommended over `THREE.Clock` as of r183. Timer pauses when the page is hidden and has a cleaner API. `THREE.Clock` still works but is considered legacy. + ## Animation System Overview Three.js animation system has three main components: @@ -118,6 +119,10 @@ track.setInterpolation(THREE.InterpolateSmooth); // Cubic spline track.setInterpolation(THREE.InterpolateDiscrete); // Step function ``` +### BezierInterpolant (r183) + +Three.js r183 adds `THREE.BezierInterpolant` for bezier curve interpolation in keyframe tracks, enabling smoother animation curves with tangent control. + ## AnimationMixer Plays animations on an object and its descendants. diff --git a/skills/threejs-fundamentals/SKILL.md b/skills/threejs-fundamentals/SKILL.md index 62cc4b8b..675238f3 100644 --- a/skills/threejs-fundamentals/SKILL.md +++ b/skills/threejs-fundamentals/SKILL.md @@ -416,7 +416,24 @@ function dispose() { } ``` -### Clock for Animation +### Timer and Clock for Animation + +**Timer (recommended in r183)** - pauses when tab is hidden, cleaner API: + +```javascript +const timer = new THREE.Timer(); + +renderer.setAnimationLoop(() => { + timer.update(); + const delta = timer.getDelta(); + const elapsed = timer.getElapsed(); + + mesh.rotation.y += delta * 0.5; + renderer.render(scene, camera); +}); +``` + +**Clock (legacy, still works):** ```javascript const clock = new THREE.Clock(); @@ -432,6 +449,17 @@ function animate() { } ``` +### Animation Loop + +Prefer `renderer.setAnimationLoop()` over manual `requestAnimationFrame`. It handles WebXR compatibility and is the standard Three.js pattern: + +```javascript +renderer.setAnimationLoop(() => { + controls.update(); + renderer.render(scene, camera); +}); +``` + ### Responsive Canvas ```javascript @@ -483,6 +511,21 @@ lod.addLevel(lowDetailMesh, 100); scene.add(lod); ``` +## WebGPU Renderer (r183) + +Three.js includes an experimental WebGPU renderer as an alternative to WebGL: + +```javascript +import { WebGPURenderer } from "three/addons/renderers/webgpu/WebGPURenderer.js"; + +const renderer = new WebGPURenderer({ antialias: true }); +await renderer.init(); +renderer.setSize(window.innerWidth, window.innerHeight); +document.body.appendChild(renderer.domElement); +``` + +WebGPU uses TSL (Three.js Shading Language) instead of GLSL. The WebGL renderer remains the default and is fully supported. + ## See Also - `threejs-geometry` - Geometry creation and manipulation diff --git a/skills/threejs-geometry/SKILL.md b/skills/threejs-geometry/SKILL.md index 00fa68cf..dc33f21b 100644 --- a/skills/threejs-geometry/SKILL.md +++ b/skills/threejs-geometry/SKILL.md @@ -543,6 +543,36 @@ new THREE.SphereGeometry(1, 16, 16); // Performance mode geometry.dispose(); ``` +## BatchedMesh (r183) + +`BatchedMesh` is a higher-level alternative to `InstancedMesh` that supports multiple geometries in a single draw call. As of r183, it supports **per-instance opacity** and **per-instance wireframe**. + +```javascript +const batchedMesh = new THREE.BatchedMesh(maxGeometryCount, maxVertexCount, maxIndexCount); +batchedMesh.sortObjects = true; // Enable depth sorting for transparency + +// Add different geometries +const boxId = batchedMesh.addGeometry(new THREE.BoxGeometry(1, 1, 1)); +const sphereId = batchedMesh.addGeometry(new THREE.SphereGeometry(0.5, 16, 16)); + +// Add instances of those geometries +const instance1 = batchedMesh.addInstance(boxId); +const instance2 = batchedMesh.addInstance(sphereId); + +// Set transforms +const matrix = new THREE.Matrix4(); +matrix.setPosition(2, 0, 0); +batchedMesh.setMatrixAt(instance1, matrix); + +// Per-instance opacity (r183) +batchedMesh.setOpacityAt(instance1, 0.5); + +// Per-instance visibility +batchedMesh.setVisibleAt(instance2, false); + +scene.add(batchedMesh); +``` + ## See Also - `threejs-fundamentals` - Scene setup and Object3D diff --git a/skills/threejs-interaction/SKILL.md b/skills/threejs-interaction/SKILL.md index c51b7fbd..fa9e6c14 100644 --- a/skills/threejs-interaction/SKILL.md +++ b/skills/threejs-interaction/SKILL.md @@ -189,6 +189,18 @@ function animate() { } ``` +#### OrbitControls Programmatic Methods (r183) + +```javascript +// Programmatic camera movement +controls.dolly(1.5); // Dolly in/out (zoom for perspective cameras) +controls.pan(deltaX, deltaY); // Pan the camera +controls.rotate(deltaAzimuth, deltaPolar); // Rotate around target + +// Cursor style (r183) +controls.cursorStyle = { orbit: "grab", pan: "move", dolly: "zoom-in" }; +``` + ### FlyControls ```javascript diff --git a/skills/threejs-lighting/SKILL.md b/skills/threejs-lighting/SKILL.md index 3469d94d..b9dd9dae 100644 --- a/skills/threejs-lighting/SKILL.md +++ b/skills/threejs-lighting/SKILL.md @@ -186,7 +186,7 @@ Rectangular area light. Great for soft, realistic lighting. import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js"; import { RectAreaLightUniformsLib } from "three/examples/jsm/lights/RectAreaLightUniformsLib.js"; -// Must initialize uniforms first +// Must initialize uniforms first (WebGL renderer only) RectAreaLightUniformsLib.init(); // RectAreaLight(color, intensity, width, height) @@ -199,7 +199,8 @@ scene.add(rectLight); const helper = new RectAreaLightHelper(rectLight); rectLight.add(helper); -// Note: Only works with MeshStandardMaterial and MeshPhysicalMaterial +// Works with MeshStandardMaterial, MeshPhysicalMaterial +// r183: Clearcoat on MeshPhysicalMaterial is now properly lit by RectAreaLight // Does not cast shadows natively ``` diff --git a/skills/threejs-loaders/SKILL.md b/skills/threejs-loaders/SKILL.md index fea39f2e..e7e2aa24 100644 --- a/skills/threejs-loaders/SKILL.md +++ b/skills/threejs-loaders/SKILL.md @@ -255,7 +255,7 @@ import { KTX2Loader } from "three/addons/loaders/KTX2Loader.js"; const ktx2Loader = new KTX2Loader(); ktx2Loader.setTranscoderPath( - "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/basis/", + "https://cdn.jsdelivr.net/npm/three@0.183.0/examples/jsm/libs/basis/", ); ktx2Loader.detectSupport(renderer); @@ -267,6 +267,22 @@ gltfLoader.load("model-with-ktx2.glb", (gltf) => { }); ``` +### GLTF with Meshopt Compression (r183) + +```javascript +import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; +import { MeshoptDecoder } from "three/addons/libs/meshopt_decoder.module.js"; + +const gltfLoader = new GLTFLoader(); +gltfLoader.setMeshoptDecoder(MeshoptDecoder); + +gltfLoader.load("compressed-model.glb", (gltf) => { + scene.add(gltf.scene); +}); +``` + +**KHR_meshopt_compression** is an alternative to Draco that often provides better compression for animated meshes and preserves mesh topology. + ### Process GLTF Content ```javascript @@ -618,6 +634,10 @@ loadModel("model.glb").then((gltf) => { }); ``` +## VRMLLoader Camera Support (r183) + +As of r183, `VRMLLoader` supports loading cameras defined in VRML files. + ## See Also - `threejs-textures` - Texture configuration diff --git a/skills/threejs-materials/SKILL.md b/skills/threejs-materials/SKILL.md index 8c570a7a..60dfd02b 100644 --- a/skills/threejs-materials/SKILL.md +++ b/skills/threejs-materials/SKILL.md @@ -515,6 +515,28 @@ function getMaterial(color) { material.dispose(); ``` +## NodeMaterial / TSL (Future Direction) + +Three.js is moving toward **NodeMaterial** and **TSL (Three.js Shading Language)** as the standard material system, especially for the WebGPU renderer: + +```javascript +import { MeshStandardNodeMaterial } from "three/addons/nodes/Nodes.js"; +import { color, uv, texture } from "three/addons/nodes/Nodes.js"; + +const material = new MeshStandardNodeMaterial(); +material.colorNode = texture(colorMap, uv()); +``` + +**Key points:** +- NodeMaterial works with both WebGL and WebGPU renderers +- `onBeforeCompile` does **not** work with the WebGPU renderer -- use NodeMaterial instead +- TSL replaces GLSL for cross-renderer shader compatibility +- Standard GLSL `ShaderMaterial` continues to work with the WebGL renderer + +## Lambert/Phong IBL Support (r183) + +As of r183, `MeshLambertMaterial` and `MeshPhongMaterial` support image-based lighting (IBL) via `scene.environment`. Previously, only PBR materials (Standard/Physical) responded to environment maps set on the scene. + ## See Also - `threejs-textures` - Texture loading and configuration diff --git a/skills/threejs-postprocessing/SKILL.md b/skills/threejs-postprocessing/SKILL.md index db7f681e..7cb7e7c3 100644 --- a/skills/threejs-postprocessing/SKILL.md +++ b/skills/threejs-postprocessing/SKILL.md @@ -521,25 +521,46 @@ function animate() { } ``` -## WebGPU Post-Processing (Three.js r150+) +## WebGPU Post-Processing (Three.js r183) + +The WebGPU renderer uses a node-based `PostProcessing` class instead of `EffectComposer`. Note that `EffectComposer` is **WebGL-only**. ```javascript -import { postProcessing } from "three/addons/nodes/Nodes.js"; -import { pass, bloom, dof } from "three/addons/nodes/Nodes.js"; +import * as THREE from "three"; +import { pass, bloom, dof } from "three/tsl"; +import { WebGPURenderer } from "three/addons/renderers/webgpu/WebGPURenderer.js"; -// Using node-based system -const scenePass = pass(scene, camera); -const bloomNode = bloom(scenePass, 0.5, 0.4, 0.85); +const renderer = new WebGPURenderer({ antialias: true }); +await renderer.init(); +// Create post-processing const postProcessing = new THREE.PostProcessing(renderer); -postProcessing.outputNode = bloomNode; + +// Scene pass +const scenePass = pass(scene, camera); + +// Add bloom +const bloomPass = bloom(scenePass, 0.5, 0.4, 0.85); + +// Set output +postProcessing.outputNode = bloomPass; // Render -function animate() { +renderer.setAnimationLoop(() => { postProcessing.render(); -} +}); ``` +### Key Differences from EffectComposer + +| EffectComposer (WebGL) | PostProcessing (WebGPU) | +| ------------------------------- | -------------------------------- | +| `addPass(new RenderPass(...))` | `pass(scene, camera)` | +| `addPass(new UnrealBloomPass)` | `bloom(scenePass, ...)` | +| `composer.render()` | `postProcessing.render()` | +| Chain of passes | Node graph with `outputNode` | +| GLSL shader passes | TSL node-based effects | + ## Performance Tips 1. **Limit passes**: Each pass adds a full-screen render diff --git a/skills/threejs-shaders/SKILL.md b/skills/threejs-shaders/SKILL.md index 86cd478b..b6166c5b 100644 --- a/skills/threejs-shaders/SKILL.md +++ b/skills/threejs-shaders/SKILL.md @@ -637,6 +637,49 @@ if (value > 0.5) { color = mix(colorB, colorA, step(0.5, value)); ``` +## TSL (Three.js Shading Language) - Future Direction + +TSL is the new shader authoring system for Three.js, designed to work with both WebGL and WebGPU renderers. GLSL patterns above are **WebGL-only** and will not work with the WebGPU renderer. + +### TSL Quick Start + +```javascript +import { MeshStandardNodeMaterial } from "three/addons/nodes/Nodes.js"; +import { + uv, sin, timerLocal, vec4, color, positionLocal, normalLocal, + float, mul, add +} from "three/addons/nodes/Nodes.js"; + +const material = new MeshStandardNodeMaterial(); + +// Animated color based on UV and time +const time = timerLocal(); +material.colorNode = color(sin(add(uv().x, time)), uv().y, 0.5); + +// Vertex displacement +material.positionNode = add( + positionLocal, + mul(normalLocal, sin(add(positionLocal.x, time)).mul(0.1)) +); +``` + +### Key Differences from GLSL + +| GLSL (WebGL only) | TSL (WebGL + WebGPU) | +| ----------------------- | ---------------------------- | +| `ShaderMaterial` | `MeshStandardNodeMaterial` | +| String-based shaders | JavaScript node graph | +| `onBeforeCompile` | Node composition | +| Manual uniforms | `uniform()` node | +| `texture2D()` | `texture()` node | +| `gl_Position` | `positionNode` | +| `gl_FragColor` | `colorNode` / `outputNode` | + +### When to Use What + +- **GLSL ShaderMaterial**: Existing WebGL projects, maximum shader control, porting existing shaders +- **TSL NodeMaterial**: New projects, WebGPU support needed, cross-renderer compatibility + ## See Also - `threejs-materials` - Built-in material types diff --git a/skills/threejs-skills/SKILL.md b/skills/threejs-skills/SKILL.md index 62512648..e4aa320f 100644 --- a/skills/threejs-skills/SKILL.md +++ b/skills/threejs-skills/SKILL.md @@ -22,13 +22,29 @@ Systematically create high-quality 3D scenes and interactive experiences using T ### 1. Essential Three.js Imports -Always use the correct CDN version (r128): +Use ES module import maps for modern Three.js (r183+): -```javascript -import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"; +```html + + ``` -**CRITICAL**: Do NOT use example imports like `THREE.OrbitControls` - they won't work on the CDN. +For production with npm/vite/webpack: + +```javascript +import * as THREE from "three"; +import { OrbitControls } from "three/addons/controls/OrbitControls.js"; +``` ### 2. Scene Initialization @@ -55,16 +71,21 @@ document.body.appendChild(renderer.domElement); ### 3. Animation Loop -Use requestAnimationFrame for smooth rendering: +Use `renderer.setAnimationLoop()` (preferred) or `requestAnimationFrame`: ```javascript -function animate() { - requestAnimationFrame(animate); - - // Update object transformations here +// Preferred: setAnimationLoop (handles WebXR compatibility) +renderer.setAnimationLoop(() => { mesh.rotation.x += 0.01; mesh.rotation.y += 0.01; + renderer.render(scene, camera); +}); +// Alternative: manual requestAnimationFrame +function animate() { + requestAnimationFrame(animate); + mesh.rotation.x += 0.01; + mesh.rotation.y += 0.01; renderer.render(scene, camera); } animate(); @@ -93,13 +114,11 @@ Choose appropriate geometry types: - `PlaneGeometry` - flat surfaces, ground planes - `TorusGeometry` - donuts, rings -**IMPORTANT**: Do NOT use `CapsuleGeometry` (introduced in r142, not available in r128) +**CapsuleGeometry** is available (stable since r142): -**Alternatives for capsules:** - -- Combine `CylinderGeometry` + 2 `SphereGeometry` -- Use `SphereGeometry` with adjusted parameters -- Create custom geometry with vertices +```javascript +new THREE.CapsuleGeometry(0.5, 1, 4, 8); // radius, length, capSegments, radialSegments +``` ### 3. Apply Materials @@ -162,9 +181,26 @@ function animate() { } ``` -### Custom Camera Controls (OrbitControls Alternative) +### OrbitControls -Since `THREE.OrbitControls` isn't available on CDN, implement custom controls: +With import maps or build tools, OrbitControls works directly: + +```javascript +import { OrbitControls } from "three/addons/controls/OrbitControls.js"; + +const controls = new OrbitControls(camera, renderer.domElement); +controls.enableDamping = true; + +// Update in animation loop +renderer.setAnimationLoop(() => { + controls.update(); + renderer.render(scene, camera); +}); +``` + +### Custom Camera Controls (Alternative) + +For lightweight custom controls without importing OrbitControls: ```javascript let isDragging = false; @@ -338,18 +374,18 @@ const material = new THREE.MeshStandardMaterial({ ### Common Pitfalls to Avoid -- ❌ Using `THREE.OrbitControls` - not available on CDN -- ❌ Using `THREE.CapsuleGeometry` - requires r142+ +- ❌ Using `outputEncoding` instead of `outputColorSpace` (renamed in r152) - ❌ 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 +- ❌ Using `THREE.Clock` without considering `THREE.Timer` (recommended in r183) ## Example Workflow User: "Create an interactive 3D sphere that responds to mouse movement" -1. **Setup**: Import Three.js (r128), create scene/camera/renderer +1. **Setup**: Import Three.js, 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 @@ -449,7 +485,7 @@ const material = new THREE.MeshStandardMaterial({ // Improve color accuracy and HDR rendering renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.0; -renderer.outputEncoding = THREE.sRGBEncoding; +renderer.outputColorSpace = THREE.SRGBColorSpace; // Was outputEncoding in older versions // Makes colors more vibrant and realistic ``` @@ -474,7 +510,7 @@ 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. +Post-processing effects are available via import maps or build tools. See `threejs-postprocessing` skill for EffectComposer, bloom, DOF, and more. ### Group Objects @@ -490,36 +526,64 @@ scene.add(group); Three.js artifacts require systematic setup: -1. Import correct CDN version (r128) +1. Import Three.js via import maps or build tools 2. Initialize scene, camera, renderer 3. Create geometry + material = mesh 4. Add lighting if using lit materials -5. Implement animation loop +5. Implement animation loop (prefer `setAnimationLoop`) 6. Handle window resize -7. Avoid r128 incompatible features +7. Set `renderer.outputColorSpace = THREE.SRGBColorSpace` Follow these patterns for reliable, performant 3D experiences. -## Modern Three.js & Production Practices +## Modern Three.js Practices (r183) -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 +### Modular Imports ```javascript -// In production with npm/vite/webpack: +// 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"; +import { OrbitControls } from "three/addons/controls/OrbitControls.js"; +import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; +import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js"; ``` -**Benefits:** +### WebGPU Renderer (Alternative) -- Tree-shaking (smaller bundle sizes) -- Access to full example library (OrbitControls, loaders, etc.) -- Latest Three.js features (r150+) -- TypeScript support +Three.js r183 includes a WebGPU renderer as an alternative to WebGL: + +```javascript +import { WebGPURenderer } from "three/addons/renderers/webgpu/WebGPURenderer.js"; + +const renderer = new WebGPURenderer({ antialias: true }); +await renderer.init(); +renderer.setSize(window.innerWidth, window.innerHeight); +``` + +WebGPU uses TSL (Three.js Shading Language) instead of GLSL for custom shaders. See `threejs-shaders` for details. + +### Timer (r183 Recommended) + +`THREE.Timer` is recommended over `THREE.Clock` as of r183: + +```javascript +const timer = new THREE.Timer(); + +renderer.setAnimationLoop(() => { + timer.update(); + const delta = timer.getDelta(); + const elapsed = timer.getElapsed(); + + mesh.rotation.y += delta; + renderer.render(scene, camera); +}); +``` + +**Benefits over Clock:** + +- Not affected by page visibility (pauses when tab is hidden) +- Cleaner API design +- Better integration with `setAnimationLoop` ### Animation Libraries (GSAP Integration) @@ -625,7 +689,7 @@ loader.load("model.gltf", (gltf) => { ### When to Use What -**CDN Approach (Current Skill):** +**Import Map Approach:** - Quick prototypes and demos - Educational content @@ -636,19 +700,16 @@ loader.load("model.gltf", (gltf) => { - 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 +Three.js r183 + Vite ├── 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. diff --git a/skills/threejs-textures/SKILL.md b/skills/threejs-textures/SKILL.md index 5b386e39..4cac7851 100644 --- a/skills/threejs-textures/SKILL.md +++ b/skills/threejs-textures/SKILL.md @@ -623,6 +623,14 @@ const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent); const textureSize = isMobile ? 1024 : 2048; ``` +## KTX2Loader BC3 Alpha Fix (r183) + +As of r183, `KTX2Loader` correctly handles BC3 compressed textures with alpha channels, fixing previously incorrect alpha rendering. + +## ISO 21496-1 Gainmap Metadata (r183) + +Three.js r183 supports ISO 21496-1 gainmap metadata in HDR textures, enabling proper tone mapping of gainmap-based HDR images (such as those produced by recent smartphone cameras). + ## See Also - `threejs-materials` - Applying textures to materials