Three.Js 实现 360 度全景浏览的简单方式

开发 前端
一般我们拍照都是拍一个方向,而全景图是拍上下左右前后 6 个方向,360 度,这样能够立体的记录所在的场景。

[[438455]]

什么是全景图?

一般我们拍照都是拍一个方向,而全景图是拍上下左右前后 6 个方向,360 度,这样能够立体的记录所在的场景。

那全景图怎么浏览呢?

全景图拍的是六个方向的图,放在一个平面看会很别扭,所以会有专门的浏览的工具,根据视角的改变来切换看到的内容,这样就能 360 度的还原拍照的场景。

用 Three.js 做这样的一个全景图浏览工具,是再简单不过的事情,只需要几行代码,但却很有用。

那我们就来学一下 Three.js 怎么做全景图浏览吧。

Three.js 基础回顾

我们简单回顾下 Three.js 的基础:

Three.js 是通过场景 Scene 来管理 3D 场景中的各种物体的,有一个三维坐标系,每个物体放在不同的位置,然后在某个位置放置相机,来观察 Scene 中的各种物体,看到的内容就是二维的,通过渲染器 Renderer 渲染出来就行。这就是 Three.js 的 3D 场景的创建和渲染成 2D 的流程。

简单回顾了下基础,那全景图改怎么浏览呢?

全景图浏览的原理

全景图是六个方向的照片,我们可以在 3D 的场景中放一个立方体,六个面贴上不同方向的图,相机放在其中,转动相机就可以看到不同方向的内容。这也是为什么全景图浏览也叫天空盒,因为就是通过立方体贴图的方式实现的。

当然,也可以用球体来做,直接贴上一个大的全景图,相机放在中间,转动相机也可以看到不同方向的内容。

那这么说做全景图浏览需要先创建个立方体或者球体喽?

其实不用,场景 Scene 是可以设置背景的纹理的,我们可以设置成立方体纹理 CubeTexture,也就是 6 个面的图片,这样转动相机,就能看到场景 Scene 的不同方向的内容。根本不用单独创建立方体或球体。

设置个纹理也就几行代码的事情,我们来写下代码。

Three.js 实现全景图浏览

我们创建 3D 场景 Scene:

  1. const scene = new THREE.Scene(); 

然后设置它的背景,用立方体的纹理来设置,需要分别指定左右上下前后的 6 个方向的图:

  1. let urls = [ 
  2.     './img/home.left.jpg'
  3.     './img/home.right.jpg'
  4.     './img/home.top.jpg'
  5.     './img/home.bottom.jpg'
  6.     './img/home.front.jpg'
  7.     './img/home.back.jpg' 
  8. ]; 
  9. let cubeTexture = new THREE.CubeTextureLoader().load(urls); 
  10. scene.background = cubeTexture; 

这样整个背景就是一个全景图,就这么几行代码。

当然,我们还要设置下相机位置,这里用透视相机就行,它的特点是从一个点去看 3D 场景,看到的内容是近大远小的。

  1. const width = window.innerWidth; 
  2. const height = window.innerHeight; 
  3. const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000); 
  4.  
  5. camera.position.set(0,0, 100); 
  6. camera.lookAt(scene.position); 

需要设置看到的角度,这里设置了 45 度,看到内容的宽高比,这里用窗口宽高比,再就是远近范围,这个设置范围大一点就行。

相机位置设置在了 z 轴 100 的位置,这样看 z 为 0 的位置就是从正面去看的,可以感受下这个看的方向。

