Three.js学习

简介

Three.js 是一个基于 WebGL 的 JavaScript 3D 库,它为开发者提供了一系列易于使用的 API,让开发者能够在网页上轻松创建和展示复杂的 3D 场景、动画和交互效果,而无需深入了解 WebGL 的底层细节。下面将从其特点、应用场景和基本原理等方面详细介绍 Three.js。

特点

  • 简单易用:Three.js 对 WebGL 复杂的底层操作进行了封装,提供了直观且易于理解的 API,降低了开发 3D 网页应用的门槛。例如,创建一个简单的 3D 立方体,只需要几行代码:
import * as THREE from 'three';

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

// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

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

// 创建立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 渲染循环
function animate() {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
}
animate();
  • 功能强大:Three.js 支持多种几何体(如立方体、球体、平面等)、材质(如基础材质、标准材质、纹理材质等)、光照(如环境光、平行光、点光源等)、动画(如关键帧动画、Tween 动画等)以及模型加载(如 GLTF、OBJ 等格式)。
  • 跨平台兼容:由于基于 WebGL 技术,Three.js 可以在支持 WebGL 的现代浏览器(如 Chrome、Firefox、Safari 等)中运行,无需额外的插件。

应用场景

  • 游戏开发:可以利用 Three.js 创建各种类型的网页游戏,如角色扮演游戏、射击游戏、益智游戏等。通过创建 3D 场景、角色和道具,以及实现动画和交互效果,为玩家带来沉浸式的游戏体验。
  • 数据可视化:将数据以 3D 形式展示,使数据更加直观和易于理解。例如,展示地理信息、科学数据、商业数据等。
  • 虚拟现实(VR)和增强现实(AR):结合 VR 和 AR 设备,Three.js 可以创建沉浸式的虚拟和增强现实体验。例如,在网页上实现 3D 虚拟展厅、AR 购物等应用。
  • 建筑和室内设计:创建 3D 建筑模型和室内场景,让客户能够提前预览设计效果,进行交互式的漫游和体验。

基本原理

