全景图H5制作之--three.js

最近关注了QQ物联合深圳天文台合作推出一个“星球计划”的H5推广,里面有用到全景图,是利用three.js制作的。
转动手机在模拟的宇宙里搜寻各大行星,就是我们今天要说的基于Html5的3D全景漫游。

原图 by UIchina
关于全景漫游
而什么是全景漫游呢,全景漫游技术可以让体验者在全景图像构建的全景空间里切换视角的浏览。它是通过拍摄全景图像,再采用计算机图形图像技术构建出全景空间,让使用者能用控制浏览的方向,或左或右、或上或下观看物体或场景,仿佛身临其境一般。与传统的3D建模相比,全景漫游技术制作简单,数据量小,系统消耗低,且更有真实感。故近年来,也是VR技术的一大热门实现手法,用前面的贴图例子来个demo。而在移动端的全景漫游,更是可以绑定陀螺仪,让你更有身临其境的感觉。
原图 by UIchina

###制作原理

想要利用Three.js制作一个物体渲染到网页中去,需要构建这3个组建:场景(scene)、相机(camera)和渲染器(renderer):

(1)场景(scene)
即是画布,是所有物体object的容器。在最开始的时候对场景实例化,将之后构建的物体都添加到场景中即可。

1
2
//定义3D场景
scene = new THREE.Scene();

(2)相机(camera)
用户是通过相机Camare来查看在scene下的3d场景,在three.js里包含了正交投影照相机(Orthographic Camera)和透视投影照相机(Perspective Camera)2种,从模拟人眼看物体的方式来选,透视投影照相机更适合。如下图所示,fov是相机视角的夹角,aspect等于相机画幅比例,near和far分别是照相机到视景体最近、最远的距离,均为正值,且far应大于near。
原图 by UIchina

1
2
3
4
5
6
7
8
9
10
camera = new THREE.PerspectiveCamera(
90,//相机的视角的夹角
window.innerWidth / window.innerHight, //相机的画幅比
100,//最近焦距
1000 //最远焦距
);
//定义相机
//new THREE.RerspectiveCamera(fov,aspect,near,far);

(3)渲染器(renderer)
渲染器是用来设定渲染的结果会在页面的什么元素上面呈现,以及按什么规则来渲染。

1
2
3
renderer = new THREE.CSS3DRenderer();//定义渲染器
renderer.setSize(window.innerWidth,window.innerHeight);//设定尺寸
$("#quanjing .main").append(renderer.domElement);//将场景加入页面

在Three.js中,场景是容器,把我们星球计划的星星们放置在构建的3D场景中的不同位置;相机对着下场景拍摄,拍摄结果通过渲染器实时的绘制在我们的浏览器上。
原图 by UIchina

(4)构建宇宙并置入场景中

定义了这三大元素之后,下一步,就是构建我们的星球计划所需的宇宙了。前文有提到,全景图像可分为球面全景图、立方体全景图以及柱状全景图。
虽然球面全景图具有和人眼最接近的构建模式,但需要很多个立面才可以构建成一个球体,球面的经纬度坐标无法展开成一个平面贴图,相对于其他方案,性能消耗过高,拼接方法过于繁琐;而柱形全景图的垂直视野小,不好做顶部底部的俯仰视角。我们选定了最常见的立方图全景图来构建我们的3D场景。

立方体全景图有6个面,我们需要定义每个面贴图的背景图片,3D位置,旋转角度(默认的6个面都是朝着我们的,我们需要定义朝坐标轴的各个方向做90度的旋转,才可以搭建成一个立方体)。

原图 by UIchina

原图 by UIchina

然后添加到THREE.Object3D 的数组中,这样我们就在场景中构建好了一个3D的宇宙空间。

1
2
3
4
var object = new THREE.CSS3DObject(element);
object.position.fromArray(side.position);
object.position.fromArray(side.rotation);
cude.add(object);

这里,考虑到星空背景主要为了氛围烘托,我们将6个面的贴图减少成2个,以此缩减了资源文件的大小,如下图所示。
原图 by UIchina

(5)渲染
这里我们用的是Threejs的 实时渲染:就是需要不停的对画面进行渲染,即使画面中什么也没有改变,也需要重新渲染。其中一个重要的函数是requestAnimationFrame,这个函数就是让浏览器去执行一次参数中的函数,这样通过上面animate中调用requestAnimationFrame()函数,requestAnimationFrame()函数又让animate()再执行一次,就形成了我们通常所说的渲染循环了。
原图 by UIchina

通过上面这些步骤,我们就构建好这个3D的宇宙空间了。
原图 by UIchina

(6)构建星球放置在宇宙中
一期的星球计划中,需要增加8颗星球,为了避免画面过于拥挤,星球们被分散定位在了6个面上。之前我们定义宇宙六个面的时候给了每个面一个固定的section id,通过简单的js 我们可以往平面中加入星球的DOM结构。
原图 by UIchina

因此也可以很轻松的利用CSS给这些星球定位及增加个性的动画效果,这里要特别注意,不要增加阴影等耗内存特别大的动画效果,它们是Crash罪魁祸首。
原图 by UIchina
原图 by UIchina

(7)绑定陀螺仪

最后一步,将全景漫游绑定陀螺仪,这里涉及到需要对陀螺仪事件做个保护代码,判断机器是否支持陀螺仪。完成以上几步,既可以实现一个在移动端的全景漫游啦。
原图 by UIchina

最后,仅以此文总结在移动端构建3D全景漫游的试水总结,该尝试基本上能够满足项目的需求,但在性能优化,细节完善上还继续打磨,希望能对有兴趣的小伙伴带来一些帮助^^。

end.

Share Comments