普通视图

发现新文章,点击刷新页面。
昨天 — 2026年1月15日首页

Three.js 材质进阶

2026年1月15日 14:47

概述

本文档将介绍Three.js中材质的进阶用法,包括各种高级材质类型、材质属性设置、环境贴图、透明效果等重要概念。通过这些知识点,您将能够创建更加真实和富有表现力的3D场景。

第一部分:MatCap材质

1. MatCap材质的概念

MatCap(Material Capture)材质是一种特殊的材质类型,它预先渲染了材质的光照效果到一张纹理上,因此具有很高的性能效率。MatCap材质非常适合用于实时渲染中需要高质量光照效果但又不想消耗过多性能的场景。

2. 基本使用方法

// 加载MatCap纹理
let matcapTexture = new THREE.TextureLoader().load(
  "./texture/matcaps/54584E_B1BAC5_818B91_A7ACA3-512px.png"
);

// 创建MatCap材质
let material = new THREE.MeshMatcapMaterial({
  matcap: matcapTexture,
  map: preMaterial.map,  // 可以同时使用其他纹理
});

// 应用到网格对象
duckMesh.material = material;

3. MatCap材质的优势

  • 性能优异:无需实时计算光照
  • 效果逼真:预渲染的光照效果非常真实
  • 使用简单:只需要一张纹理即可实现复杂的光照效果

第二部分:Lambert和Phong材质

1. Lambert材质

Lambert材质是一种漫反射材质,它模拟的是理想漫反射表面,适用于不光滑的表面。

let planeMaterial = new THREE.MeshLambertMaterial({
  map: colorTexture,           // 颜色贴图
  specularMap: specularTexture, // 高光贴图
  transparent: true,           // 透明度
  normalMap: normalTexture,    // 法线贴图
  bumpMap: dispTexture,        // 凹凸贴图
  displacementMap: dispTexture, // 位移贴图
  displacementScale: 0.02,     // 位移缩放
  aoMap: aoTexture,            // 环境光遮蔽贴图
});

2. Phong材质

Phong材质是一种更高级的材质,它可以计算镜面高光,适用于光滑表面。

let planeMaterial = new THREE.MeshPhongMaterial({
  map: colorTexture,
  specularMap: specularTexture,
  transparent: true,
  normalMap: normalTexture,
  bumpMap: dispTexture,
  displacementMap: dispTexture,
  displacementScale: 0.02,
  aoMap: aoTexture,
});

3. 两者的区别

  • Lambert材质:只计算漫反射,没有镜面高光
  • Phong材质:计算漫反射和镜面高光,更适合光滑表面

第三部分:Phong材质制作玻璃和水晶效果

1. 玻璃效果的实现

// 使用折射环境贴图
envMap.mapping = THREE.EquirectangularRefractionMapping;

duckMesh.material = new THREE.MeshPhongMaterial({
  map: preMaterial.map,
  refractionRatio: 0.7,   // 折射率
  reflectivity: 0.99,     // 反射率
  envMap: envMap,         // 环境贴图
});

2. 参数调节

  • refractionRatio:控制折射程度,值越大折射越明显
  • reflectivity:控制反射强度,接近1.0时反射效果更强

第四部分:Standard材质详解

Standard材质(MeshStandardMaterial)是Three.js中最常用的PBR(基于物理的渲染)材质之一。

1. 基本属性

// Standard材质的主要属性
const material = new THREE.MeshStandardMaterial({
  color: 0xffffff,              // 基础颜色
  roughness: 0.5,               // 粗糙度 (0-1)
  metalness: 0.5,               // 金属度 (0-1)
  map: texture,                 // 颜色贴图
  normalMap: normalTexture,     // 法线贴图
  roughnessMap: roughnessTexture, // 粗糙度贴图
  metalnessMap: metalnessTexture, // 金属度贴图
  aoMap: aoTexture,             // 环境光遮蔽贴图
  envMap: envMap,               // 环境贴图
});

2. 动态控制材质属性

// 通过GUI动态控制材质属性
let params = {
  aoMap: true,
};

gui.add(params, "aoMap").onChange((value) => {
  mesh.material.aoMap = value ? aoMap : null;
  mesh.material.needsUpdate = true;  // 需要更新材质
});

第五部分:透光性、厚度、衰减颜色和衰减距离

