threejs-skills by sickn33/antigravity-awesome-skills
npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill threejs-skills使用 Three.js 最佳实践,系统性地创建高质量 3D 场景和交互体验。
始终使用正确的 CDN 版本 (r128):
import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js";
关键:不要使用像 THREE.OrbitControls 这样的示例导入——它们在 CDN 上无法工作。
每个 Three.js 项目都需要这些核心组件:
// 场景 - 包含所有 3D 对象
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);
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用 requestAnimationFrame 实现平滑渲染:
function animate() {
requestAnimationFrame(animate);
// 在此处更新对象变换
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
首先确定:
选择合适的几何体类型:
基本形状:
BoxGeometry - 立方体、长方体SphereGeometry - 球体、行星CylinderGeometry - 圆柱体、管道PlaneGeometry - 平面、地面TorusGeometry - 甜甜圈、圆环重要:不要使用 CapsuleGeometry(在 r142 中引入,r128 中不可用)
胶囊体的替代方案:
CylinderGeometry + 2 个 SphereGeometrySphereGeometry根据视觉需求选择材质:
常用材质:
MeshBasicMaterial - 无光照、纯色(无需灯光)
MeshStandardMaterial - 基于物理、真实感(需要灯光)
MeshPhongMaterial - 具有镜面高光的闪亮表面
MeshLambertMaterial - 哑光表面、漫反射
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00, metalness: 0.5, roughness: 0.5, });
如果使用光照材质(Standard、Phong、Lambert),请添加灯光:
// 环境光 - 整体照明
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);
如果使用 MeshBasicMaterial,可以跳过光照——它本身设计为无光照。
始终添加窗口大小调整处理:
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
由于 CDN 上没有 THREE.OrbitControls,请实现自定义控制:
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.preventDefault();
camera.position.z += event.deltaY * 0.01;
camera.position.z = Math.max(2, Math.min(20, camera.position.z)); // 限制范围
});
检测鼠标在 3D 对象上的点击和悬停:
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const clickableObjects = []; // 可点击网格的数组
// 更新鼠标位置
window.addEventListener("mousemove", (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});
// 检测点击
window.addEventListener("click", () => {
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(clickableObjects);
if (intersects.length > 0) {
const clickedObject = intersects[0].object;
// 处理点击 - 改变颜色、缩放等
clickedObject.material.color.set(0xff0000);
}
});
// 动画循环中的悬停效果
function animate() {
requestAnimationFrame(animate);
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(clickableObjects);
// 重置所有对象
clickableObjects.forEach((obj) => {
obj.scale.set(1, 1, 1);
});
// 高亮悬停的对象
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);
}
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);
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);
}
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("texture-url.jpg");
const material = new THREE.MeshStandardMaterial({
map: texture,
});
重用几何体和材质,当创建多个相似对象时
使用 BufferGeometry 处理自定义形状(更高效)
限制粒子数量以保持 60fps(从 1000-5000 开始)
释放资源,当移除对象时:
geometry.dispose();
material.dispose();
texture.dispose();
antialias: true 以获得平滑边缘THREE.OrbitControls - CDN 上不可用THREE.CapsuleGeometry - 需要 r142+scene.add() 将对象添加到场景renderer.render()用户:"创建一个响应鼠标移动的交互式 3D 球体"
SphereGeometry(1, 32, 32) 以获得平滑球体MeshStandardMaterial 以获得真实感外观黑屏 / 无渲染:
性能差:
对象不可见:
阴影:
// 在渲染器上启用阴影
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 柔和阴影
// 投射阴影的光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
// 配置阴影质量
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 50;
scene.add(directionalLight);
// 对象投射和接收阴影
mesh.castShadow = true;
mesh.receiveShadow = true;
// 地面平面接收阴影
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);
环境贴图和反射:
// 从立方体贴图创建环境贴图
const loader = new THREE.CubeTextureLoader();
const envMap = loader.load([
"px.jpg",
"nx.jpg", // 正 x,负 x
"py.jpg",
"ny.jpg", // 正 y,负 y
"pz.jpg",
"nz.jpg", // 正 z,负 z
]);
scene.environment = envMap; // 影响所有 PBR 材质
scene.background = envMap; // 可选:用作天空盒
// 或应用于特定材质
const material = new THREE.MeshStandardMaterial({
metalness: 1.0,
roughness: 0.1,
envMap: envMap,
});
色调映射和输出编码:
// 提高色彩准确性和 HDR 渲染
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
renderer.outputEncoding = THREE.sRGBEncoding;
// 使颜色更鲜艳、更真实
用于深度的雾效:
// 线性雾
scene.fog = new THREE.Fog(0xcccccc, 10, 50); // 颜色,近处,远处
// 或指数雾(更真实)
scene.fog = new THREE.FogExp2(0xcccccc, 0.02); // 颜色,密度
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));
虽然 r128 CDN 可能无法使用高级后期处理,但可以通过着色器和渲染目标实现基本效果。
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
group.rotation.y = Math.PI / 4;
scene.add(group);
Three.js 项目需要系统性设置:
遵循这些模式以获得可靠、高性能的 3D 体验。
虽然本技能侧重于基于 CDN 的 Three.js (r128) 以确保项目兼容性,但以下是你在生产环境中会做的事情:
// 在生产环境中使用 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 gsap from "gsap";
// 替代手动动画循环:
gsap.to(mesh.position, {
x: 5,
duration: 2,
ease: "power2.inOut",
});
// 复杂序列:
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");
为什么使用 GSAP:
// 将 3D 动画与页面滚动同步
let scrollY = window.scrollY;
window.addEventListener("scroll", () => {
scrollY = window.scrollY;
});
function animate() {
requestAnimationFrame(animate);
// 基于滚动位置旋转
mesh.rotation.y = scrollY * 0.001;
// 在场景中移动相机
camera.position.y = -(scrollY / window.innerHeight) * 10;
renderer.render(scene, camera);
}
高级滚动库:
// 细节层次 (LOD)
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 0); // 近距离
lod.addLevel(mediumDetailMesh, 10); // 中距离
lod.addLevel(lowDetailMesh, 50); // 远距离
scene.add(lod);
// 用于许多相同对象的实例化网格
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial();
const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000);
// 为每个实例设置变换
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);
}
// 在生产环境中,加载 3D 模型:
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
const loader = new GLTFLoader();
loader.load("model.gltf", (gltf) => {
scene.add(gltf.scene);
// 遍历并设置材质
gltf.scene.traverse((child) => {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
});
CDN 方法(当前技能):
生产构建方法:
Three.js (最新版) + Vite/Webpack
├── GSAP (动画)
├── React Three Fiber (可选 - React 集成)
├── Drei (辅助组件)
├── Leva (调试 GUI)
└── 后期处理效果
本技能提供了与 CDN 兼容的基础。在生产环境中,你将叠加这些现代工具以获得专业效果。
每周安装量
203
仓库
GitHub 星标数
27.1K
首次出现
2026 年 1 月 30 日
安全审计
安装于
opencode184
gemini-cli182
codex181
github-copilot180
kimi-cli178
amp174
Systematically create high-quality 3D scenes and interactive experiences using Three.js best practices.
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.
Every Three.js artifact needs these core components:
// 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);
Use requestAnimationFrame for smooth rendering:
function animate() {
requestAnimationFrame(animate);
// Update object transformations here
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
Start by identifying:
Choose appropriate geometry types:
Basic Shapes:
BoxGeometry - cubes, rectangular prismsSphereGeometry - spheres, planetsCylinderGeometry - cylinders, tubesPlaneGeometry - flat surfaces, ground planesTorusGeometry - donuts, ringsIMPORTANT : Do NOT use CapsuleGeometry (introduced in r142, not available in r128)
Alternatives for capsules:
CylinderGeometry + 2 SphereGeometrySphereGeometry with adjusted parametersChoose 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, });
If using lit materials (Standard, Phong, Lambert), add lights:
// 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.
Always add window resize handling:
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
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;
// 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
});
Detect mouse clicks and hovers on 3D objects:
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);
}
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);
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);
}
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("texture-url.jpg");
const material = new THREE.MeshStandardMaterial({
map: texture,
});
Reuse geometries and materials when creating multiple similar objects
UseBufferGeometry for custom shapes (more efficient)
Limit particle counts to maintain 60fps (start with 1000-5000)
Dispose of resources when removing objects:
geometry.dispose();
material.dispose();
texture.dispose();
antialias: true on renderer for smooth edgesTHREE.OrbitControls - not available on CDNTHREE.CapsuleGeometry - requires r142+scene.add()renderer.render() in animation loopUser: "Create an interactive 3D sphere that responds to mouse movement"
SphereGeometry(1, 32, 32) for smooth sphereMeshStandardMaterial for realistic lookBlack screen / Nothing renders:
Poor performance:
Objects not visible:
Shadows:
// 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:
// 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:
// 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:
// 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
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));
While advanced post-processing may not be available in r128 CDN, basic effects can be achieved with shaders and render targets.
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
group.rotation.y = Math.PI / 4;
scene.add(group);
Three.js artifacts require systematic setup:
Follow these patterns for reliable, performant 3D experiences.
While this skill focuses on CDN-based Three.js (r128) for artifact compatibility, here's what you'd do in production environments:
// 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:
// 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:
// 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:
// 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);
}
// 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;
}
});
});
CDN Approach (Current Skill):
Production Build Approach:
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.
Weekly Installs
203
Repository
GitHub Stars
27.1K
First Seen
Jan 30, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode184
gemini-cli182
codex181
github-copilot180
kimi-cli178
amp174
Genkit JS 开发指南:AI 应用构建、错误排查与最佳实践
6,100 周安装