从 0 开始学习 Three.js : 场景搭建

什么是三维可视化页面

我们常见的网页,比如掘金、知乎、微博等都是平面的,只有长宽两个维度。三维可视化页面增加了一个新的维度--深度,利用 HTML5 的 WebGL 接口,通过 JavaScript 编程, 在网页中展示三维模型。

三维可视化页面的魅力

三维模型相比文字描述或者二维图片,更加符合日常生活中人们观察世界的感受,能给用户提供浸入式的产品体验。一些复杂的模型及数据,通过三维可视化的手段,也能更加准确完整的传递所要表达的信息。

一个精彩的 Demo:Solar-System-Motion-Simulator

什么是 Three.js

Three.js 是一个 JavaScript 3D 库,它将底层的 WebGL 进行了封装。简单调用 Three.js 的接口,就可以快速方便的构建三维可视化页面。

我相信你肯定听说过 WebGL,也听说过 canvas。如果没有听过这两个名词,可以去 MDN 简单了解一下,不熟悉 WebGL 和 canvas 不会对学习 Three.js 产生任何阻碍。

同样的,不了解图形学的知识也不会阻碍你使用 Three.js 。

学习 Three.js 需要什么知识

什么都不需要。准确的说,只要你能看懂中文(因为本文是中文写作的),还记得三角函数的知识(不记得你也可以查),会一点点 JavaScript(因为我也只会一点点 JavaScript)就够了,不需要了解 Webpack、sass 、vue、react 等工具和框架的任何知识。

开始学习吧

我知道你已经迫不及待地想要敲上几行代码,一览 Three.js 的魅力了。但在这之前,我们先要弄明白两个关键问题:

  • 三维场景有什么
  • 如何将三维场景展示在二维平面中

想像一下拍摄上图时的样子:我们先要找到一个拍摄的场地,另外还得有一台相机。然后准备一些棋子、一个棋盘,把棋子和棋盘摆放在场地中,准备好灯光,拿起摄像机,调整好摄像机的位子和角度。按下快门。

三维可视化网页的创建和这个步骤完全重合。