1. 物理材质的透光效果

MeshPhysicalMaterial支持更高级的透光效果,可以模拟玻璃、钻石等材质。

const material = new THREE.MeshPhysicalMaterial({
  transparent: true,                    // 启用透明
  transmission: 0.95,                   // 透射率 (0-1)
  roughness: 0.05,                      // 粗糙度
  thickness: 2,                         // 厚度
  attenuationColor: new THREE.Color(0.9, 0.9, 0), // 衰减颜色
  attenuationDistance: 1,               // 衰减距离
  thicknessMap: thicknessMap,           // 厚度贴图
});

2. 参数说明

  • transmission:透射率,值越高越透明
  • thickness:厚度,影响光线穿过物体的方式
  • attenuationColor:光线在物体内部传播时的颜色变化
  • attenuationDistance:光线在物体内部传播的距离

3. 通过GUI调节参数

gui.add(material, "attenuationDistance", 0, 10).name("衰减距离");
gui.add(material, "thickness", 0, 2).name("厚度");

第六部分:折射率和反射率

1. 折射率(IOR)

折射率(Index of Refraction)决定了光线穿过材质时的弯曲程度。

const material = new THREE.MeshPhysicalMaterial({
  transparent: true,
  transmission: 0.95,
  roughness: 0.05,
  thickness: 2,
  attenuationColor: new THREE.Color(0.9, 0.9, 0),
  attenuationDistance: 1,
  ior: 1.5,                // 折射率
});

// 通过GUI调节折射率
gui.add(material, "ior", 0, 2).name("折射率");

2. 反射率

反射率控制材质表面的反射强度。

// 设置反射率
material.reflectivity = 0.9;

// 通过GUI调节反射率
gui.add(material, "reflectivity", 0, 1).name("反射率");

3. 常见材质的折射率参考

  • 空气:1.0
  • 水:1.33
  • 玻璃:1.5
  • 钻石:2.4

第七部分:清漆、清漆法向和清漆粗糙度

1. 清漆效果

清漆(Clearcoat)属性可以模拟材质表面的额外涂层,如汽车漆面或家具上的清漆层。

const material = new THREE.MeshPhysicalMaterial({
  transparent: true,
  color: 0xffff00,                  // 基础颜色
  roughness: 0.5,                   // 基础粗糙度
  clearcoat: 1,                     // 清漆强度 (0-1)
  clearcoatRoughness: 0,            // 清漆粗糙度 (0-1)
  clearcoatMap: thicknessMap,       // 清漆贴图
  clearcoatRoughnessMap: thicknessMap, // 清漆粗糙度贴图
  clearcoatNormalMap: scratchNormal, // 清漆法线贴图
  normalMap: carbonNormal,          // 基础法线贴图
  clearcoatNormalScale: new THREE.Vector2(0.1, 0.1), // 清漆法线缩放
});

2. 清漆相关属性

  • clearcoat:清漆层的强度
  • clearcoatRoughness:清漆层的粗糙度
  • clearcoatNormalMap:清漆层的法线贴图
  • clearcoatNormalScale:清漆法线贴图的缩放

第八部分:布料和织物材料光泽效果

1. Sheen属性

Sheen属性用于模拟织物等材料的光泽效果,特别适合制作布料、丝绸等材质。

const sphereMaterial = new THREE.MeshPhysicalMaterial({
  color: 0x222288,              // 基础颜色
  sheen: 1,                     // 光泽强度 (0-1)
  sheenColor: 0xffffff,         // 光泽颜色
  roughness: 1,                 // 粗糙度
  sheenRoughness: 1,            // 光泽粗糙度
  sheenColorMap: brickRoughness, // 光泽颜色贴图
});

2. Sheen相关属性

  • sheen:光泽效果的强度
  • sheenColor:光泽的颜色
  • sheenRoughness:光泽的粗糙度
  • sheenColorMap:光泽颜色贴图

第九部分:虹彩效应(Iridescence)

1. 虹彩效果简介

虹彩效果可以模拟某些特殊材质(如肥皂泡、昆虫翅膀、油膜等)产生的彩虹色效果。

const sphereMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xffffff,                           // 基础颜色
  roughness: 0.05,                          // 粗糙度
  transmission: 1,                          // 透射率
  thickness: 0.1,                           // 厚度
  iridescence: 1,                           // 虹彩强度 (0-1)
  reflectivity: 1,                          // 反射率
  iridescenceIOR: 1.3,                      // 虹彩折射率
  iridescenceThicknessRange: [100, 400],    // 虹彩厚度范围
  iridescenceThicknessMap: brickRoughness,  // 虹彩厚度贴图
});

2. 虹彩相关属性

  • iridescence:虹彩效果强度
  • iridescenceIOR:虹彩折射率
  • iridescenceThicknessRange:虹彩厚度范围
  • iridescenceThicknessMap:虹彩厚度贴图

3. 通过GUI调节虹彩参数

// 调节虹彩参数
gui.add(sphereMaterial, "iridescence", 0, 1).name("彩虹色");
gui.add(sphereMaterial, "reflectivity", 0, 1).name("反射率");
gui.add(sphereMaterial, "iridescenceIOR", 0, 3).name("彩虹色折射率");

// 调节虹彩厚度范围
let iridescenceThickness = {
  min: 100,
  max: 400,
};

gui
  .add(iridescenceThickness, "min", 0, 1000)
  .name("彩虹色最小厚度")
  .onChange(() => {
    sphereMaterial.iridescenceThicknessRange[0] = iridescenceThickness.min;
  });

gui
  .add(iridescenceThickness, "max", 0, 1000)
  .name("彩虹色最大厚度")
  .onChange(() => {
    sphereMaterial.iridescenceThicknessRange[1] = iridescenceThickness.max;
  });

第十部分:发光属性与发光贴图

1. 发光效果的实现

通过emissive属性可以创建自发光效果,常用于模拟屏幕、灯泡等发光物体。

// 加载手机模型并设置发光效果
gltfLoader.load(
  "./model/mobile/scene.glb",
  (gltf) => {
    console.log(gltf);
    scene.add(gltf.scene);
    
    // 可以进一步调整屏幕等特定部分的发光效果
    let screen = gltf.scene.getObjectByName("screen"); // 假设屏幕有特定名称
    if(screen) {
      screen.material.emissive = new THREE.Color(0x00ffff); // 设置发光颜色
      screen.material.emissiveIntensity = 1; // 设置发光强度
    }
  }
);

2. 环境贴图的重要性

发光效果通常需要配合高质量的环境贴图才能达到最佳效果:

// 加载HDR环境贴图
let rgbeLoader = new RGBELoader();
rgbeLoader.load("./texture/Alex_Hart-Nature_Lab_Bones_2k.hdr", (envMap) => {
  envMap.mapping = THREE.EquirectangularRefractionMapping;
  scene.background = new THREE.Color(0x7aaff5);
  scene.environment = envMap;  // 设置场景环境贴图
});

第十一部分:控制器限制查看3D场景

1. 轨道控制器的限制设置

为了限制用户的视角范围,可以对轨道控制器设置各种限制:

const controls = new OrbitControls(camera, renderer.domElement);

// 设置目标点
controls.target.set(0, 1.2, 0);

// 禁用平移
controls.enablePan = false;

// 设置距离限制
controls.minDistance = 3;  // 最小距离
controls.maxDistance = 5;  // 最大距离

// 设置角度限制
controls.minPolarAngle = Math.PI / 2 - Math.PI / 12;  // 垂直最小角度
controls.maxPolarAngle = Math.PI / 2;                 // 垂直最大角度

controls.minAzimuthAngle = Math.PI / 2 - Math.PI / 12;  // 水平最小角度
controls.maxAzimuthAngle = Math.PI / 2 + Math.PI / 12;  // 水平最大角度

2. 限制参数说明

  • enablePan:是否启用平移
  • minDistance/maxDistance:相机与目标点的最小/最大距离
  • minPolarAngle/maxPolarAngle:垂直旋转角度限制
  • minAzimuthAngle/maxAzimuthAngle:水平旋转角度限制

第十二部分:材质销毁

1. 资源管理的重要性

在Three.js中,及时释放不再使用的材质、纹理等资源是非常重要的,以避免内存泄漏。

