导语
随着软硬件的发展,在PC和移动端浏览器上进行web 3D开发的条件已经基本成熟了,出现了不少js 3D库,Threejs是js 3D库中的佼佼者。国内也有企业开始做一些应用尝试,某宝2016年双11就用ThreeJS做了一个比较酷炫的3D宣传页面刷爆了朋友圈。
下图是用Threejs绘制的一个3D立方体动画的截图,在这个demo里,立方体会动态的旋转,threeJS 30行代码就可以完成这么一个demo。Threejs让没有丰富3D编程经验的web前端开发人员,也可以快速上手开发web 3D应用。
Threejs是什么
官网对Threejs的介绍非常简单:“Javascript 3D library”。openGL是一个跨平台3D/2D的绘图标准,WebGL则是openGL在浏览器上的一个实现。web前端开发人员可以直接用WebGL接口进行编程,但WebGL只是非常基础的绘图API,需要编程人员有很多的数学知识、绘图知识才能完成3D编程任务,而且代码量巨大。Threejs对WebGL进行了封装,让前端开发人员在不需要掌握很多数学知识和绘图知识的情况下,也能够轻松进行web 3D开发,降低了门槛,同时大大提升了效率。
Threejs应用场景举例
1、web 3D游戏
2、3D模型展示
下图的例子中,用户可以跟浏览器交互,通过鼠标操作360度查看汽车,点击车门进入到车内,查看车内立体视图,如同身临其境。
3、数据可视化
4、web vr
Threejs的基本要素
3D编程跟2D编程有较大不同,因此需要掌握一些3D编程的基本概念。Threejs的基本要素包括以下几个方面:场景、相机、光、物体。
场景:是一个三维空间,所有物品的容器。可以把场景想象成一个空房间,接下来我们会往房间里面放要呈现的物体、相机、光源。
相机:Threejs必须要有往场景中添加一个相机,相机用来确定观察位置、方向、角度,相机看到的内容,就是我们最终在屏幕上看到的内容。在程序运行过程中,可以调整相机的位置、方向、角度。想象一下,在房间里放了一个摄像机,你不在房间里面,但可以远程控制相机移动,摄像机传给远程电脑上展示出来的画面,就是Threejs在屏幕上呈现的画面。
光:假如没有光,摄像机看不到任何东西,因此需要往场景中添加光源。为了跟真实世界更加接近,Threejs支持模拟不同光源,展现不同光照效果,有点光源、平行光、聚光灯、环境光等。
物体:有了场景、相机、光,就可以往场景中放物体了,在Threejs中,物体由形状和材质两部分组成,形状决定物品的轮廓,材质则是物体的材料和质感。
渲染
Threejs绘制的东西,最终需要在屏幕一块矩形画布上显示出来。为了实现动画效果,我们需要有一个重绘机制。由于视神经元的反应速度问题,图像消失后仍然会在人眼残留1/24秒,只要一秒内绘制的帧数超过24就能实现流畅的动画效果。Threejs提供了重绘接口,我们有两种方式去调用接口实现重绘。一种是setInterval,以固定的时间间隔去调用,可以用于我们对渲染帧数要求比较高的场景,但事实上由于Javascript是单线程的,这种方式并不能100%保证相同的时间间隔调用,如果浏览器繁忙可能会导致setInterval的延迟执行;第二种方式是requestAnimationFrame,让浏览器自行根据当前cpu负载等情况决定何时重绘,达到最佳帧率。
位置
为了方便描述位置,引入了坐标系,Threejs使用的是右手坐标系,如下图所示。坐标系的原点位于渲染画布的几何中心。我们对物体的位置的描述,也是指物体的几何中心的位置。
相机
相机有正交投影相机和透视投影相机两种。透视投影跟人眼看到的世界是一样的,近大远小;正交投影则远近都是一样的大小,三维空间中平行的线,投影到二维空间也一定是平行的。大部分场景都适合使用透视投影相机,因为跟真实世界的观测效果一样;在制图、建模等场景适合使用正交投影相机,方便观察模型之间的大小比例。
Threejs中的相机跟真实世界的相机不完全一样,这里相机的可见区域是一个立方体,称为相机的示景体。
正交投影相机
示景体是一个长方体,由6个参数确定:THREE.OrthographicCamera(left, right, top, bottom, near, far),这6个参数规定了相机示景体的左、右、上、下、前、后六个面的位置。
透视投影相机
示景体是一个梯形体,由四个参数确定:THREE.PerspectiveCamera(fov, aspect, near, far)
fov是相机在竖直方向的张角,aspect则是宽高比,即width/height,通常设为画布的宽高比,near和far分别是近平面和远平面与相机的距离。
投影的大小
考虑一种比较简单的场景,相机示景体的远近平面和坐标系中的xy平面平行,从而示景体远近平面上的内容刚好可以垂直投影到画布上,并且示景体中与xy平面平行的任何一个平面,投影到画布上刚好等于画布大小。假如透视投影相机的近平面的大小为axb,远平面大小为2ax2b,则一张axb大小的纸放在近平面上,投影到画布时刚好铺满整张画布;放到远平面上则只能占据画布面积的1/4(远平面的面积是近平面的4倍)。正是因为透视投影相机的示景体近小远大,才会导致同样一个物品放在不同位置显示出近大远小的效果。而正交投影相机因为远近平面大小一样,所以同一个物品距离相机的远近不影响物体在画布上投影展示的大小。
物体
物体由几何形状(Geometry)和材质(Material)组成。同样的几何形状,不同材质构成了不同物体,比如球状,有篮球、玻璃球、水晶球等。
形状
Threejs提供了一些常见的几何形状,有三维的也有二维的,三维的比如长方体、球体、圆柱体、环等,二维的比如长方形、圆形、扇形等。如果默认提供的形状不能满足需求,也可以自定义,通过定义顶点和顶点之间的连线绘制自定义几何形状,更复杂的模型还可以用建模软件建模后导入。
计算机是如何绘制几何形状的呢?我们知道,计算机只能绘制直线,那么曲线和3D形状如何绘制出来呢?
1、绘制圆形。如下图所示,通过绘制多边形实现近似的圆形效果,当多边形的边数足够多的时候,两条边之间的过渡就显得平滑,多边形看起来就足够圆了。
2、绘制3D模型。常用的做法是用三角形组成的网格来模拟,如下图所示,用足够多的三角形时,兔子的身体看起来就足够平滑,跟真实兔子比较接近。著名的斯坦福兔子模型用了69451个三角形。
材质
Threejs提供了几种比较有代表性的材质,常用的有漫反射、镜面反射两种材质,还可以引入外部图片,贴到物体表面,称为纹理贴图。
外部模型
现实世界丰富多彩,不是Threejs的几种默认几何形状和材质所能表达的,实际运用中,很多时候需要用到外部模型,通过3D建模软件构建物体的三维模型并导出模型文件,Threejs导入模型文件进行使用。
光照
光源主要是以下几种:1)、环境光,所有角度看到的亮度一样,通常用来为整个场景指定一个基础亮度,没有明确光源位置;2)、点光源,一个点发出的光源,照到不同物体表面的亮度线性递减;3)、平行光,亮度与光源和物体之间的距离无关,只与平行光的角度和物体所在平面有关;4)、聚光灯,投射出的是类似圆锥形的光线。
小结
本文对Threejs编程做了一下简单介绍,目的是让读者对Threejs编程有个基本认识。纸上得来终觉浅,绝知此事要躬行!建议到Threejs官网首页看看那些有趣的demo,着手写一些简单的demo进行实践。目前web 3D应用因为浏览器渲染性能、模型体积过大等原因,并没有大规模使用起来,只限于在品牌宣传等部分领域尝试使用。我刚好经历过浏览器2D数据可视化绘图由flash向JS转变的过程(2012年前后),相信随着软硬件性能的提升和网络速度的提升,web 3D应用也会慢慢的推广使用起来。