前言
为了满足工作需求,我已着手学习Three.js,并决定详细记录这一学习过程。在此旅程中,如果出现理解偏差或有其他更佳的学习方法,请大家不吝赐教,在评论区给予指正或分享您的宝贵建议,我将不胜感激。
搭建一个threejs项目
- 创建文件夹hello-cube
mkdir hello-cube
cd ./hello-cube
- 在根目录下创建src文件夹并在该文件夹内创建main.js(空文件)
mkdir src
- 初始化项目
npm init -y
- 使用npm install安装three库和构建工具webpack,webpack相关插件
npm install @types/three three
npm install html-webpack-plugin webpack webpack-cli webpack-dev-server -D
- 在根目录中创建index.html文件如下
<!DOCTYPE html>
<html><head><title>hello,正方体!</title><meta name="viewport" content="width=device-width, initial-scale=1" /><meta charset="UTF-8" /></head><style>#scene-container {width: 100vw;height: 100vh;}</style><body><div id="scene-container"></div></body>
</html>
- 在根目录创建webpack.config.js文件如下
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {mode: "development",entry: "./src/main.js",output: {filename: "main.js",path: path.resolve(__dirname, "dist"),clean: true,},devServer: {static: "./dist",},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, "index.html"),}),],
};
- 在package.json中scripts添加指令
"scripts": {"start": "webpack serve --open",
}
小结
至此项目已搭建完成,大家可以安装自己的方式搭建。如果是安装本文搭建现在可以终端执行npm run start启动看看。只要webpack能构建成功就可以了。
场景、相机和渲染器
- 场景(scene)
场景是我们能看到的一切的载体。
场景空间是一个 3D 笛卡尔坐标系。场景的中心是点(0,0,0),也称为坐标系的原点。每当我们创建一个新对象并将其添加到我们的场景中时,它将被放置在原点,并且每当我们移动它时,是在这个坐标系中移动它。
import { Scene } from 'three';
const scene = new Scene;
- 相机(camera)
查看场景
对我们来说,最重要的投影类型是透视投影,它旨在匹配我们的眼睛看待世界的方式。要使用透视投影查看场景,我们使用 PerspectiveCamera。
import { PerspectiveCamera } from 'three';
const fov = 35; //视野: 相机的视野有多宽,以度为单位。
const aspect = container.clientWidth / container.clientHeight; //纵横比: 场景的宽度与高度的比率。
const near = 0.1; // 近剪裁平面:任何比这更靠近相机的东西都是不可见的。
const far = 100; // 远剪裁平面:任何比这更远离相机的东西都是不可见的。
const camera = new PerspectiveCamera(fov, aspect, near, far);
这四个参数一起用于创建一个有边界的空间区域,称之为视锥体。
我们传递给构造函数的四个参数PerspectiveCamera分别创建了截锥体的一个方面:
- 视野定义了平截头体扩展的角度。小视场会产生窄截锥体,而宽视场会产生宽截锥体。
- 纵横比将平截头体与场景容器元素相匹配。当我们将其设置为容器的宽度除以其高度时,我们确保可以将类似矩形的平截头体完美的扩展到容器中。如果我们弄错了这个值,场景看起来会伸展和模糊。
- 近剪切平面定义了平截头体的小端(最接近相机的点)。
- 远剪裁平面定义了平截头体的大端(距相机最远)。
渲染器不会绘制场景中不在平截头体内的任何对象。如果一个物体部分在平截头体体内部,部分在平截头体外部,则外部的部分将被切掉(剪掉)。
- 渲染器(renderer)
渲染
渲染器,通过相机观察并将看到的东西非常快的绘制到一个canvas中去。 我们把这个过程叫做渲染,得到的图片就是一个渲染效果图。使用 WebGLRenderer —— 它使用 WebGL2来渲染我们的场景 (如果可用),如果不可用则回退到WebGL V1。
import { WebGLRenderer } from 'three';
const renderer = new WebGLRenderer();
小结
场景、相机和渲染器一起为我们提供了 three.js 应用程序的基本脚手架。
网格 Mesh
网格是 3D 计算机图形学中最常见的可见对象,用于显示各种 3D 对象——猫、狗、人类、树木、建筑物、花卉和山脉都可以使用网格来表示。
import { Mesh } from 'three';
const mesh = new Mesh(geometry, material);
Mesh构造函数有两个参数:几何和材质。在创建网格之前,我们需要创建这两个。
几何体
几何体定义了网格的形状。
需要一个立方缓冲几何体,将使用 BoxGeometry。
import { BoxGeometry } from 'three';
const geometry = new BoxGeometry(2, 2, 2);
材料
几何体定义了形状,材质定义了网格表面的外观。
使用 MeshBasicMaterial ,这是可用的最简单的材质,更重要的是,不需在场景中添加任何灯光。
import { MeshBasicMaterial } from 'three';
const material = new MeshBasicMaterial();
开始编写
- 初始设置
从three引入相关的类,并获取容器。
在main.js添加内容如下:
import {BoxGeometry, // 立方缓冲几何体Color, // 颜色Mesh, // 网格MeshBasicMaterial, // 基础网格材质Scene, // 场景PerspectiveCamera, // 透视相机WebGLRenderer, // WebGL Render 用WebGL渲染出你精心制作的场景。
} from "three";
const container = document.querySelector("#scene-container");
- 创建场景
main.js: 创建场景并将背景设置为天蓝色
const scene = new Scene();
scene.background = new Color("skyblue");
- 创建相机
main.js: 创建相机并设置相机位置
// 创建相机
const fov = 35; // 视野: 相机的视野有多宽,以度为单位。
const aspect = container.clientWidth / container.clientHeight; // 纵横比: 场景的宽度与高度的比率。
const near = 0.1; // 近剪裁平面:任何比这更靠近相机的东西都是不可见的。
const far = 100; // 远剪裁平面:任何比这更远离相机的东西都是不可见的。
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10); // 设置相机位置
- 创建可见对象
main.js:创建几何体
// 创建几何体
const geometry = new BoxGeometry(2, 2, 2);
main.js:创建材质
// 创建材质
const material = new MeshBasicMaterial();
此材质还会忽略场景中的任何灯光,并根据材质的颜色和其他设置为网格着色(阴影)。
如果使用除MeshBasicMaterial之外的几乎任何其他材质类型,将无法看到任何东西,因为场景完全处于黑暗中。就像在现实世界中一样,我们通常需要光线才能看到场景中的事物。MeshBasicMaterial是该规则的一个例外。
main.js:创建网格
// 创建网格
const cube = new Mesh(geometry, material);
main.js: 将网格添加到场景中
// 将网格添加到场景中
scene.add(cube);
- 创建渲染器
main.js: 创建渲染器,设置渲染器大小,设置设备像素大小,将canvas元素添加到我们的页面
// 创建渲染器
const renderer = new WebGLRenderer();
// 设置渲染器大小
renderer.setSize(container.clientWidth, container.clientHeight);
// 设置设备像素大小 这是防止 HiDPI 显示器模糊所必需的 (也称为视网膜显示器)。
renderer.setPixelRatio(window.devicePixelRatio);
// 将canvas元素添加到我们的页面
container.appendChild(renderer.domElement);
- 渲染场景
main.js: 渲染场景
// 渲染场景
renderer.render(scene, camera);
总结
至此已经全部完成。你好,正方体!如果出现理解偏差或有其他更佳的学习方法,请大家不吝赐教,在评论区给予指正或分享您的宝贵建议,我将不胜感激。
主要文献
three.js官网
《discoverthreejs》