Three.js 的核心是场景(Scene)、相机(Camera)和渲染器(Renderer)。

  • 场景(Scene:是所有 3D 对象的容器,就像一个舞台,所有的物体、灯光等都将放置在这个舞台上。
  • 相机(Camera:决定了我们从哪个角度观察场景。Three.js 提供了多种类型的相机,如透视相机(PerspectiveCamera)和正交相机(OrthographicCamera)。透视相机模拟了人眼的视觉效果,有近大远小的特点;正交相机则没有透视效果,物体的大小不会随距离变化。通过new THREE.PerspectiveCamera()创建透视相机。
  • 渲染器(Renderer:负责将场景和相机的内容渲染到网页上的画布中。Three.js 提供了多种渲染器,如 WebGL 渲染器(WebGLRenderer)和 CSS3D 渲染器(CSS3DRenderer)。通过new THREE.WebGLRenderer()创建 WebGL 渲染器。

通过组合场景、相机和渲染器,以及添加各种几何体、材质、光照和动画,就可以创建出丰富多彩的 3D 网页应用。

1. 基础设置与初始化

1.1 场景(THREE.Scene

场景是 Three.js 中所有对象的容器,就像一个舞台,所有的物体、灯光等都将放置在这个舞台上。

import * as THREE from 'three';
const scene = new THREE.Scene();

这样创建一个场景并导出供其他模块使用。

1.2 相机(THREE.PerspectiveCamera

相机决定了我们从哪个角度观察场景。PerspectiveCamera是透视相机,它模拟了人眼的视觉效果,有近大远小的特点。

// 主相机
const camera = new THREE.PerspectiveCamera(
    45, // 视角大小
    window.innerWidth / window.innerHeight, // 宽高比
    0.1, // 近裁剪面
    1000 // 远裁剪面
);
camera.position.set(0, 0, 5); // 设置相机位置

封装创建相机的函数:

const defaultOptions = {
    fov: 45,
    aspect: window.innerWidth / window.innerHeight,
    near: 0.1,
    far: 1000,
    position: [0, 0, 5]
};

const createCamera = (options = {}) => {
    const cameraOpts = Object.assign(defaultOptions, options);
    const camera = new THREE.PerspectiveCamera(...Object.values(cameraOpts));
    camera.position.set(...cameraOpts.position);
    return camera;
};

export default createCamera;

1.3 渲染器(THREE.WebGLRenderer

渲染器负责将场景和相机的内容渲染到网页上的画布中。

class Renderer extends THREE.WebGLRenderer {
    constructor(scene, camera) {
        super({ antialias: true }); // 开启抗锯齿
        this.scene = scene;
        this.camera = camera;
        this.init();
    }

    init() {
        this.setSize(window.innerWidth, window.innerHeight); // 设置渲染器大小
        document.body.appendChild(this.domElement); // 将渲染器的DOM元素添加到页面中
        this.render(this.scene, this.camera); // 渲染场景
    }

    // 创建动画函数
    animation(cb) {
        if (typeof cb!== 'function') {
            console.error('animation callback必须是一个函数');
            return;
        }
        this.setAnimationLoop(cb); // 设置动画循环
    }
}

export default Renderer;

2. 几何体与网格

2.1 几何体(THREE.BoxGeometryTHREE.PlaneGeometry等)

几何体定义了物体的形状,例如立方体、平面、球体等。

// 创建立方体几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);

// 创建平面几何体
const planeGeometry = new THREE.PlaneGeometry(30, 30);

2.2 材质(THREE.MeshBasicMaterialTHREE.MeshStandardMaterial等)

材质决定了物体的外观,如颜色、光泽等。

// 基础网格材质,不受光照影响
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });

// 标准网格材质,受光照影响
const standardMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff });

不同材质的使用:

let material;
switch (val) {
    case 'basic':  // 基础网格材质(不受光照影响)
        material = new THREE.MeshBasicMaterial({
            color: materialParam.color,
            wireframe: materialParam.wireframe
        });
        break;
    case 'normal':  // 法向可视化材质
        material = new THREE.MeshNormalMaterial();
        break;
    case 'lambert':  // Lambert漫反射材质(适合哑光表面)
        material = new THREE.MeshLambertMaterial({
            color: materialParam.color
        });
        break;
    case 'phong':  // Phong高光材质(适合光滑表面)
        material = new THREE.MeshPhongMaterial({
            color: materialParam.color,
            shininess: materialParam.shininess
        });
        break;
    default:
        console.warn('未知材质类型');
        break;
}

2.3 网格(THREE.Mesh

网格是几何体和材质的组合,将形状和外观结合在一起形成一个可渲染的物体。

const mesh = new THREE.Mesh(cubeGeometry, basicMaterial);
scene.add(mesh); // 将网格添加到场景中

3. 光照

3.1 环境光(THREE.AmbientLight

环境光会均匀照亮场景中的所有物体,没有特定的方向。

const ambientLight = new THREE.AmbientLight(0xffffff, 0.2); // 颜色为白色,强度为0.2
scene.add(ambientLight);

3.2 平行光(THREE.DirectionalLight

平行光从一个特定的方向照射物体,就像太阳光一样。

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(3, 3, 3); // 设置光源位置
scene.add(directionalLight);

如何设置平行光的阴影:

directionalLight.castShadow = true; // 开启平行光投射阴影
plane.receiveShadow = true; // 平面接收阴影
renderer.shadowMap.enabled = true; // 开启渲染器的阴影映射

4. 辅助工具

4.1 坐标轴辅助工具(THREE.AxesHelper

坐标轴辅助工具用于可视化场景中的坐标轴,方便我们确定方向。

const axesHelper = new THREE.AxesHelper(10); // 长度为10
scene.add(axesHelper);

4.2 网格辅助工具(THREE.GridHelper

网格辅助工具用于可视化场景中的网格,帮助我们确定物体的位置。

const gridHelper = new THREE.GridHelper(20, 20); // 大小为20,分割为20份
scene.add(gridHelper);

4.3 轨道控制器(OrbitControls

轨道控制器允许用户通过鼠标交互来控制相机的视角,实现旋转、缩放和平移。

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const controls = new OrbitControls(camera, renderer.domElement);

封装辅助工具类:

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

class Helper {
    constructor(options = {}, camera, renderer, scene) {
        const defaultOpts = {
            OrbitControls: true,
            axesHelper: { size: 10 },
            gridHelper: { size: 20, division: 20 }
        };
        this.options = Object.assign(options, defaultOpts);
        this.camera = camera;
        this.renderer = renderer;
        this.scene = scene;
        this.init();
    }

    init() {
        const { OrbitControls, axesHelper, gridHelper } = this.options;
        OrbitControls && this.initOribit();
        axesHelper && this.initAxesHelper(axesHelper);
        gridHelper && this.initGrid(gridHelper);
    }

    initOribit() {
        this.oribitControl = new OrbitControls(this.camera, this.renderer.domElement);
    }

    initAxesHelper(option) {
        const { size } = option;
        const axesHelper = new THREE.AxesHelper(size);
        this.scene.add(axesHelper);
    }

    initGrid(option) {
        const { size, division } = option;
        const grid = new THREE.GridHelper(size, division);
        this.scene.add(grid);
    }
}

export default Helper;

5. 纹理与材质

5.1 纹理加载(THREE.TextureLoader

纹理加载器用于加载图像纹理,将其应用到物体的材质上。

const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('/src/assets/texture/地球.jpeg');
const material = new THREE.MeshStandardMaterial({ map: texture });

纹理的使用:

const texture = new THREE.TextureLoader().load('/src/assets/texture/地球.jpeg');
const textureAlpha = new THREE.TextureLoader().load('/src/assets/texture/world_normal.jpg');

shpere.material = new THREE.MeshStandardMaterial({
    map: texture,
    normalMap: textureAlpha
});

6. 模型加载

6.1 GLTF 模型加载(GLTFLoader

GLTFLoader 用于加载 GLTF 或 GLB 格式的 3D 模型。

import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

const gltfLoader = new GLTFLoader();
const darcoLoader = new DRACOLoader();
darcoLoader.setDecoderPath('/node_modules/three/examples/jsm/libs/draco/');
gltfLoader.setDRACOLoader(darcoLoader);

gltfLoader.load('/src/assets/models/gltf/ferrari.glb', (gltf) => {
    const model = gltf.scene;
    model.traverse(mesh => {
        if (mesh.isMesh) {
            mesh.castShadow = true;
        }
    });
    scene.add(model);
});

6.2 OBJ 模型加载(OBJLoaderMTLLoader

OBJLoader 用于加载 OBJ 格式的 3D 模型,MTLLoader 用于加载对应的材质文件。

import { MTLLoader } from 'three/addons/loaders/MTLLoader';
import { OBJLoader } from 'three/addons/loaders/OBJLoader';

const mtlLoader = new MTLLoader();
const basePath = '/src/assets/models/obj/';
mtlLoader.setPath(basePath);
mtlLoader.load('ambulance.mtl', (material) => {
    material.preload();
    const objLoader = new OBJLoader();
    objLoader.setMaterials(material);
    objLoader.load(`${basePath}ambulance.obj`, (object) => {
        object.traverse(mesh => {
            if (mesh.isMesh) {
                mesh.castShadow = true;
            }
        });
        scene.add(object);
    });
});

7. 动画

7.1 关键帧动画(THREE.KeyframeTrackTHREE.AnimationClipTHREE.AnimationMixer

关键帧动画允许我们通过定义关键帧来创建物体的动画效果。

// 1. 创建关键帧数据
const times = [0, 4, 8];
const positions = [0, 0, 0, 3, 4, 5, 0, 0, 0];
const kf = new THREE.KeyframeTrack('box.position', times, positions);

// 2. 创建剪辑对象clip
const clip = new THREE.AnimationClip('moving_clip', 8, [kf]);

// 3. 创建一个播放器mixer
const mixer = new THREE.AnimationMixer(cube);
const action = mixer.clipAction(clip);
action.play();
action.loop = THREE.LoopRepeat;

const clock = new THREE.Clock();
renderer.animation(() => {
    if (mixer) {
        mixer.update(clock.getDelta());
    }
    renderer.render(scene, camera);
});
你想学习关于 three.js 的内容吗?我可以为你提供一些相关的信息和资源。首先,three.js 是一个用于创建 3D 图形的 JavaScript 库,它可以在 Web 浏览器中渲染复杂的三维场景和动画效果。如果你想学习如何使用 three.js,以下是一些步骤和资源供你参考: 1. 了解基础知识:在开始学习 three.js 之前,建议你先掌握 HTML、CSS 和 JavaScript 的基础知识。 2. 安装和设置:你可以通过下载 three.js 的最新版本文件或使用 CDN 来引入 three.js 库。确保在你的 HTML 文件中正确地链接和配置 three.js。 3. 学习文档和示例:three.js 官方网站提供了详细的文档和示例,你可以通过阅读文档和尝试示例来了解 three.js 的各种功能和用法。官方文档地址是:https://threejs.org/docs/index.html 4. 学习基本概念:熟悉 three.js 中的基本概念,如场景(Scene)、相机(Camera)、渲染器(Renderer)、几何体(Geometry)、材质(Material)等。理解这些概念对于构建三维场景至关重要。 5. 创建简单场景:从简单的场景开始,逐步添加和调整对象、光照和材质等。通过实践来熟悉 three.js 的基本用法和 API。 6. 学习进阶技术:一旦你掌握了基本的用法,你可以学习更高级的技术,如动画、纹理映射、阴影、粒子效果等。three.js 提供了丰富的功能和扩展库,你可以根据自己的需求进一步探索。 除了官方文档外,还有一些优秀的教程和资源可供参考,例如: - three.js Fundamentals:https://threejsfundamentals.org/ ***
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super毛毛穗

今天晚饭加什么?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值