// 销毁物体的示例代码
function disposeObject(obj) {
  if (obj.geometry) {
    obj.geometry.dispose();
  }
  
  if (obj.material) {
    if (Array.isArray(obj.material)) {
      obj.material.forEach(material => {
        if (material.map) material.map.dispose();
        material.dispose();
      });
    } else {
      if (obj.material.map) obj.material.map.dispose();
      obj.material.dispose();
    }
  }
}

2. 纹理和材质的销毁

// 销毁纹理
texture.dispose();

// 销毁材质
material.dispose();

// 销毁几何体
geometry.dispose();

总结

通过本教程,我们学习了Three.js中材质的进阶用法:

  1. MatCap材质:高效预渲染光照效果的材质类型
  2. Lambert和Phong材质:传统光照模型的两种基本材质
  3. 玻璃和水晶效果:利用折射和反射实现透明材质
  4. Standard材质:PBR渲染管线的标准材质
  5. 透光效果:实现半透明和光线穿透效果
  6. 折射率和反射率:控制光线与材质表面的交互
  7. 清漆效果:模拟表面涂层的额外反射层
  8. 光泽效果:模拟织物等材质的特殊光泽
  9. 虹彩效应:创建彩虹色的光学效果
  10. 发光效果:实现自发光材质
  11. 控制器限制:限制用户视角的交互方式
  12. 资源管理:正确销毁材质以避免内存泄漏

这些高级材质特性可以让您的3D场景更加真实和吸引人。掌握这些技术后,您可以创建出令人惊叹的视觉效果。

Three.js Geometry进阶

2026年1月15日 14:37

概述

本文档将介绍Three.js中Geometry的进阶用法,包括UV映射、法向量、几何体变换、包围盒计算等重要概念。通过这些知识点,您将能够更好地控制和操作3D几何体。

第一部分:UV属性设置

1. UV映射的概念

UV映射是将2D纹理映射到3D几何体表面的过程。U和V分别对应纹理坐标的水平和垂直轴,与3D空间中的X、Y、Z轴相对应。

2. 基本UV设置

// 创建几何体
const geometry = new THREE.BufferGeometry();

// 创建顶点数据
const vertices = new Float32Array([
  -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0,
]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));

// 创建索引
const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));

// 设置UV坐标
const uv = new Float32Array([
  0, 0,   // 第一个顶点的UV坐标
  1, 0,   // 第二个顶点的UV坐标
  1, 1,   // 第三个顶点的UV坐标
  0, 1,   // 第四个顶点的UV坐标
]);
// 创建UV属性
geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));

// 应用纹理
const texture = new THREE.TextureLoader().load("./texture/uv_grid_opengl.jpg");
const material = new THREE.MeshBasicMaterial({ map: texture });
const plane = new THREE.Mesh(geometry, material);

3. UV坐标详解

UV坐标系的原点(0,0)通常位于纹理的左下角,而(1,1)位于右上角。每个顶点都需要分配相应的UV坐标,以便正确映射纹理。

第二部分:法向量

1. 法向量的概念

法向量是垂直于表面的向量,用于确定光照计算、背面剔除等。每个顶点都可以有自己的法向量。

2. 手动设置法向量

// 设置法向量
const normals = new Float32Array([
  0, 0, 1,  // 第一个顶点的法向量
  0, 0, 1,  // 第二个顶点的法向量
  0, 0, 1,  // 第三个顶点的法向量
  0, 0, 1,  // 第四个顶点的法向量
]);
// 创建法向量属性
geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));

3. 自动计算法向量

// 计算法向量
geometry.computeVertexNormals();

4. 显示法向量辅助器

import { VertexNormalsHelper } from "three/examples/jsm/helpers/VertexNormalsHelper.js";

// 创建法向量辅助器
const helper = new VertexNormalsHelper(plane, 0.2, 0xff0000);
scene.add(helper);

第三部分:几何体顶点转换

1. 几何体变换方法

BufferGeometry提供了多种变换方法来修改顶点数据:

// 平移几何体
geometry.translate(x, y, z);

// 旋转几何体
geometry.rotateX(Math.PI / 2);
geometry.rotateY(angle);
geometry.rotateZ(angle);

// 缩放几何体
geometry.scale(scaleX, scaleY, scaleZ);

2. 变换的顺序

变换的顺序很重要,通常是先缩放,再旋转,最后平移(SRT顺序)。

第四部分:几何体居中

1. 计算包围盒

// 计算包围盒
geometry.computeBoundingBox();

