Three.js实战指南:从基础场景到高级着色器开发

一、3D场景初始化:从空白到立方体

1.1 HTML模板搭建与依赖引入

创建Three.js应用的首要步骤是构建基础HTML结构。推荐使用CDN方式引入核心库文件,示例如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Three.js基础场景</title>
  6. <style>body { margin: 0; }</style>
  7. </head>
  8. <body>
  9. <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
  10. <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
  11. <script src="main.js"></script>
  12. </body>
  13. </html>

关键点说明:

  • 必须引入three.min.js核心库
  • 后续章节的交互功能需额外加载OrbitControls.js
  • 建议将业务逻辑分离至独立JS文件

1.2 核心渲染组件创建

main.js中初始化三大核心组件:

  1. // 场景设置
  2. const scene = new THREE.Scene();
  3. scene.background = new THREE.Color(0x333333);
  4. // 相机配置(透视相机)
  5. const camera = new THREE.PerspectiveCamera(
  6. 75, // 视野角度
  7. window.innerWidth / window.innerHeight, // 宽高比
  8. 0.1, // 近裁剪面
  9. 1000 // 远裁剪面
  10. );
  11. camera.position.z = 5;
  12. // 渲染器初始化
  13. const renderer = new THREE.WebGLRenderer({ antialias: true });
  14. renderer.setSize(window.innerWidth, window.innerHeight);
  15. document.body.appendChild(renderer.domElement);

1.3 基础几何体生成

创建旋转立方体的完整流程:

  1. // 几何体与材质
  2. const geometry = new THREE.BoxGeometry(1, 1, 1);
  3. const material = new THREE.MeshBasicMaterial({
  4. color: 0x00ff00,
  5. wireframe: false
  6. });
  7. const cube = new THREE.Mesh(geometry, material);
  8. scene.add(cube);
  9. // 渲染循环
  10. function animate() {
  11. requestAnimationFrame(animate);
  12. cube.rotation.x += 0.01;
  13. cube.rotation.y += 0.01;
  14. renderer.render(scene, camera);
  15. }
  16. animate();

关键参数说明:

  • BoxGeometry参数依次为长宽高
  • MeshBasicMaterialwireframe属性控制线框模式
  • 旋转动画通过修改rotation属性实现

二、进阶交互控制:轨道控制器详解

2.1 时间驱动与补间动画对比

动画类型 实现原理 适用场景
时间驱动动画 requestAnimationFrame循环 持续旋转/缩放效果
补间动画 插值计算关键帧 路径动画/状态过渡

补间动画实现示例:

  1. import { Tween } from '@tweenjs/tween.js';
  2. // 创建补间动画
  3. new Tween(cube.position)
  4. .to({ x: 2 }, 1000) // 1秒内移动到x=2
  5. .easing(TWEEN.Easing.Quadratic.Out)
  6. .start();
  7. // 动画循环中更新
  8. function animate(time) {
  9. TWEEN.update(time);
  10. // ...原有渲染代码
  11. }

2.2 轨道控制器配置指南

OrbitControls核心参数配置表:

参数 默认值 功能说明
enableDamping false 启用惯性阻尼效果
dampingFactor 0.05 阻尼系数(值越小惯性越强)
rotateSpeed 1.0 旋转灵敏度
zoomSpeed 1.0 缩放灵敏度

完整配置示例:

  1. const controls = new OrbitControls(camera, renderer.domElement);
  2. controls.enableDamping = true;
  3. controls.dampingFactor = 0.05;
  4. controls.rotateSpeed = 0.8;
  5. // 需要在animate函数中调用update
  6. function animate() {
  7. controls.update();
  8. // ...其他代码
  9. }

2.3 多设备交互实现

触摸事件检测代码框架:

  1. renderer.domElement.addEventListener('touchstart', (e) => {
  2. if (e.touches.length === 2) {
  3. // 双指缩放处理
  4. } else if (e.touches.length === 1) {
  5. // 单指旋转处理
  6. }
  7. });
  8. // 鼠标点击检测
  9. renderer.domElement.addEventListener('click', (e) => {
  10. const mouse = new THREE.Vector2(
  11. (e.clientX / window.innerWidth) * 2 - 1,
  12. -(e.clientY / window.innerHeight) * 2 + 1
  13. );
  14. // 射线检测实现对象拾取
  15. const raycaster = new THREE.Raycaster();
  16. raycaster.setFromCamera(mouse, camera);
  17. const intersects = raycaster.intersectObjects(scene.children);
  18. if (intersects.length > 0) {
  19. console.log('点击对象:', intersects[0].object);
  20. }
  21. });

三、着色器编程:从基础到特效实现

3.1 GLSL着色器结构解析

顶点着色器标准模板:

  1. uniform mat4 modelViewMatrix;
  2. uniform mat4 projectionMatrix;
  3. attribute vec3 position;
  4. attribute vec3 normal;
  5. varying vec3 vNormal;
  6. void main() {
  7. vNormal = normal;
  8. gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  9. }

片元着色器标准模板:

  1. varying vec3 vNormal;
  2. uniform vec3 color;
  3. void main() {
  4. vec3 light = normalize(vec3(1.0, 1.0, 1.0));
  5. float diffuse = max(dot(vNormal, light), 0.0);
  6. gl_FragColor = vec4(color * diffuse, 1.0);
  7. }

3.2 动态水面波纹实现

噪声函数生成波纹:

  1. // 顶点着色器修改
  2. uniform float time;
  3. varying vec2 vUv;
  4. float noise(vec2 p) {
  5. return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
  6. }
  7. void main() {
  8. vUv = uv;
  9. float wave = sin(position.x * 5.0 + time) * 0.1;
  10. vec3 newPos = position + vec3(0.0, wave, 0.0);
  11. gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);
  12. }

3.3 JS与着色器数据交互

通过uniform变量传递数据:

  1. // 创建着色器材质
  2. const shaderMaterial = new THREE.ShaderMaterial({
  3. uniforms: {
  4. time: { value: 0 },
  5. color: { value: new THREE.Color(0x1e90ff) }
  6. },
  7. vertexShader: vertexShaderSource,
  8. fragmentShader: fragmentShaderSource
  9. });
  10. // 动画循环中更新uniform
  11. function animate(time) {
  12. shaderMaterial.uniforms.time.value = time * 0.001;
  13. // ...渲染代码
  14. }

四、性能优化与最佳实践

4.1 渲染性能监控

关键指标检测代码:

  1. const stats = new Stats();
  2. document.body.appendChild(stats.dom);
  3. function animate() {
  4. stats.begin();
  5. // ...渲染代码
  6. stats.end();
  7. requestAnimationFrame(animate);
  8. }

4.2 资源管理策略

  1. 几何体复用:使用THREE.InstancedMesh批量渲染
  2. 纹理压缩:采用KTX2或BASIS格式
  3. 内存释放:及时调用dispose()方法

4.3 跨平台适配方案

响应式设计实现:

  1. window.addEventListener('resize', () => {
  2. camera.aspect = window.innerWidth / window.innerHeight;
  3. camera.updateProjectionMatrix();
  4. renderer.setSize(window.innerWidth, window.innerHeight);
  5. });

本指南完整覆盖了Three.js开发的核心技术点,从基础场景搭建到高级着色器编程均有详细说明。通过提供的代码示例和参数配置表,开发者可以快速构建出具有专业水准的3D交互应用。建议结合官方文档进行深入学习,并积极参与开源社区讨论以获取最新技术动态。