Skip to content

Web 3D与Three.js

简介

随着WebGL和WebGPU等技术的发展,浏览器已经成为一个强大的3D渲染平台。Three.js作为最流行的WebGL库,大大简化了Web 3D开发流程,结合了图形学、物理模拟、用户交互等多个领域的技术,为用户提供沉浸式的Web体验。

核心技术

WebGL

  • OpenGL ES 2.0/3.0 Web实现
  • 着色器编程(GLSL)
  • 3D数学基础
  • 渲染管线与性能优化

WebGPU

  • 新一代Web图形API
  • 计算着色器支持
  • 多线程渲染
  • 与原生GPU API对齐

Three.js

  • 场景、相机与灯光
  • 几何体与材质
  • 动画与变换
  • 加载器与导出工具

3D建模与资源

模型格式

  • glTF/GLB标准格式
  • FBX与OBJ导入
  • DRACO压缩
  • 模型优化策略

材质与纹理

  • PBR物理材质
  • 法线贴图与置换贴图
  • 环境贴图与反射
  • 纹理压缩与流式加载

动画系统

  • 骨骼动画
  • 变形目标动画
  • 关键帧插值
  • 动作混合与过渡

物理与交互

物理引擎

  • Ammo.js/cannon.js
  • 刚体动力学
  • 碰撞检测
  • 约束与关节

用户交互

  • 鼠标与触摸控制
  • VR控制器
  • 射线投射与拾取
  • 手势识别

粒子系统

  • GPU加速粒子
  • 粒子发射器
  • 物理驱动粒子
  • 特效与视觉反馈

性能优化

渲染优化

  • 层次细节(LOD)
  • 实例化渲染
  • 遮挡剔除
  • 渲染队列管理

资源管理

  • 资源预加载
  • 延迟加载
  • 内存管理
  • 资源池与复用

移动设备优化

  • 自适应分辨率
  • 着色器复杂度控制
  • 电池与热量管理
  • 触摸控制优化

WebXR与沉浸式体验

虚拟现实(VR)

  • WebXR Device API
  • 立体渲染
  • 空间音频
  • VR交互设计

增强现实(AR)

  • WebXR AR模块
  • 平面检测
  • 图像追踪
  • AR内容放置

沉浸式Web

  • 空间界面设计
  • 3D音频集成
  • 多用户交互
  • 可访问性考虑

代码示例

javascript
// Three.js基础场景示例
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x336699);

// 创建相机
const camera = new THREE.PerspectiveCamera(
  75, window.innerWidth / window.innerHeight, 0.1, 1000
);
camera.position.set(0, 1.5, 3);

// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1, 0);
controls.update();

// 添加灯光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 7.5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
scene.add(directionalLight);

// 添加地面
const groundGeometry = new THREE.PlaneGeometry(10, 10);
const groundMaterial = new THREE.MeshStandardMaterial({ 
  color: 0x999999,
  roughness: 0.8,
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);

// 加载3D模型
const loader = new GLTFLoader();
loader.load(
  'models/character.glb',
  (gltf) => {
    const model = gltf.scene;
    model.traverse((object) => {
      if (object.isMesh) {
        object.castShadow = true;
      }
    });
    model.position.set(0, 0, 0);
    model.scale.set(1, 1, 1);
    scene.add(model);
    
    // 动画
    const mixer = new THREE.AnimationMixer(model);
    const animations = gltf.animations;
    if (animations && animations.length) {
      const idleAnimation = mixer.clipAction(animations[0]);
      idleAnimation.play();
    }
  },
  (xhr) => {
    console.log((xhr.loaded / xhr.total * 100) + '% loaded');
  },
  (error) => {
    console.error('An error happened', error);
  }
);

// 处理窗口大小变化
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

// 动画循环
const clock = new THREE.Clock();
function animate() {
  requestAnimationFrame(animate);
  
  const delta = clock.getDelta();
  mixer?.update(delta);
  
  controls.update();
  renderer.render(scene, camera);
}

animate();

用知识点燃技术的火山