threejs-fundamentals by cloudai-x/threejs-skills
npx skills add https://github.com/cloudai-x/threejs-skills --skill threejs-fundamentalsimport * as THREE from "three";
// 创建场景、相机、渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000,
);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
// 添加一个网格
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 添加光源
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 5, 5);
scene.add(dirLight);
camera.position.z = 5;
// 动画循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
// 处理窗口大小变化
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
所有 3D 对象、光源和相机的容器。
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000); // 纯色背景
scene.background = texture; // 天空盒纹理
scene.background = cubeTexture; // 立方体贴图
scene.environment = envMap; // 用于 PBR 的环境贴图
scene.fog = new THREE.Fog(0xffffff, 1, 100); // 线性雾
scene.fog = new THREE.FogExp2(0xffffff, 0.02); // 指数雾
PerspectiveCamera - 最常用,模拟人眼视角。
// PerspectiveCamera(fov, aspect, near, far)
const camera = new THREE.PerspectiveCamera(
75, // 视野角度(度)
window.innerWidth / window.innerHeight, // 宽高比
0.1, // 近裁剪平面
1000, // 远裁剪平面
);
camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);
camera.updateProjectionMatrix(); // 更改 fov、aspect、near、far 后调用
OrthographicCamera - 无透视变形,适用于 2D/等轴测视图。
// OrthographicCamera(left, right, top, bottom, near, far)
const aspect = window.innerWidth / window.innerHeight;
const frustumSize = 10;
const camera = new THREE.OrthographicCamera(
(frustumSize * aspect) / -2,
(frustumSize * aspect) / 2,
frustumSize / 2,
frustumSize / -2,
0.1,
1000,
);
ArrayCamera - 使用子相机实现多个视口。
const cameras = [];
for (let i = 0; i < 4; i++) {
const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
subcamera.viewport = new THREE.Vector4(
Math.floor(i % 2) * 0.5,
Math.floor(i / 2) * 0.5,
0.5,
0.5,
);
cameras.push(subcamera);
}
const arrayCamera = new THREE.ArrayCamera(cameras);
CubeCamera - 渲染用于反射的环境贴图。
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
scene.add(cubeCamera);
// 用于反射
material.envMap = cubeRenderTarget.texture;
// 每帧更新(开销大!)
cubeCamera.position.copy(reflectiveMesh.position);
cubeCamera.update(renderer, scene);
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#canvas"), // 可选的现有画布
antialias: true, // 平滑边缘
alpha: true, // 透明背景
powerPreference: "high-performance", // GPU 性能提示
preserveDrawingBuffer: true, // 用于截图
});
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
// 色调映射
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
// 色彩空间 (Three.js r152+)
renderer.outputColorSpace = THREE.SRGBColorSpace;
// 阴影
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 清除颜色
renderer.setClearColor(0x000000, 1);
// 渲染
renderer.render(scene, camera);
所有 3D 对象的基类。Mesh、Group、Light、Camera 都继承自 Object3D。
const obj = new THREE.Object3D();
// 变换
obj.position.set(x, y, z);
obj.rotation.set(x, y, z); // 欧拉角(弧度)
obj.quaternion.set(x, y, z, w); // 四元数旋转
obj.scale.set(x, y, z);
// 局部与世界变换
obj.getWorldPosition(targetVector);
obj.getWorldQuaternion(targetQuaternion);
obj.getWorldDirection(targetVector);
// 层级结构
obj.add(child);
obj.remove(child);
obj.parent;
obj.children;
// 可见性
obj.visible = false;
// 图层(用于选择性渲染/光线投射)
obj.layers.set(1);
obj.layers.enable(2);
obj.layers.disable(0);
// 遍历层级结构
obj.traverse((child) => {
if (child.isMesh) child.material.color.set(0xff0000);
});
// 矩阵更新
obj.matrixAutoUpdate = true; // 默认:自动更新矩阵
obj.updateMatrix(); // 手动更新矩阵
obj.updateMatrixWorld(true); // 递归更新世界矩阵
用于组织对象的空容器。
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
scene.add(group);
// 变换整个组
group.position.x = 5;
group.rotation.y = Math.PI / 4;
结合几何体和材质。
const mesh = new THREE.Mesh(geometry, material);
// 多个材质(每个几何体组对应一个)
const mesh = new THREE.Mesh(geometry, [material1, material2]);
// 有用的属性
mesh.geometry;
mesh.material;
mesh.castShadow = true;
mesh.receiveShadow = true;
// 视锥体裁剪
mesh.frustumCulled = true; // 默认:如果超出相机视野则跳过渲染
// 渲染顺序
mesh.renderOrder = 10; // 数值越大,渲染越晚
Three.js 使用 右手坐标系 :
+X 指向右侧
+Y 指向上方
+Z 指向观察者(屏幕外)
// 坐标轴辅助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 红色=X,绿色=Y,蓝色=Z
const v = new THREE.Vector3(x, y, z);
v.set(x, y, z);
v.copy(otherVector);
v.clone();
// 运算(原地修改)
v.add(v2);
v.sub(v2);
v.multiply(v2);
v.multiplyScalar(2);
v.divideScalar(2);
v.normalize();
v.negate();
v.clamp(min, max);
v.lerp(target, alpha);
// 计算(返回新值)
v.length();
v.lengthSq(); // 比 length() 更快
v.distanceTo(v2);
v.dot(v2);
v.cross(v2); // 修改 v
v.angleTo(v2);
// 变换
v.applyMatrix4(matrix);
v.applyQuaternion(q);
v.project(camera); // 世界坐标到 NDC
v.unproject(camera); // NDC 到世界坐标
const m = new THREE.Matrix4();
m.identity();
m.copy(other);
m.clone();
// 构建变换矩阵
m.makeTranslation(x, y, z);
m.makeRotationX(theta);
m.makeRotationY(theta);
m.makeRotationZ(theta);
m.makeRotationFromQuaternion(q);
m.makeScale(x, y, z);
// 组合/分解
m.compose(position, quaternion, scale);
m.decompose(position, quaternion, scale);
// 运算
m.multiply(m2); // m = m * m2
m.premultiply(m2); // m = m2 * m
m.invert();
m.transpose();
// 相机矩阵
m.makePerspective(left, right, top, bottom, near, far);
m.makeOrthographic(left, right, top, bottom, near, far);
m.lookAt(eye, target, up);
const q = new THREE.Quaternion();
q.setFromEuler(euler);
q.setFromAxisAngle(axis, angle);
q.setFromRotationMatrix(matrix);
q.multiply(q2);
q.slerp(target, t); // 球面线性插值
q.normalize();
q.invert();
const euler = new THREE.Euler(x, y, z, "XYZ"); // 旋转顺序很重要!
euler.setFromQuaternion(q);
euler.setFromRotationMatrix(m);
// 旋转顺序:'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'
const color = new THREE.Color(0xff0000);
const color = new THREE.Color("red");
const color = new THREE.Color("rgb(255, 0, 0)");
const color = new THREE.Color("#ff0000");
color.setHex(0x00ff00);
color.setRGB(r, g, b); // 范围 0-1
color.setHSL(h, s, l); // 范围 0-1
color.lerp(otherColor, alpha);
color.multiply(otherColor);
color.multiplyScalar(2);
THREE.MathUtils.clamp(value, min, max);
THREE.MathUtils.lerp(start, end, alpha);
THREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);
THREE.MathUtils.degToRad(degrees);
THREE.MathUtils.radToDeg(radians);
THREE.MathUtils.randFloat(min, max);
THREE.MathUtils.randInt(min, max);
THREE.MathUtils.smoothstep(x, min, max);
THREE.MathUtils.smootherstep(x, min, max);
function dispose() {
// 清理几何体
mesh.geometry.dispose();
// 清理材质
if (Array.isArray(mesh.material)) {
mesh.material.forEach((m) => m.dispose());
} else {
mesh.material.dispose();
}
// 清理纹理
texture.dispose();
// 从场景中移除
scene.remove(mesh);
// 清理渲染器
renderer.dispose();
}
const clock = new THREE.Clock();
function animate() {
const delta = clock.getDelta(); // 距离上一帧的时间(秒)
const elapsed = clock.getElapsedTime(); // 总时间(秒)
mesh.rotation.y += delta * 0.5; // 与帧率无关的恒定速度
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onWindowResize() {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}
window.addEventListener("resize", onWindowResize);
const manager = new THREE.LoadingManager();
manager.onStart = (url, loaded, total) => console.log("开始加载");
manager.onLoad = () => console.log("全部加载完成");
manager.onProgress = (url, loaded, total) => console.log(`${loaded}/${total}`);
manager.onError = (url) => console.error(`加载 ${url} 时出错`);
const textureLoader = new THREE.TextureLoader(manager);
const gltfLoader = new GLTFLoader(manager);
THREE.LOD 进行基于距离的网格切换getWorldPosition:缓存结果// 合并静态几何体
import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
const merged = mergeGeometries([geo1, geo2, geo3]);
// LOD
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 0);
lod.addLevel(medDetailMesh, 50);
lod.addLevel(lowDetailMesh, 100);
scene.add(lod);
threejs-geometry - 几何体创建与操作threejs-materials - 材质类型与属性threejs-lighting - 光源类型与阴影每周安装量
1.9K
代码仓库
GitHub 星标数
1.8K
首次出现
2026年1月20日
安全审计
安装于
opencode1.5K
gemini-cli1.4K
codex1.3K
claude-code1.3K
cursor1.2K
github-copilot1.2K
import * as THREE from "three";
// Create scene, camera, renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000,
);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
// Add a mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// Add light
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 5, 5);
scene.add(dirLight);
camera.position.z = 5;
// Animation loop
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
// Handle resize
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
Container for all 3D objects, lights, and cameras.
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000); // Solid color
scene.background = texture; // Skybox texture
scene.background = cubeTexture; // Cubemap
scene.environment = envMap; // Environment map for PBR
scene.fog = new THREE.Fog(0xffffff, 1, 100); // Linear fog
scene.fog = new THREE.FogExp2(0xffffff, 0.02); // Exponential fog
PerspectiveCamera - Most common, simulates human eye.
// PerspectiveCamera(fov, aspect, near, far)
const camera = new THREE.PerspectiveCamera(
75, // Field of view (degrees)
window.innerWidth / window.innerHeight, // Aspect ratio
0.1, // Near clipping plane
1000, // Far clipping plane
);
camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);
camera.updateProjectionMatrix(); // Call after changing fov, aspect, near, far
OrthographicCamera - No perspective distortion, good for 2D/isometric.
// OrthographicCamera(left, right, top, bottom, near, far)
const aspect = window.innerWidth / window.innerHeight;
const frustumSize = 10;
const camera = new THREE.OrthographicCamera(
(frustumSize * aspect) / -2,
(frustumSize * aspect) / 2,
frustumSize / 2,
frustumSize / -2,
0.1,
1000,
);
ArrayCamera - Multiple viewports with sub-cameras.
const cameras = [];
for (let i = 0; i < 4; i++) {
const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
subcamera.viewport = new THREE.Vector4(
Math.floor(i % 2) * 0.5,
Math.floor(i / 2) * 0.5,
0.5,
0.5,
);
cameras.push(subcamera);
}
const arrayCamera = new THREE.ArrayCamera(cameras);
CubeCamera - Renders environment maps for reflections.
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
scene.add(cubeCamera);
// Use for reflections
material.envMap = cubeRenderTarget.texture;
// Update each frame (expensive!)
cubeCamera.position.copy(reflectiveMesh.position);
cubeCamera.update(renderer, scene);
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#canvas"), // Optional existing canvas
antialias: true, // Smooth edges
alpha: true, // Transparent background
powerPreference: "high-performance", // GPU hint
preserveDrawingBuffer: true, // For screenshots
});
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
// Tone mapping
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
// Color space (Three.js r152+)
renderer.outputColorSpace = THREE.SRGBColorSpace;
// Shadows
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Clear color
renderer.setClearColor(0x000000, 1);
// Render
renderer.render(scene, camera);
Base class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.
const obj = new THREE.Object3D();
// Transform
obj.position.set(x, y, z);
obj.rotation.set(x, y, z); // Euler angles (radians)
obj.quaternion.set(x, y, z, w); // Quaternion rotation
obj.scale.set(x, y, z);
// Local vs World transforms
obj.getWorldPosition(targetVector);
obj.getWorldQuaternion(targetQuaternion);
obj.getWorldDirection(targetVector);
// Hierarchy
obj.add(child);
obj.remove(child);
obj.parent;
obj.children;
// Visibility
obj.visible = false;
// Layers (for selective rendering/raycasting)
obj.layers.set(1);
obj.layers.enable(2);
obj.layers.disable(0);
// Traverse hierarchy
obj.traverse((child) => {
if (child.isMesh) child.material.color.set(0xff0000);
});
// Matrix updates
obj.matrixAutoUpdate = true; // Default: auto-update matrices
obj.updateMatrix(); // Manual matrix update
obj.updateMatrixWorld(true); // Update world matrix recursively
Empty container for organizing objects.
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
scene.add(group);
// Transform entire group
group.position.x = 5;
group.rotation.y = Math.PI / 4;
Combines geometry and material.
const mesh = new THREE.Mesh(geometry, material);
// Multiple materials (one per geometry group)
const mesh = new THREE.Mesh(geometry, [material1, material2]);
// Useful properties
mesh.geometry;
mesh.material;
mesh.castShadow = true;
mesh.receiveShadow = true;
// Frustum culling
mesh.frustumCulled = true; // Default: skip if outside camera view
// Render order
mesh.renderOrder = 10; // Higher = rendered later
Three.js uses a right-handed coordinate system :
+X points right
+Y points up
+Z points toward viewer (out of screen)
// Axes helper const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // Red=X, Green=Y, Blue=Z
const v = new THREE.Vector3(x, y, z);
v.set(x, y, z);
v.copy(otherVector);
v.clone();
// Operations (modify in place)
v.add(v2);
v.sub(v2);
v.multiply(v2);
v.multiplyScalar(2);
v.divideScalar(2);
v.normalize();
v.negate();
v.clamp(min, max);
v.lerp(target, alpha);
// Calculations (return new value)
v.length();
v.lengthSq(); // Faster than length()
v.distanceTo(v2);
v.dot(v2);
v.cross(v2); // Modifies v
v.angleTo(v2);
// Transform
v.applyMatrix4(matrix);
v.applyQuaternion(q);
v.project(camera); // World to NDC
v.unproject(camera); // NDC to world
const m = new THREE.Matrix4();
m.identity();
m.copy(other);
m.clone();
// Build transforms
m.makeTranslation(x, y, z);
m.makeRotationX(theta);
m.makeRotationY(theta);
m.makeRotationZ(theta);
m.makeRotationFromQuaternion(q);
m.makeScale(x, y, z);
// Compose/decompose
m.compose(position, quaternion, scale);
m.decompose(position, quaternion, scale);
// Operations
m.multiply(m2); // m = m * m2
m.premultiply(m2); // m = m2 * m
m.invert();
m.transpose();
// Camera matrices
m.makePerspective(left, right, top, bottom, near, far);
m.makeOrthographic(left, right, top, bottom, near, far);
m.lookAt(eye, target, up);
const q = new THREE.Quaternion();
q.setFromEuler(euler);
q.setFromAxisAngle(axis, angle);
q.setFromRotationMatrix(matrix);
q.multiply(q2);
q.slerp(target, t); // Spherical interpolation
q.normalize();
q.invert();
const euler = new THREE.Euler(x, y, z, "XYZ"); // Order matters!
euler.setFromQuaternion(q);
euler.setFromRotationMatrix(m);
// Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'
const color = new THREE.Color(0xff0000);
const color = new THREE.Color("red");
const color = new THREE.Color("rgb(255, 0, 0)");
const color = new THREE.Color("#ff0000");
color.setHex(0x00ff00);
color.setRGB(r, g, b); // 0-1 range
color.setHSL(h, s, l); // 0-1 range
color.lerp(otherColor, alpha);
color.multiply(otherColor);
color.multiplyScalar(2);
THREE.MathUtils.clamp(value, min, max);
THREE.MathUtils.lerp(start, end, alpha);
THREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);
THREE.MathUtils.degToRad(degrees);
THREE.MathUtils.radToDeg(radians);
THREE.MathUtils.randFloat(min, max);
THREE.MathUtils.randInt(min, max);
THREE.MathUtils.smoothstep(x, min, max);
THREE.MathUtils.smootherstep(x, min, max);
function dispose() {
// Dispose geometries
mesh.geometry.dispose();
// Dispose materials
if (Array.isArray(mesh.material)) {
mesh.material.forEach((m) => m.dispose());
} else {
mesh.material.dispose();
}
// Dispose textures
texture.dispose();
// Remove from scene
scene.remove(mesh);
// Dispose renderer
renderer.dispose();
}
const clock = new THREE.Clock();
function animate() {
const delta = clock.getDelta(); // Time since last frame (seconds)
const elapsed = clock.getElapsedTime(); // Total time (seconds)
mesh.rotation.y += delta * 0.5; // Consistent speed regardless of framerate
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onWindowResize() {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}
window.addEventListener("resize", onWindowResize);
const manager = new THREE.LoadingManager();
manager.onStart = (url, loaded, total) => console.log("Started loading");
manager.onLoad = () => console.log("All loaded");
manager.onProgress = (url, loaded, total) => console.log(`${loaded}/${total}`);
manager.onError = (url) => console.error(`Error loading ${url}`);
const textureLoader = new THREE.TextureLoader(manager);
const gltfLoader = new GLTFLoader(manager);
THREE.LOD for distance-based mesh switchinggetWorldPosition in loops: Cache results// Merge static geometries
import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
const merged = mergeGeometries([geo1, geo2, geo3]);
// LOD
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 0);
lod.addLevel(medDetailMesh, 50);
lod.addLevel(lowDetailMesh, 100);
scene.add(lod);
threejs-geometry - Geometry creation and manipulationthreejs-materials - Material types and propertiesthreejs-lighting - Light types and shadowsWeekly Installs
1.9K
Repository
GitHub Stars
1.8K
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode1.5K
gemini-cli1.4K
codex1.3K
claude-code1.3K
cursor1.2K
github-copilot1.2K
99,500 周安装