| name | threejs-skills |
| 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. |
| category | Document Processing |
| source | antigravity |
| tags | ["javascript","typescript","react","ai","workflow","design","document","aws","rag","cro"] |
| url | https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/threejs-skills |
Three.js Skills
Systematically create high-quality 3D scenes and interactive experiences using Three.js best practices.
When to Use
- 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
Core Setup Pattern
1. Essential Three.js Imports
Always use the correct CDN version (r128):
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:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000,
);
camera.position.z = 5;
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:
function animate() {
requestAnimationFrame(animate);
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
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:
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
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:
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
Common Patterns
Rotating Object
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:
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;
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 };
});
renderer.domElement.addEventListener("wheel", (event) => {
event.();
camera.. += event. * ;
camera.. = .(, .(, cam