淺談 WebVR 全景
前言
近年來VR概念越來越火,相信大家在網(wǎng)上都有過VR的瀏覽體驗(yàn),比如VR全景看房[1]、VR全景看車[2]、VR全景旅游[3]等等,VR全景給了我們視覺上的沉浸式體驗(yàn)。本文將會(huì)簡(jiǎn)單探究Web VR全景的實(shí)現(xiàn)原理,同時(shí)也會(huì)用threejs實(shí)現(xiàn)兩個(gè)小的demo,希望對(duì)大家以后在業(yè)務(wù)上遇到類似的場(chǎng)景能有所幫助。
什么是VR
引用維基百科的定義:
虛擬現(xiàn)實(shí)(英語:virtual reality,縮寫VR),是利用電腦模擬產(chǎn)生一個(gè)三維空間的虛擬世界,提供用戶關(guān)于視覺等感官的模擬,讓用戶感覺仿佛身歷其境,可以即時(shí)、沒有限制地觀察三維空間內(nèi)的事物。用戶進(jìn)行位置移動(dòng)時(shí),電腦可以立即進(jìn)行復(fù)雜的運(yùn)算,將精確的三維世界影像傳回產(chǎn)生臨場(chǎng)感。
與基于現(xiàn)實(shí)場(chǎng)景進(jìn)行增強(qiáng)效果的 AR(Augmented Reality)的區(qū)別在于,VR 的場(chǎng)景需要完全重建,類似于進(jìn)入另一個(gè)世界。
虛擬現(xiàn)實(shí)的實(shí)現(xiàn)原理
人眼對(duì)世界的感知,是通過將三維世界投射至視網(wǎng)膜上,以二維圖像建立的視覺體系。所以一張具備透視關(guān)系的圖像,在特定的角度,可以使人感受到三維的空間關(guān)系,這就是人眼的深度知覺(depth perception)。VR 技術(shù)則建立在這個(gè)基礎(chǔ)之上。
廣泛意義上來說,只要符合模擬三維空間這一行為,就可以稱為 VR,手機(jī)、電腦、大熒幕、VR 眼鏡甚至于空氣,都可以成為 VR 的載體。
如何在web上模擬三維空間
三維空間是由2D和3D圖形構(gòu)成的,要模擬三維空間,必須繪制2D和3D圖形,我們寫js有ECMAScript規(guī)范,同理的繪制2D和3D圖形也有一套規(guī)范,這套規(guī)范就是OpenGL
?OpenGL是什么?
OpenGL(英語:Open Graphics Library,譯名:開放圖形庫(kù)或者“開放式圖形庫(kù)”)是用于渲染2D、3D矢量圖形的跨語言、跨平臺(tái)的應(yīng)用程序編程接口(API)。
OpenGL規(guī)范描述了繪制2D和3D圖形的抽象API,常用于CAD、虛擬現(xiàn)實(shí)、科學(xué)可視化程序和電子游戲開發(fā)。
?在Web上能用OpenGL嗎?
可以的,在web上可以使用WebGL,它是Web瀏覽器中OpenGL的JavaScript綁定。
?什么是WebGL?
WebGL是一種JavaScript API,用于在不使用外掛程式的情況下在任何相容的網(wǎng)頁瀏覽器中呈現(xiàn)交互式2D和3D圖形。WebGL完全整合到瀏覽器的所有網(wǎng)頁標(biāo)準(zhǔn)中,可將影像處理和效果的GPU加速使用方式當(dāng)做網(wǎng)頁Canvas的一部分。WebGL元素可以加入其他HTML元素之中并與網(wǎng)頁或網(wǎng)頁背景的其他部分混合。
有了WebGL API,我們就可以web網(wǎng)頁上構(gòu)建三維空間啦。我們可以借助canvas標(biāo)簽來獲取WebGL實(shí)例來進(jìn)行WebGL API的調(diào)用,更多API可以戳WebGL: 2D and 3D graphics for the web - Web APIs | MDN[4]查看,下面是使用示例:
目前業(yè)界有很多成熟的WebGL3D引擎,比如three.js[5]、babylon.js[6]等等,這些3D引擎已經(jīng)對(duì)WebGL API做了非常高效的封裝,可以幫助我們快速繪制2D和3D圖形。
three.js實(shí)現(xiàn)vr全景
在實(shí)戰(zhàn)前先了解下three.js的基本概念
?基本概念?
在three.js中,渲染一個(gè)三維空間的必要因素是場(chǎng)景(scene)、攝像機(jī)(camera)、渲染器(renderer)。渲染出一個(gè)三維空間后,可以往里面增加各種各樣的物體、光源等等。
場(chǎng)景(scene)
一個(gè)容器,容納著除渲染器以外的3d世界里的一切。場(chǎng)景的元素采用右手坐標(biāo)系,x軸正方向向右,y軸正方向向上,z軸由屏幕從里向外。
攝像機(jī)(camera)
就像人的眼睛,在一個(gè)空間里可以看向任意方向,可以通過參數(shù)調(diào)節(jié)可視角度和可視距離。
three.js中常用的camera有兩種,透視投影相機(jī)(PerspectiveCamera)與正交投影相機(jī)(OrthographicCamera)。這里的投影是指將三維空間中的物體坐標(biāo)投影到二維平面上。
- 透視 投影是將每個(gè)點(diǎn)都投影到三維空間中,近大遠(yuǎn)小,看起來更符合真實(shí)世界看到的物體。
- 正交 投影是只考慮所有點(diǎn)的XY坐標(biāo),每一個(gè)二維空間中的點(diǎn)都是與Z軸平行的直線在觀察平面上的投影。所看到的物體大小不會(huì)受到距離遠(yuǎn)近的影響。
透視相機(jī)(PerspectiveCamera)
使用perspective projection(透視投影)來進(jìn)行投影。
這一投影模式被用來模擬人眼所看到的景象,它是3D場(chǎng)景的渲染中使用得最普遍的投影模式。
PerspectiveCamera(fov, aspect, near, far) 有四個(gè)參數(shù):
- fov - field of view,視野角,下圖中綠色英文標(biāo)注的地方,是距離觀測(cè)點(diǎn)near長(zhǎng)度處,最上端與最下端之間的角度,F(xiàn)ov越大,表示眼睛睜得越大,離得越遠(yuǎn),看得更多。
- aspect - 畫面橫寬比
- near - 相機(jī)最近范圍內(nèi)可以看到的物體的距離
- far - 相機(jī)最遠(yuǎn)范圍內(nèi)可以看到的物體的距離
正交相機(jī)(OrthographicCamera)
這一攝像機(jī)使用orthographic projection(正交投影)來進(jìn)行投影。
在這種投影模式下,無論物體距離相機(jī)距離遠(yuǎn)或者近,在最終渲染的圖片中物體的大小都保持不變。這對(duì)于渲染2D場(chǎng)景或者UI元素是非常有用的。
OrthographicCamera(left, right, top, bottom, near, far)有六個(gè)參數(shù)
left, right, top, bottom - 分別是紅色點(diǎn)距離左右上下邊框的距離,對(duì)應(yīng)圖中XY軸的值;
near - 場(chǎng)景開始渲染并可以顯示的起點(diǎn),對(duì)應(yīng)圖中Z軸坐標(biāo)的值,通常為負(fù);
far - 場(chǎng)景結(jié)束渲染的終點(diǎn),對(duì)應(yīng)圖中Z軸坐標(biāo)的值,通常為正;
渲染器(renderer)?
將camera在scene里看到的內(nèi)容渲染/繪制到畫布上
設(shè)置好 dpr、畫布寬高,Three.js 就會(huì)生成一個(gè) canvas。
幾何體(geometry)
三維空間里的所有物體都是點(diǎn)組成面,面組成幾何體。
three.js核心中內(nèi)置了多種幾何體,如下圖的幾何體從左到右分別為:球緩沖幾何體(SphereGeometry)?、 圓柱緩沖幾何體(CylinderGeometry)、立方緩沖幾何體(BoxGeometry)、圓錐緩沖幾何體(ConeGeometry)?、 圓環(huán)(TorusGeometry)和圓環(huán)緩沖扭結(jié)幾何體(TorusKnotGeometry)等等
貼圖(texture)
想象一下你手里有一個(gè)幾何體,你用一張A4紙包裹上幾何體,并在上面畫畫。你畫的內(nèi)容就是貼圖。
下面給立方體貼上小黃鴨貼圖:
也可以給立方體貼上視頻
材質(zhì)(material)
延續(xù)貼圖里的想象,你用白卡紙畫畫,還是用油紙畫畫,呈現(xiàn)出來的質(zhì)感是不同的,這就是材質(zhì)!
下面五個(gè)圓環(huán)扭結(jié)的顏色都是一樣的,而材質(zhì)從左至右分別是:
- MeshBasicMaterial(基礎(chǔ)材質(zhì),簡(jiǎn)單的幾何材料,不考慮光照的影響)
- MeshMatcapMaterial(網(wǎng)帽材質(zhì),在場(chǎng)景沒有光源的情況下,會(huì)模擬出物體被光照的效果)
- MeshPhongMaterial(高光材質(zhì),適用于陶瓷,烤漆類質(zhì)感)
- MeshToonMaterial(卡通材質(zhì))
- MeshLambertMaterial (非光澤表面的材質(zhì),沒有鏡面高光,可以很好地模擬一些表面,例如未經(jīng)處理的木材或石材,但不能模擬具有鏡面高光的光澤表面,例如涂漆木材。)
環(huán)境光的情況下:
有從上往下的平行光:
燈光(light)
在沒有手動(dòng)創(chuàng)建光的情況下會(huì)默認(rèn)有個(gè)環(huán)境光,不然你什么都看不到。
常見的燈光有以下幾種類型:
AmbientLight:環(huán)境光,沒有方向,會(huì)均勻的照亮場(chǎng)景中的所有物體,不會(huì)產(chǎn)生陰影
DirectionalLight:平行光,常常用平行光來模擬太陽光 的效果; 太陽足夠遠(yuǎn),因此我們可以認(rèn)為太陽的位置是無限遠(yuǎn),所以我們認(rèn)為從太陽發(fā)出的光線也都是平行的。
PointLight:點(diǎn)光源,從一個(gè)點(diǎn)向各個(gè)方向發(fā)射的光源。可以模擬一個(gè)燈泡發(fā)出的光。
SpotLight?:聚光燈,光線從一個(gè)點(diǎn)沿一個(gè)方向射出,隨著光線照射的變遠(yuǎn),光線圓錐體的尺寸也逐漸增大。
?VR全景看房的實(shí)現(xiàn)?
原理
我們可以通過模擬人走在房子里的行為來實(shí)現(xiàn):
- 用攝像機(jī)模擬人,鏡頭相當(dāng)于人的眼睛
- 用立方幾何體六個(gè)面貼上貼圖模擬房子,貼圖要求真實(shí)還原房子六個(gè)面的情況
- 將攝像機(jī)放置在幾何體里面,移動(dòng)攝像機(jī)相當(dāng)于人在房子里走動(dòng)
素材準(zhǔn)備
房子六面貼圖:
代碼實(shí)現(xiàn)
1.創(chuàng)建場(chǎng)景和攝像機(jī),并且設(shè)置攝像機(jī)位置和添加加軌道控制器
2.創(chuàng)建立方幾何體,并且給幾何體貼上準(zhǔn)備好的貼圖
頁面效果:
3.將攝像頭的位置移動(dòng)到幾何體內(nèi)部
將攝像機(jī)移動(dòng)到幾何體內(nèi)部后發(fā)現(xiàn)視野一片黑暗,這是因?yàn)橘N圖是在幾何體外表面,所以需要將貼圖翻轉(zhuǎn)至內(nèi)表面。
4.將幾何體貼圖翻轉(zhuǎn)至內(nèi)表面,就能看到全景啦
5.監(jiān)聽鍵盤事件移動(dòng)攝像機(jī)
最終效果
?VR全景看車的實(shí)現(xiàn)?
原理
VR全景看車的難點(diǎn)是汽車模型的設(shè)計(jì),需要設(shè)計(jì)一個(gè)3d汽車模型,然后渲染到頁面上。汽車換裝則是通過對(duì)關(guān)鍵節(jié)點(diǎn)的操作來完成。
另外我們一般說的3d模型就是一個(gè)或多個(gè)幾何體,只是有的3d模型文件里除了包含幾何體還可以包含一些額外的信息,比如貼圖,材質(zhì)等等需要在讀取模型文件時(shí)解析出來
3d模型的文件格式有很多,但threejs里常用的基本是:
- OBJ格式:老牌通用3d模型文件,不包含貼圖,材質(zhì),動(dòng)畫等信息。
- GLTF格式(圖形語言傳輸格式):由OpenGL官方維護(hù)團(tuán)隊(duì)推出的現(xiàn)代3d模型通用格式,可以包含幾何體、材質(zhì)、動(dòng)畫及場(chǎng)景、攝影機(jī)等信息,并且文件量還小。有3D模型界的JPEG之稱。GLTF格式有.gltf(JSON/ASCII)和.glb(二進(jìn)制)兩種拓展名。
素材準(zhǔn)備
官網(wǎng)上找了一個(gè)汽車模型,可以用PlayCanvas glTF Viewer[7]查看汽車模型的節(jié)點(diǎn)信息。
代碼實(shí)現(xiàn)
1.創(chuàng)建場(chǎng)景和攝像機(jī),并且設(shè)置攝像機(jī)位置和添加加軌道控制器
2.加載汽車模型
通過GLTFLoader,我們可以加載一個(gè)gltf?格式的3d模型文件。需要注意的是,這些Loader都以插件的形式存在,需要引入相應(yīng)的XXXLoader.js才能使用
3.車輪滾動(dòng)
4.提供拾色器,改變車身(body)、細(xì)節(jié)(detail)和玻璃(glass)的顏色
最終效果
總結(jié)一下
以上只是本人對(duì)web VR全景的一個(gè)粗淺的探究,希望能夠引起你們對(duì)web VR的興趣。threejs(或其他3d引擎)能做的東西遠(yuǎn)不止于此,還有非常多炫酷、好玩的3d場(chǎng)景,感興趣的可以私下探索哦!
參考資料
[1]VR全景看房: https://bj.ke.com/
[2]VR全景看車: https://car.autohome.com.cn/vr/list-0-0-0-1.html
[3]VR全景旅游: http://www.quanjingke.com/
[4]WebGL: 2D and 3D graphics for the web - Web APIs | MDN: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
[5]three.js: https://github.com/mrdoob/three.js/
[6]babylon.js: https://github.com/BabylonJS/Babylon.js
[7]PlayCanvas glTF Viewer: https://playcanvas.com/viewer
[8]three.js docs: https://threejs.org/docs/index.html#manual/zh/introduction/Creating-a-scene
[9]three.js中兩種常用的攝像機(jī)模式: https://segmentfault.com/a/1190000013145246
[10]Three 之 three.js (webgl)涉及的各種材質(zhì)簡(jiǎn)單說明(常用材質(zhì)配有效果圖)_仙魁XAN的博客-CSDN博客_threejs材質(zhì)和紋理: https://blog.csdn.net/u014361280/article/details/124416631
[11]Threejs 實(shí)現(xiàn)簡(jiǎn)單的全景圖: https://fangsueluo.github.io/2021/01/12/vr-threejs-learning/
[12]三種前端實(shí)現(xiàn)VR全景看房的方案!說不定哪天就用得上! - 掘金: https://juejin.cn/post/6973865268426571784
[13]一步步帶你實(shí)現(xiàn)web全景看房--three.js - 掘金: https://juejin.cn/post/6844903918409875469
[14]硬核看房利器——Web 全景的實(shí)現(xiàn): https://segmentfault.com/a/1190000024476102
[15]2天賺了4個(gè)W,手把手教你用Threejs搭建一個(gè)Web3D汽車展廳! - 掘金: https://juejin.cn/post/6981249521258856456
[16]WebGL坐標(biāo)系介紹_桑榆未晚_的博客-CSDN博客_webgl坐標(biāo)系: https://blog.csdn.net/TW934440653/article/details/102529017?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-102529017-blog-70878160.pc_relevant_multi_platform_whitelistv4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-102529017-blog-70878160.pc_relevant_multi_platform_whitelistv4&utm_relevant_index=2
- EN?