// 获取包围盒
let boundingBox = geometry.boundingBox;

// 获取包围盒中心点
let center = boundingBox.getCenter(new THREE.Vector3());

2. 几何体居中

// 将几何体居中
geometry.center();

3. 处理模型的世界变换

// 对于复杂模型,需要考虑世界矩阵
mesh.updateWorldMatrix(true, true);
boundingBox.applyMatrix4(mesh.matrixWorld);
let center = boundingBox.getCenter(new THREE.Vector3());

第五部分:包围盒

1. 包围盒的概念

包围盒是包含几何体所有顶点的最小矩形框,常用于碰撞检测和视锥剔除。

2. 计算包围盒

// 计算几何体的边界框
geometry.computeBoundingBox();

// 获取边界框
let boundingBox = geometry.boundingBox;
console.log(boundingBox);

3. 包围球

包围球是包含几何体所有顶点的最小球体:

// 计算包围球
geometry.computeBoundingSphere();

// 获取包围球
let boundingSphere = geometry.boundingSphere;
console.log(boundingSphere);

4. 可视化包围盒

// 创建包围盒辅助器
import { Box3Helper } from "three";

let boxHelper = new THREE.Box3Helper(boundingBox, 0xffff00);
scene.add(boxHelper);

// 创建包围球辅助器
let sphereGeometry = new THREE.SphereGeometry(boundingSphere.radius, 16, 16);
let sphereMaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  wireframe: true,
});
let sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphereMesh.position.copy(boundingSphere.center);
scene.add(sphereMesh);

第六部分:多个几何体合并包围盒

1. 合并包围盒的原理

当需要为多个对象计算一个共同的包围盒时,可以使用union方法。

2. 实现方法

// 创建一个空的包围盒
var box = new THREE.Box3();

// 遍历所有对象
let arrSphere = [sphere1, sphere2, sphere3];
for (let i = 0; i < arrSphere.length; i++) {
  // 方法一:获取单个对象的包围盒并应用世界矩阵
  // arrSphere[i].geometry.computeBoundingBox();
  // let box3 = arrSphere[i].geometry.boundingBox;
  // arrSphere[i].updateWorldMatrix(true, true);
  // box3.applyMatrix4(arrSphere[i].matrixWorld);
  
  // 方法二:直接从对象创建包围盒
  let box3 = new THREE.Box3().setFromObject(arrSphere[i]);
  // 合并包围盒
  box.union(box3);
}

console.log(box);

// 创建合并后的包围盒辅助器
let boxHelper = new THREE.Box3Helper(box, 0xffff00);
scene.add(boxHelper);

第七部分:线框几何体

1. EdgesGeometry

EdgesGeometry用于显示几何体的边缘线条:

// 获取边缘几何体
let edgesGeometry = new THREE.EdgesGeometry(geometry);

// 创建线段材质
let edgesMaterial = new THREE.LineBasicMaterial({
  color: 0xffffff,
});

// 创建线段
let edges = new THREE.LineSegments(edgesGeometry, edgesMaterial);
scene.add(edges);

2. WireframeGeometry

WireframeGeometry用于显示几何体的线框模式:

// 线框几何体
let wireframeGeometry = new THREE.WireframeGeometry(geometry);

// 创建线段
let wireframe = new THREE.LineSegments(wireframeGeometry, edgesMaterial);
scene.add(wireframe);

3. 处理模型的线框显示

对于复杂的GLTF模型,需要遍历所有网格对象:

gltf.scene.traverse((child) => {
  if (child.isMesh) {
    let mesh = child;
    let geometry = mesh.geometry;

    // 获取边缘几何体
    let edgesGeometry = new THREE.EdgesGeometry(geometry);
    let edgesMaterial = new THREE.LineBasicMaterial({
      color: 0xffffff,
    });

    // 创建线段
    let edges = new THREE.LineSegments(edgesGeometry, edgesMaterial);

    // 应用原始对象的变换矩阵
    mesh.updateWorldMatrix(true, true);
    edges.matrix.copy(mesh.matrixWorld);
    edges.matrix.decompose(edges.position, edges.quaternion, edges.scale);

    // 添加到场景
    scene.add(edges);
  }
});

总结

