写点什么

Three.js - 走进 3D 的奇妙世界(上)

  • 2020-02-06
  • 本文字数:3142 字

    阅读完需:约 10 分钟

Three.js - 走进3D的奇妙世界(上)

本文将通过 Three.js 的介绍及示例带我们走进 3D 的奇妙世界。

文章来源:宜信技术学院 & 宜信支付结算团队技术分享第 6 期-支付结算部支付研发团队前端研发高级工程师-刘琳《three.js - 走进 3D 的奇妙世界》

分享者:宜信支付结算部支付研发团队前端研发高级工程师-刘琳


随着人们对用户体验越来越重视,Web 开发已经不满足于 2D 效果的实现,而把目标放到了更加炫酷的 3D 效果上。Three.js 是用于实现 web 端 3D 效果的 JS 库,它的出现让 3D 应用开发更简单,本文将通过 Three.js 的介绍及示例带我们走进 3D 的奇妙世界。

一、Three.js 相关概念

1.1 Three.JS

Three.JS 是基于 WebGL 的 Javascript 开源框架,简言之,就是能够实现 3D 效果的 JS 库。

1.2 WebGL

WebGL 是一种 Javascript 的 3D 图形接口,把 JavaScript 和 OpenGL ES 2.0 结合在一起。

1.3 OpenGL

OpenGL 是开放式图形标准,跨编程语言、跨平台,Javascript、Java 、C、C++ 、 python 等都能支持 OpenG ,OpenGL 的 Javascript 实现就是 WebGL,另外很多 CAD 制图软件都采用这种标准。OpenGL ES 2.0 是 OpenGL 的子集,针对手机、游戏主机等嵌入式设备而设计。

1.4 Canvas

Canvas 是 HTML5 的画布元素,在使用 Canvas 时,需要用到 Canvas 的上下文,可以用 2D 上下文绘制二维的图像,也可以使用 3D 上下文绘制三维的图像,其中 3D 上下文就是指 WebGL。


1574760602091095648.png

二、Three.js 应用场景

利用 Three.JS 可以制作出很多酷炫的 3D 动画,并且 Three.js 还可以通过鼠标、键盘、拖拽等事件形成交互,在页面上增加一些 3D 动画和 3D 交互可以产生更好的用户体验。


通过 Three.JS 可以实现全景视图,这些全景视图应用在房产、家装行业能够带来更直观的视觉体验。在电商行业利用 Three.JS 可以实现产品的 3D 效果,这样用户就可以 360 度全方位地观察商品了,给用户带来更好的购物体验。另外,使用 Three.JS 还可以制作类似微信跳一跳那样的小游戏。随着技术的发展、基础网络的建设,web3D 技术还能得到更广泛的应用。


1574761659639065918.png

三、主要组件

在 Three.js 中,有了场景(scene)、相机(camera)和渲染器(renderer) 这 3 个组建才能将物体渲染到网页中去。


1)场景


场景是一个容器,可以看做摄影的房间,在房间中可以布置背景、摆放拍摄的物品、添加灯光设备等。


2)相机


相机是用来拍摄的工具,通过控制相机的位置和方向可以获取不同角度的图像。


3)渲染器


渲染器利用场景和相机进行渲染,渲染过程好比摄影师拍摄图像,如果只渲染一次就是静态的图像,如果连续渲染就能得到动态的画面。在 JS 中可以使用 requestAnimationFrame 实现高效的连续渲染。

3.1 常用相机

1574761667808077881.png


1)透视相机


透视相机模拟的效果与人眼看到的景象最接近,在 3D 场景中也使用得最普遍,这种相机最大的特点就是近大远小,同样大小的物体离相机近的在画面上显得大,离相机远的物体在画面上显得小。透视相机的视锥体如上图左侧所示,从近端面到远端面构成的区域内的物体才能显示在图像上。


透视相机构造器


PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )


  • fov — 摄像机视锥体垂直视野角度

  • aspect — 摄像机视锥体长宽比

  • near — 摄像机视锥体近端面

  • far — 摄像机视锥体远端面


2)正交相机


使用正交相机时无论物体距离相机远或者近,在最终渲染的图片中物体的大小都保持不变。正交相机的视锥体如上图右侧所示,和透视相机一样,从近端面到远端面构成的区域内的物体才能显示在图像上。


正交相机构造器


OrthographicCamera( left : Number, right : Number, top : Number, bottom : Number, near : Number, far : Number )


  • left — 摄像机视锥体左侧面

  • right — 摄像机视锥体右侧面

  • top — 摄像机视锥体上侧面

  • bottom — 摄像机视锥体下侧面

  • near — 摄像机视锥体近端面

  • far — 摄像机视锥体远端面

3.2 坐标系

