Three-js 實現 360 度全景瀏覽的最簡單方式
什麼是全景圖?
一般我們拍照都是拍一個方向,而全景圖是拍上下左右前後 6 個方向,360 度,這樣能夠立體的記錄所在的場景。
那全景圖怎麼瀏覽呢?
全景圖拍的是六個方向的圖,放在一個平面看會很彆扭,所以會有專門的瀏覽的工具,根據視角的改變來切換看到的內容,這樣就能 360 度的還原拍照的場景。
#three.js 實現全景圖瀏覽,也就幾行代碼
用 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:
const scene = new THREE.Scene();
然後設置它的背景,用立方體的紋理來設置,需要分別指定左右上下前後的 6 個方向的圖:
let urls = [
'./img/home.left.jpg',
'./img/home.right.jpg',
'./img/home.top.jpg',
'./img/home.bottom.jpg',
'./img/home.front.jpg',
'./img/home.back.jpg'
];
let cubeTexture = new THREE.CubeTextureLoader().load(urls);
scene.background = cubeTexture;
這樣整個背景就是一個全景圖,就這麼幾行代碼。
當然,我們還要設置下相機位置,這裏用透視相機就行,它的特點是從一個點去看 3D 場景,看到的內容是近大遠小的。
const width = window.innerWidth;
const height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
camera.position.set(0,0, 100);
camera.lookAt(scene.position);
需要設置看到的角度,這裏設置了 45 度,看到內容的寬高比,這裏用窗口寬高比,再就是遠近範圍,這個設置範圍大一點就行。
相機位置設置在了 z 軸 100 的位置,這樣看 z 爲 0 的位置就是從正面去看的,可以感受下這個看的方向。
有了 3D 的 Scene,設置好了相機,就可以用 Renderer 把它渲染出來了。
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement)
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
我們用 requestAnimationFrame 來一幀幀的調用 renderer 渲染。
當然,還要加上鼠標控制,可以通過鼠標的拖動方向來改變相機看到的角度,這個用 Three.js 提供的 Controls 就行,不用自己寫。
我們需要 360 度的看,用 OrbitsControls 來做交互就行,他叫軌道控制器,也就是衛星繞地球的那種軌道的感覺。
const controls = new THREE.OrbitControls(camera);
OrbitControls 參數是 camera,因爲它就是通過改變 camera 位置實現的。
至此,我們就實現了全景圖的瀏覽。來看下效果:
#three.js 實現全景圖瀏覽,也就幾行代碼
全部代碼上傳了 github:https://github.com/QuarkGluonPlasma/threejs-exercize
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>全景圖</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
<script src="./js/three.js"></script>
<script src="./js/OrbitControls.js"></script>
</head>
<body>
<script>
const width = window.innerWidth;
const height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer();
camera.position.set(0,0, 100);
camera.lookAt(scene.position);
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement)
function create() {
let urls = [
'./img/home.left.jpg',
'./img/home.right.jpg',
'./img/home.top.jpg',
'./img/home.bottom.jpg',
'./img/home.front.jpg',
'./img/home.back.jpg'
];
let cubeTexture = new THREE.CubeTextureLoader().load(urls);
scene.background = cubeTexture;
}
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
create();
render();
const controls = new THREE.OrbitControls(camera);
</script>
</body>
</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 或者類似的工具就可以裁切出來。
全景圖瀏覽一共也沒幾行代碼,但是這個功能還是很有用的。如果你會拍全景圖,那就更棒了,可以把生活中一些場景立體的記錄下來,自己寫一個工具來瀏覽。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/LyRjT5fkpSLtMYxXzO7KRQ