通过本教程,我们学习了Three.js中Geometry的进阶用法:

  1. UV映射:学会了如何为自定义几何体设置UV坐标,使纹理能够正确映射到几何体表面

  2. 法向量:了解了法向量的重要性及其设置方法,包括手动设置和自动计算

  3. 几何体变换:掌握了如何对几何体进行平移、旋转和缩放操作

  4. 几何体居中:学会了如何计算几何体的中心并将其居中

  5. 包围盒和包围球:理解了包围盒和包围球的概念及应用,包括可视化方法

  6. 合并包围盒:掌握了如何为多个对象计算共同的包围盒

  7. 线框几何体:学会了如何显示几何体的边缘和线框,用于模型可视化

这些技能对于创建复杂的3D场景和优化渲染性能至关重要。掌握这些几何体操作技巧将使您能够更精确地控制3D对象的行为和外观。

昨天以前首页

Three.js 环境搭建与开发初识

2026年1月14日 17:58

概述

本文档将详细介绍如何搭建ThreeJS开发环境以及创建您的第一个ThreeJS应用程序。通过本文档,您将学会:

  • 如何安装和配置ThreeJS开发环境
  • 如何创建一个简单的3D立方体并让它旋转
  • 如何将ThreeJS与Vue和React框架集成

第一部分:环境搭建与第一个应用

1. 初始化项目

要创建一个ThreeJS项目,首先需要初始化一个新的npm项目并安装必要的依赖:

npm create vite@latest my-threejs-app
cd my-threejs-app
npm install
npm install three

这将创建一个基于Vite的新项目,并安装ThreeJS作为依赖项。

2. 项目结构

典型的ThreeJS项目结构如下:

my-threejs-app/
├── public/
│   └── css/
│       └── style.css
├── src/
│   └── main.js
├── index.html
├── package.json
└── vite.config.js

3. HTML文件配置

index.html中,我们需要设置基本的HTML结构:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="src/main-mk.js"></script>
  </body>
</html>

注意:我们引入了CSS样式表来确保Canvas元素正确显示。

4. CSS样式配置

public/css/style.css中设置基本样式:

*{
  margin: 0;
  padding: 0;
}

canvas{
  display: block;
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
}

这些样式确保Canvas元素占据整个浏览器窗口且没有默认的边距。

5. 核心JavaScript代码

这是ThreeJS应用的核心代码(在src/main-mk.js中):

import * as THREE from 'three';

// 创建场景
const scene = new THREE.Scene();
// 修改场景背景色
scene.background = new THREE.Color(0xeeeeee);

// 创建透视相机
const camera = new THREE.PerspectiveCamera(
  45, // 视角
  window.innerWidth / window.innerHeight, // 宽高比
  0.1, // 近平面
)

// 创建WebGL渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建几何体 - 盒子几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 创建材质 - 基础网格材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建网格对象
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 设置相机位置
camera.position.z = 5;

// 动画循环函数
function animate() {
  requestAnimationFrame(animate);
  
  // 让立方体持续旋转
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  
  // 渲染场景
  renderer.render(scene, camera);
}

// 启动动画循环
animate()

这段代码包含了ThreeJS应用的三个核心组件:

  1. 场景(Scene):所有3D对象的容器
  2. 相机(Camera):定义观察者视角
  3. 渲染器(Renderer):负责将场景和相机组合起来渲染为图像

6. 项目的package.json配置

{
  "name": "01-startapp",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "vite": "^4.3.9"
  },
  "dependencies": {
    "three": "^0.153.0"
  }
}

第二部分:与Vue框架集成

1. Vue项目配置

当将ThreeJS与Vue集成时,需要在Vue项目中安装额外的依赖:

{
  "name": "threejsvue",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "three": "^0.153.0",
    "vue": "^3.2.47"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.1.0",
    "vite": "^4.3.9"
  }
}

2. 在Vue组件中使用ThreeJS

在Vue的App.vue文件中可以直接集成ThreeJS代码:

<script setup>
// 导入threejs
import * as THREE from "three";

// 创建场景
const scene = new THREE.Scene();

// 创建相机
const camera = new THREE.PerspectiveCamera(
  45, // 视角
  window.innerWidth / window.innerHeight, // 宽高比
  0.1, // 近平面
  1000 // 远平面
);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 创建材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建网格
const cube = new THREE.Mesh(geometry, material);

