一直以来没有系统的学习three.js,那就从现在开始记录我学习的过程吧

26 阅读5分钟

中文文档(切换语言为中文即可):threejs.org/docs/index.…

image.png

examples示例: threejs.org/examples/

基础模版

  • 1.创建场景:THREE.Scene 是所有3D对象的容器。
  • 2.创建相机:THREE.Perspectivecamera用于定义视角,参数分别为视角角度、宽高比、近裁剪平面和远裁剪平面。
  • 3.创建渲染器:THREE.webGLRenderer 负责将3D场景渲染到屏幕,设置渲染器大小并将其附加到HTML文档中。
  • 4.创建几何体:THREE.BoxGeometry 创建一个立方体的形状,参数表示边长。
  • 5.响应窗口大小变化。
  • 6.渲染循环: requestAnimationFrame 用于创建动画循环,不断调用 renderer.render 渲染场景和相机视图.
<!DOCTYPE html>
<html>
<head>
    <title>Three.js 基本模板</title>
    <!-- 引入 Three.js 库 -->
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script>
        // 1. 创建场景
        const scene = new THREE.Scene();

        // 2. 创建相机(透视相机)
        // 参数:视场角、宽高比、近平面、远平面
        const camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            1000
        );
        camera.position.z = 5; // 相机位置

        // 3. 创建渲染器
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器尺寸
        document.body.appendChild(renderer.domElement); // 将渲染器添加到页面

        // 4. 创建几何体(立方体)
        const geometry = new THREE.BoxGeometry();
        // 创建材质(基础网格材质,带颜色)
        const material = new THREE.MeshBasicMaterial({ 
            color: 0x00ff00,
            wireframe: true // 线框模式,便于观察
        });
        // 创建网格(几何体+材质)
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube); // 将立方体添加到场景

        // 5. 响应窗口大小变化
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix(); // 更新相机投影矩阵
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // 6. 动画循环
        function animate() {
            requestAnimationFrame(animate); // 递归调用,创建动画循环

            // 立方体旋转动画
            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;

            renderer.render(scene, camera); // 渲染场景
        }

        // 启动动画
        animate();
    </script>
</body>
</html>

Three.js 常用 API 速查表

一、核心基础组件

1. 场景(Scene)

  • 创建场景:const scene = new THREE.Scene();
  • 添加物体:scene.add(object);
  • 移除物体:scene.remove(object);
  • 设置背景色:scene.background = new THREE.Color(0xffffff);

2. 相机(Camera)

透视相机(常用)

  • 创建:const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

    • fov:视场角(默认 75);aspect:宽高比(window.innerWidth/window.innerHeight);near/far:近 / 远裁剪面
  • 设置位置:camera.position.set(x, y, z);

  • 看向目标:camera.lookAt(targetPosition);(targetPosition 为 THREE.Vector3 实例)

正交相机

  • 创建:const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);

3. 渲染器(Renderer)

  • 创建:const renderer = new THREE.WebGLRenderer();
  • 设置尺寸:renderer.setSize(width, height);
  • 挂载到页面:document.body.appendChild(renderer.domElement);
  • 渲染场景:renderer.render(scene, camera);
  • 开启抗锯齿:new THREE.WebGLRenderer({ antialias: true });

二、物体与材质

1. 几何体(Geometry)

基础几何体

  • 立方体:new THREE.BoxGeometry(width, height, depth);
  • 球体:new THREE.SphereGeometry(radius, widthSegments, heightSegments);
  • 圆柱体:new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radialSegments);
  • 平面:new THREE.PlaneGeometry(width, height);

缓冲几何体(性能更优)

  • 立方体:new THREE.BoxBufferGeometry(width, height, depth);(其他几何体同理,后缀加 Buffer)

2. 材质(Material)

基础材质

  • 网格基础材质(不受光照影响):new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
  • 网格漫反射材质(受光照影响):new THREE.MeshLambertMaterial({ color: 0x00ff00 });
  • 网格高光材质(带反光效果):new THREE.MeshPhongMaterial({ color: 0x00ff00, shininess: 100 });

材质通用属性

  • 设置颜色:material.color.set(0x00ff00);
  • 设置透明度:material.opacity = 0.5; material.transparent = true;

3. 网格物体(Mesh)

  • 创建:const mesh = new THREE.Mesh(geometry, material);
  • 位置设置:mesh.position.set(x, y, z);
  • 旋转设置:mesh.rotation.set(x, y, z);(单位:弧度)
  • 缩放设置:mesh.scale.set(x, y, z);
  • 隐藏 / 显示:mesh.visible = false/true;

三、光照系统

1. 基础光源

  • 环境光(无阴影,整体提亮):const ambientLight = new THREE.AmbientLight(0xffffff, intensity);

  • 平行光(模拟太阳光,有阴影):const directionalLight = new THREE.DirectionalLight(0xffffff, intensity);

    • 设置方向:directionalLight.position.set(x, y, z);
    • 开启阴影:directionalLight.castShadow = true;
  • 点光源(向四周发射光线):const pointLight = new THREE.PointLight(0xffffff, intensity, distance, decay);

2. 光源操作

  • 添加光源到场景:scene.add(light);

四、动画与交互