let scene = new THREE.Scene();//准备拍摄的场地
let camera = new THREE.PerspectiveCamera(fov,aspectRatio,nearPlane,farPlane);//买了个相机
camera.position.set(x,y,z)//把照相机放到(x,y,z)处
camera.lookAt(new THREE.Vector3(0,0,0)//照相机看向坐标(0,0,0)
let light = new THREE.PointLight( 0xff0000, 1, 100 );//Light 在有些时候并不是必须的。
let chessman = createChessman();//准备好棋子
chessman.position(a,b,c)//把棋子放到坐标(x,y,z)处
let chessboard = createChessboard();//准备好棋盘
chessboard.position(e,d,f)//把棋子放到坐标(e,d,f)处
scene.add(chessman);//把棋子放到空间中
scene.add(chessboard);//把棋盘放到空间中
let renderer = new THREE.WebGLRenderer();//一个渲染器,不要深究于此
renderer.render(scene,camera);//按下快门,咔嚓~拍照完成!
复制代码

上面的代码中肯定有许多你不明白的地方,不要担心,现在只需要感性的认识到搭建一个 Three.js 场景和现实生活中照相的步骤是一样的就可以了。

Three.js 的 hello world

学习编程的第一步都是 「Hello World」。Three.js 的 「Hello World」是在网页中生成一个立方体。

现在,打开你的编辑器,一步一步跟着做吧。

承载场景的元素
<script src="three.js"><script>
<div id="container"></div>
复制代码

先引入 three.js 并在 HTML 中创建一个承载场景的元素#container

Three.js 下载到本地,或者使用 CDN (https://cdn.bootcss.com/three.js/90/three.js) 引入。

如果你熟悉 NPM 等工具的话,可以参考这个import-via-module

生成场景
let scene = new THREE.Scene();
复制代码

一行代码生成 Three.js 的场景。

生成照相机

Three.js 中的照相机有四种:CubeCamera、OrthographicCamera、PerspectiveCamera 和 StereoCamera。 其中常用的是 PerspectiveCamera 和 OrthographicCamera。

OrthographicCamera 是正交相机。

正交相机拍摄的物体不会被缩放,平行线永远保持平行。多用在物理建模等需要精确尺寸的模型中。

PerspectiveCamera 是投影相机。

投影相机和人眼一样有近大远小的效果,平行线不一定平行。多用在模拟现实场景的模型中。(本文中的模型都会采用投影相机)。

关注一下 PerspectiveCamera 的四个参数:fov、aspect、near、far。

fov 是上图中的 θ ,常用的数字是45 和 60。

aspect 是宽长比,多用#container的比例。

near 是离摄影机近的面到摄影机的距离。一般为1等很小的数字。

far 是离摄影机远的面到摄影机的距离。一般设置为 1000、10000等较大的数字。

通过这4个参数,就可以确定一个四棱台。在四棱台内的物体会被渲染,而超出四棱台范围内的物体就被裁剪掉了。

let camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);
复制代码
three.js 的坐标系

在生成 camera 的代码中,你应该注意到 near 被设置为了1,far 被设置为了1000。这并不是一个错误,千万不要写成 1px,1000px。three.js 的坐标系中表示的距离并不是真实的距离,而是一种比例关系,1和1000表示的是 far 比 near 距 camera 远1000 倍。

three.js 的坐标系符合右手定则。

可以按照上图去比一下试试。

我是看着电脑屏幕记住的:电脑屏幕向右是 x 正半轴,电脑屏幕向上是 y 正半轴,垂直屏幕向外是 z 正半轴。

还有一点要记住的是,新生成的任何物体,默认初始位置都是几何中心位于(0,0,0)。camera 默认看向 z 轴负半轴。

camera.position.set(0, 0, 10);
复制代码

把 camera 往 x 轴正半轴挪一点。不然 camera 默认在(0,0,0),看向 z 轴负半轴。是拍不到位于 (0,0,0) 的物体的。

先搞个渲染器

渲染器这一块比较复杂,还好 three.js 做了十分彻底的封装。我们只需要用就 ok 了。在 Three.js 中,你只会用到 WebGLRenderer

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
复制代码

把 renderer 的大小设置为与 scene 一致是一个不错的选择。 如果你在 MDN 查了 WebGL 相关的资料的话,一定知道需要在<canvas>元素中使用 WebGL。

可以借由 Three.js 在 DOM 中引入<canvas>,

document.getElementById('container').appendChild(renderer.domElement);
复制代码

也可以显式的在 HTML 页面插入<canvas> 我比较喜欢前一种,简单一些。

准备就绪,开始产生立方体

如果前面的步骤都没问题了,生成一个立方体就是一瞬间的事情。

let cubeGeometry = new THREE.BoxGeometry(1,1,1);
let cubeMaterial = new THREE.MeshBasicMaterial({
    color:0xff0000;
});
let cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube);
renderer.render(scene,camera);
复制代码

super fast !!!

注意 .BoxGeometry,你可能会在较老的资料上看到是 .CubeGeometry,那是很久以前的事情了。现在生成长方体/立方体用 .BoxGeometry

在 Three.js 中生成一个物体只需要三步:

  1. 设置物体的形状
  2. 设置物体的材质
  3. 把形状和材质结合起来

最后要把生成的物体通过 scene的add()方法添加到 scene 中。renderer 直接渲染 scene 和 camera 就 OK 了。

至于什么是形状,什么是材质,如何把形状和材质结合起来,又是很长一部分内容。我会放在其它部分详细讲解。


一些可能遇到的问题

1.页面没有效果。检查浏览器是否支持 WebGL

在 JS 文件中引入

if (Detector.webgl) {
    // Initiate function or other initializations here
    animate();
} else {
    var warning = Detector.getWebGLErrorMessage();
    document.getElementById('container').appendChild(warning);
}
复制代码

2.页面没有效果。检查浏览器console 是否报错。

3.页面没有效果。检查 Three.js 资源是否成功引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值