// 将网格添加到场景中
scene.add(cube);

// 设置相机位置
camera.position.z = 5;
camera.lookAt(0, 0, 0);

// 渲染函数
function animate() {
  requestAnimationFrame(animate);
  // 旋转
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  // 渲染
  renderer.render(scene, camera);
}
animate();
</script>

<template>
  <div></div>
</template>

<style>
* {
  margin: 0;
  padding: 0;
}

canvas {
  display: block;
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
}
</style>

第三部分:与React框架集成

1. React项目配置

当将ThreeJS与React集成时,需要在React项目中安装相应的依赖:

{
  "name": "react3d",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "three": "^0.153.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.37",
    "@types/react-dom": "^18.0.11",
    "@vitejs/plugin-react": "^4.0.0",
    "eslint": "^8.38.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.3.4",
    "vite": "^4.3.9"
  }
}

2. 在React组件中使用ThreeJS

在React的App.jsx文件中可以这样集成ThreeJS:

import { useState,useEffect ,Component} from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
// 导入threejs
import * as THREE from "three";
import './App.css'

class App extends Component{
  render(){
    return <div></div>
  }
  componentDidMount(){
    // 创建场景
    const scene = new THREE.Scene();

    // 创建相机
    const camera = new THREE.PerspectiveCamera(
      45, // 视角
      window.innerWidth / window.innerHeight, // 宽高比
      0.1, // 近平面
      1000 // 远平面
    );

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 创建几何体
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    // 创建材质
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    // 创建网格
    const cube = new THREE.Mesh(geometry, material);

    // 将网格添加到场景中
    scene.add(cube);

    // 设置相机位置
    camera.position.z = 5;
    camera.lookAt(0, 0, 0);

    // 渲染函数
    function animate() {
      requestAnimationFrame(animate);
      // 旋转
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      // 渲染
      renderer.render(scene, camera);
    }
    animate();
  }
}

export default App

总结

通过以上步骤,我们已经成功搭建了ThreeJS开发环境,并创建了独立运行的ThreeJS应用以及与Vue和React框架集成的应用。ThreeJS的三个核心概念——场景、相机和渲染器是构建任何3D应用的基础,理解它们的作用和关系对于后续学习非常重要。

无论是在纯JavaScript项目还是在现代前端框架(Vue、React)中,ThreeJS的基本使用方法都是一致的,只是集成方式略有不同。掌握了这些基础知识后,您可以进一步探索ThreeJS的更多功能,如光照、材质、纹理等高级特性。

从“无”到“有”:手动实现一个 3D 渲染循环全过程

作者 烛阴
2026年1月12日 22:34

一、 Three.js 的基本构成

  1. Scene :场景。
  2. Camera :摄像机。
  3. Renderer :渲染器,。

二、具体实现

1. 初始化场景 (The Scene)

场景是一切物体的容器。

const scene = new THREE.Scene();
// 💡 INTP 视角:把它想象成一个坐标系原点为 (0,0,0) 的无限空腔。

2. 配置相机 (The Camera)

最常用的是 透视相机(PerspectiveCamera) ,它模拟了人眼的“近大远小”效果。

const camera = new THREE.PerspectiveCamera(
    75, // 视角 (Field of View)
    window.innerWidth / window.innerHeight, // 宽高比
    0.1, // 近剪裁面
    1000 // 远剪裁面
);
camera.position.z = 5; // 将相机后退 5 个单位,否则会在物体中心

3. 加入材质 (The Mesh)

一个物体由两部分组成:

  • 几何体(Geometry)
  • 材质(Material)
const geometry = new THREE.BoxGeometry(1, 1, 1); // 形状:立方体
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 材质:基础绿色
const cube = new THREE.Mesh(geometry, material); // 组合成网格
scene.add(cube); // 必须添加到场景中

4. 渲染与循环 (The Render Loop)

这是最关键的一步。我们需要每一秒刷新 60 次屏幕,才能看到动画。

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

function animate() {
    requestAnimationFrame(animate); // 核心:请求下一帧
    
    // 让物体动起来,增加一点生命力
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera); // 真正绘制的一行
}
animate();

📂 核心代码与完整示例:   my-three-app

总结

如果你喜欢本教程,记得点赞+收藏!关注我获取更多Three.js开发干货

❌
❌