有了 3D 的 Scene,设置好了相机,就可以用 Renderer 把它渲染出来了。

  1. const renderer = new THREE.WebGLRenderer(); 
  2. renderer.setSize(width, height); 
  3. document.body.appendChild(renderer.domElement) 
  4.  
  5. function render() { 
  6.     renderer.render(scene, camera); 
  7.     requestAnimationFrame(render); 
  8.  
  9. render(); 

我们用 requestAnimationFrame 来一帧帧的调用 renderer 渲染。

当然,还要加上鼠标控制,可以通过鼠标的拖动方向来改变相机看到的角度,这个用 Three.js 提供的 Controls 就行,不用自己写。

我们需要 360 度的看,用 OrbitsControls 来做交互就行,他叫轨道控制器,也就是卫星绕地球的那种轨道的感觉。

  1. const controls = new THREE.OrbitControls(camera); 

OrbitControls 参数是 camera,因为它就是通过改变 camera 位置实现的。

至此,我们就实现了全景图的浏览。来看下效果:

全部代码上传了 github:https://github.com/QuarkGluonPlasma/threejs-exercize

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <title>全景图</title> 
  6.     <style> 
  7.         body { 
  8.             margin: 0; 
  9.             overflow: hidden; 
  10.         } 
  11.     </style> 
  12.     <script src="./js/three.js"></script> 
  13.     <script src="./js/OrbitControls.js"></script> 
  14. </head> 
  15. <body> 
  16. <script> 
  17.     const width = window.innerWidth; 
  18.     const height = window.innerHeight; 
  19.     const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000); 
  20.  
  21.     const scene = new THREE.Scene(); 
  22.     const renderer = new THREE.WebGLRenderer(); 
  23.  
  24.     camera.position.set(0,0, 100); 
  25.     camera.lookAt(scene.position); 
  26.  
  27.     renderer.setSize(width, height); 
  28.     document.body.appendChild(renderer.domElement) 
  29.  
  30.     function create() { 
  31.         let urls = [ 
  32.             './img/home.left.jpg'
  33.             './img/home.right.jpg'
  34.             './img/home.top.jpg'
  35.             './img/home.bottom.jpg'
  36.             './img/home.front.jpg'
  37.             './img/home.back.jpg' 
  38.         ]; 
  39.         let cubeTexture = new THREE.CubeTextureLoader().load(urls); 
  40.         scene.background = cubeTexture; 
  41.     } 
  42.  
  43.     function render() { 
  44.         renderer.render(scene, camera); 
  45.         requestAnimationFrame(render); 
  46.     } 
  47.  
  48.     create(); 
  49.     render(); 
  50.     const controls = new THREE.OrbitControls(camera); 
  51.  
  52. </script> 
  53. </body> 
  54. </html> 

 

 

 

 

 

 

 

 

 

 

 

 

 

一共也没几行代码。

我们来做下小结:

全景图浏览不用创建立方体或者球体,直接给场景(Scene)设置立方体纹理(CubeTexture)的背景就可以了,贴上 6 张图。之后设置下相机(Camera)位置,用渲染器(Renderer)一帧帧渲染出来,还要加上轨道控制器来支持拖拽改变相机位置。

主要的逻辑讲完了,但还有一个支线剧情要讲:6 张图是怎么来的?

全景图转 6 张贴图

全景图网上能搜到很多,我们手机的相机也都能拍全景图,但是它是一张完整的大图,而立方体纹理要加载 6 张不同方向的图,如果把全景图裁切成 6 张图呢?

这个有工具来做,我是用的 PTGui (试用版)来做的裁切。

官网有下载地址:https://www.ptgui.com/download.html?ps=main

点击 tools 里面的 convert to cube faces,会打开一个窗口,然后选择一个全景图,设置导出的格式,点导出就行了,就能生成上下左右前后的六个方向的图。

总结

一般的照片只是一个方向的画面,而全景图是上下左右前后 360 度的画面,它能立体的记录拍照位置的场景。

全景图需要专门的工具来浏览,我们可以用 Three.js 来实现。原理就是通过立方体贴 6 张图(也叫天空盒),或者通过球体贴一张大图,把相机设置在中间,转动相机就可以看到不同方向的画面。

其实实现全景图浏览更简单的方式是直接给 Scene 设置立方体纹理,不用再单独创建立方体或球体,用 CubeTextureLoader 加载六张图,设置到 Scene 的背景上就行。

还要设置下相机,加上轨道控制器,通过渲染器一帧帧的渲染出来,这样就实现了全景图浏览的功能。

至于那六张贴图,通过 PTGui 或者类似的工具就可以裁切出来。

全景图浏览一共也没几行代码,但是这个功能还是很有用的。如果你会拍全景图,那就更棒了,可以把生活中一些场景立体的记录下来,自己写一个工具来浏览。

 

责任编辑:武晓燕 来源: 神光的编程秘籍
相关推荐

2022-07-15 13:09:33

Three.js前端

2019-11-29 09:30:37

Three.js3D前端

2017-05-08 11:41:37

WebGLThree.js

2021-11-22 06:14:45

Three.js3D 渲染花瓣雨

2021-04-23 16:40:49

Three.js前端代码

2021-12-14 11:44:37

可视化Three.js 信息

2022-01-16 19:23:25

Three.js粒子动画群星送福

2021-11-27 10:42:01

Three.js3D可视化AudioContex

2022-05-27 14:55:34

canvas画布鸿蒙

2022-03-07 09:20:00

JavaScripThree.jsNFT

2010-08-23 17:57:43

交换机配置dhcp

2011-02-17 11:19:24

Linux Live

2022-07-08 10:39:09

Three.js元宇宙VR

2016-09-21 14:24:37

3D全景浏览器浏览器

2020-11-23 07:43:18

JS

2012-10-17 14:25:29

HTML5WebGLWeb

2019-09-19 14:44:18

LinuxWindows操作系统

2011-10-12 14:54:06

360度辅助系统

2021-11-23 22:50:14

.js 3D几何体

2021-12-07 13:44:43

Three.js3D可视化3D 游戏
点赞
收藏

51CTO技术栈公众号