1. 动画循环

  • 基础循环:

    function animate() {
      requestAnimationFrame(animate);
      // 物体动画逻辑(如旋转)
      mesh.rotation.x += 0.01;
      renderer.render(scene, camera);
    }
    animate();
    

2. 窗口自适应

  • 监听窗口变化:
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix(); // 更新相机投影矩阵
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
    

五、常用工具

1. 向量(Vector3)

  • 创建向量:const vec3 = new THREE.Vector3(x, y, z);
  • 向量加法:vec3.add(otherVec);
  • 向量归一化:vec3.normalize();

2. 控制器(轨道控制器,需引入扩展)

  • 引入:<script src="https://cdn.jsdelivr.net/npm/three@0.160.0/examples/js/controls/OrbitControls.js"></script>
    const controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true; // 开启阻尼效果,更平滑
    // 动画循环中更新控制器
    function animate() {
      controls.update();
      // ...其他逻辑
    }
    

六、纹理贴图(Textures)

1. 基础纹理加载

  • 加载普通纹理(如图片作为材质表面):

    // 创建纹理加载器
    const textureLoader = new THREE.TextureLoader();
    // 加载图片(支持回调/Promise)
    const texture = textureLoader.load(
      'textures/earth.jpg', // 图片路径
      (texture) => { /* 加载成功回调 */ },
      (xhr) => { /* 加载进度:xhr.loaded / xhr.total */ },
      (error) => { /* 加载失败 */ }
    );
    // 应用到材质
    const material = new THREE.MeshBasicMaterial({ map: texture });
    

2. 纹理常用属性

  • 重复纹理:texture.repeat.set(2, 2);(x/y 方向重复次数)

  • 纹理包裹模式:

    texture.wrapS = THREE.RepeatWrapping; // 水平方向
    texture.wrapT = THREE.RepeatWrapping; // 垂直方向
    // 可选值:RepeatWrapping(重复)、ClampToEdgeWrapping(边缘拉伸)、MirroredRepeatWrapping(镜像重复)
    
  • 纹理过滤(缩放时):

    texture.minFilter = THREE.LinearMipmapLinearFilter; // 缩小过滤(更平滑)
    texture.magFilter = THREE.LinearFilter; // 放大过滤
    

3. 特殊纹理

  • 法线贴图(增强表面细节):

    const normalTexture = textureLoader.load('textures/normal.jpg');
    const material = new THREE.MeshPhongMaterial({ 
      map: baseTexture,
      normalMap: normalTexture 
    });
    
  • 环境贴图(反射周围环境):

    const envTexture = new THREE.CubeTextureLoader()
      .setPath('env/')
      .load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']); // 六张环境贴图
    scene.background = envTexture; // 场景背景使用环境贴图
    material.envMap = envTexture; // 材质反射环境
    

二、模型加载(GLB/GLTF、OBJ 等)

1. GLB/GLTF 模型(推荐,主流格式)

  • 引入加载器

    <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/examples/js/loaders/GLTFLoader.js"></script>
    
  • 加载模型

    const loader = new THREE.GLTFLoader();
    loader.load(
      'models/model.glb', // 模型路径
      (gltf) => { // 加载成功
        const model = gltf.scene; // 模型场景对象
        scene.add(model);
        // 调整模型位置/缩放
        model.position.set(0, 0, 0);
        model.scale.set(1, 1, 1);
        // 动画处理(如果有)
        const animations = gltf.animations;
        if (animations.length > 0) {
          const mixer = new THREE.AnimationMixer(model);
          const action = mixer.clipAction(animations[0]);
          action.play();
          // 在动画循环中更新
          function animate() {
            mixer.update(deltaTime); // deltaTime 需通过时钟计算
          }
        }
      },
      (xhr) => { /* 进度:xhr.loaded / xhr.total */ },
      (error) => { /* 失败 */ }
    );
    

2. OBJ 模型(传统格式,需配合材质)

  • 引入加载器

    <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/examples/js/loaders/OBJLoader.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/examples/js/loaders/MTLLoader.js"></script> <!-- 材质加载器 -->
    
  • 加载模型 + 材质

    // 先加载材质
    const mtlLoader = new THREE.MTLLoader();
    mtlLoader.load('models/model.mtl', (materials) => {
      materials.preload(); // 预加载材质
      // 再加载模型
      const objLoader = new THREE.OBJLoader();
      objLoader.setMaterials(materials); // 关联材质
      objLoader.load('models/model.obj', (object) => {
        scene.add(object);
      });
    });
    

3. 模型加载工具

  • DRACOLoader(压缩模型加载,需配合解码器):

    <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/examples/js/loaders/DRACOLoader.js"></script>
    
    const dracoLoader = new THREE.DRACOLoader();
    dracoLoader.setDecoderPath('libs/draco/'); // 解码器路径(需下载官方解码器文件)
    const gltfLoader = new THREE.GLTFLoader();
    gltfLoader.setDRACOLoader(dracoLoader); // 关联 DRACO 加载器
    gltfLoader.load('model-draco.glb', (gltf) => { /* 处理模型 */ });
    

    问豆包three.js可以做什么方向的事情,这是豆包的回复,我决定从每一个方向都做一个demo练习

image.png