在场景中,可以放物品、相机、灯光,这些东西放置到什么位置就需要使用坐标系。Three.JS 使用右手坐标系,这源于 OpenGL 默认情况下,也是右手坐标系。从初中、高中到大学的课堂上,教材中所涉及的几何基本都是右手坐标系。


1574761676237007220.png


上图右侧就是右手坐标系,五指并拢手指放平,指尖指向 x 轴的正方向,然后把四个手指垂直弯曲大拇指分开,并拢的四指指向 y 轴的正方向,大拇指指向的就是 Z 轴的正方向。


在 Three.JS 中提供了坐标轴工具(THREE.AxesHelper),在场景中添加坐标轴后,画面会出现 3 条垂直相交的直线,红色表示 x 轴,绿色表示 y 轴,蓝色表示 z 轴(如下图所示)。


1574761682608065195.png

3.3 示例代码

/* 场景 */var scene = new THREE.Scene();scene.add(new THREE.AxesHelper(10)); // 添加坐标轴辅助线
/* 几何体 */// 这是自定义的创建几何体方法,如果创建几何体后续会介绍var kleinGeom = createKleinGeom(); scene.add(kleinGeom); // 场景中添加几何体
/* 相机 */var camera = new THREE.PerspectiveCamera(45, width/height, 1, 100);camera.position.set(5,10,25); // 设置相机的位置camera.lookAt(new THREE.Vector3(0, 0, 0)); // 相机看向原点
/* 渲染器 */var renderer = new THREE.WebGLRenderer({antialias:true});renderer.setSize(width, height);// 将canvas元素添加到bodydocument.body.appendChild(renderer.domElement);// 进行渲染renderer.render(scene, camera);
复制代码

四、几何体

计算机内的 3D 世界是由点组成,两个点能够组成一条直线,三个不在一条直线上的点就能够组成一个三角形面,无数三角形面就能够组成各种形状的几何体。


1574761690685071923.png


以创建一个简单的立方体为例,创建简单的立方体需要添加 8 个顶点和 12 个三角形的面,创建顶点时需要指定顶点在坐标系中的位置,添加面的时候需要指定构成面的三个顶点的序号,第一个添加的顶点序号为 0,第二个添加的顶点序号为 1…


创建立方体的代码如下:


var geometry = new THREE.Geometry();
// 添加8个顶点geometry.vertices.push(new THREE.Vector3(1, 1, 1));geometry.vertices.push(new THREE.Vector3(1, 1, -1));geometry.vertices.push(new THREE.Vector3(1, -1, 1));geometry.vertices.push(new THREE.Vector3(1, -1, -1));geometry.vertices.push(new THREE.Vector3(-1, 1, -1));geometry.vertices.push(new THREE.Vector3(-1, 1, 1));geometry.vertices.push(new THREE.Vector3(-1, -1, -1));geometry.vertices.push(new THREE.Vector3(-1, -1, 1));
// 添加12个三角形的面geometry.faces.push(new THREE.Face3(0, 2, 1));geometry.faces.push(new THREE.Face3(2, 3, 1));geometry.faces.push(new THREE.Face3(4, 6, 5));geometry.faces.push(new THREE.Face3(6, 7, 5));geometry.faces.push(new THREE.Face3(4, 5, 1));geometry.faces.push(new THREE.Face3(5, 0, 1));geometry.faces.push(new THREE.Face3(7, 6, 2));geometry.faces.push(new THREE.Face3(6, 3, 2));geometry.faces.push(new THREE.Face3(5, 7, 0));geometry.faces.push(new THREE.Face3(7, 2, 0));geometry.faces.push(new THREE.Face3(1, 3, 4));geometry.faces.push(new THREE.Face3(3, 6, 4));
复制代码

4.1 正面和反面

创建几何体的三角形面时,指定了构成面的三个顶点,如: new THREE.Face3(0, 2, 1),如果把顶点的顺序改成 0,1,2 会有区别吗?


通过下图可以看到,按照 0,2,1 添加顶点是顺时针方向的,而按 0,1,2 添加顶点则是逆时针方向的,通过添加顶点的方向就可以判断当前看到的面是正面还是反面,如果顶点是逆时针方向添加,当前看到的面是正面,如果顶点是顺时针方向添加,则当前面为反面。


下图所看到的面就是反面。如果不好记,可以使用右手沿顶点添加的方向握住,大拇指所在的面就是正面,很像我们上学时学的电磁感应定律。


1574761698095080964.png


本文转载自宜信技术学院。


原文链接:http://college.creditease.cn/detail/328


2020-02-06 10:342600

评论

发布
暂无评论
发现更多内容
Three.js - 走进3D的奇妙世界(上)_行业深度_刘琳_InfoQ精选文章