裸眼 3D 是什么效果?
作者:沙因,騰訊 IEG 前端開發(fā)工程師
介紹一種裸眼 3D 的實(shí)現(xiàn)方式,代碼以 web 端為例。
平常我們都是戴著 3D 眼鏡才能感受 3D 效果,那裸眼能直接看 3D 么?可以看看下面這個(gè)視頻:
感興趣可以掃描這個(gè)二維碼實(shí)際體驗(yàn)下:
以上效果是基于 threejs 封裝了個(gè)相機(jī)組件:
使用 GlassFree3dCamera 代替正常的相機(jī),其中 xyz 為裸眼 3d 相機(jī)的坐標(biāo),width,height 為投影平面的寬高。
實(shí)現(xiàn)原理
這種裸眼 3d 實(shí)際上是基于一種視覺誤差產(chǎn)生的,與傳統(tǒng)的雙眼產(chǎn)生的不同的圖像差形成距離感不同,這種裸眼是依賴 3d 的“離軸投影”,離軸投影將產(chǎn)生“非對(duì)稱相機(jī)”視錐體。
不過離軸投影與非對(duì)稱相機(jī)并不是已有的專業(yè)名詞,這是 TheParallaxView 作者提出的一個(gè)概念。
視頻中,作者利用 ARkit 的 faceid 功能,定位到眼睛的位置,然后將裸眼 3d 的相機(jī)位置替代到人眼球位置。
除去 ARkit 的功能,這個(gè)效果的核心技術(shù)在其實(shí)現(xiàn)的“非對(duì)稱的鏡頭”上。當(dāng)時(shí)覺得這個(gè)看起來不難,就嘗試的實(shí)現(xiàn)了一下,將傳統(tǒng)相機(jī)的軸鎖定(lookAt)在“盒子”的正中心。
傳統(tǒng)相機(jī)效果:
雖然也有“立體感”,但那是平常我們常見的“全景”專題的 3d。
實(shí)際上的裸眼 3d 效果應(yīng)該是下面這種:
“盒子”的四個(gè)角始終“粘”在畫面的四個(gè)角上。
為什么會(huì)有這種區(qū)別?
首先,我們要了解 3d 相機(jī)的工作機(jī)制。
3d 相機(jī)機(jī)制
3d 相機(jī)的算法核心是投影矩陣:
在一個(gè)視錐體內(nèi)的 3d 對(duì)象,通過投影矩陣渲染到平面上。
three.js 的投影矩陣:
var te = []; var x = 2 \* near / ( right - left ); var y = 2 \* near / ( top - bottom );var a = ( right + left ) / ( right - left ); var b = ( top + bottom ) / ( top - bottom ); var c = - ( far + near ) / ( far - near ); var d = - 2 \* far \* near / ( far - near );te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;具體投影矩陣的算法,可以查看文章最后的參考資料。
其中,相機(jī)與視錐截面中心的連線垂直于視錐截面。
投影矩陣可以渲染出紅色方塊的縱深,但是當(dāng)相機(jī)旋轉(zhuǎn)后將會(huì)出現(xiàn)方塊的邊“溢出”屏幕的情況:
而正常情況下,我們看一個(gè)現(xiàn)實(shí)中的 3d 盒子是這樣的視角:
這時(shí)候的投影是一個(gè)不規(guī)則的四邊形,直接計(jì)算這個(gè)四邊形的范圍是很困難的。
而這個(gè)看似非常難以實(shí)現(xiàn)的效果,實(shí)際上轉(zhuǎn)換一下思維就變得很簡單了,我們會(huì)卡在這一步的原因就是先入為主的認(rèn)為,視錐體一定需要是一個(gè)正錐體。
但是,只要我們直接平移投影矩陣,就可以創(chuàng)造出偏離軸心的投影矩陣。
該方案的裸眼 3d 技術(shù)核心就是這個(gè)“離軸投影”的算法。
實(shí)際做法只要在投影矩陣計(jì)算的時(shí)候,輸入指定區(qū)域的視錐參數(shù)即可。了解投影矩陣的前提下,視錐移軸并沒有新的算法,僅僅參數(shù)不同,但是這個(gè)思維轉(zhuǎn)換在這過程中卻是很重要的一環(huán)。關(guān)于投影矩陣的詳細(xì)介紹可以參考文末的參考資料。
完成裸眼 3d 相機(jī)后,只要對(duì)相機(jī)的位置進(jìn)行操作綁定即可。
如 TheParallaxView 作者,就是將相機(jī)的位置與人的眼睛位置通過 ARkit 進(jìn)行綁定:
glassfree3dcamera 組件中,添加了 touch 事件進(jìn)行綁定,通過下面語句開啟點(diǎn)擊事件。
camera.initMove();當(dāng)然,這種裸眼 3d 效果,一般情況下肯定是需要搭配陀螺儀進(jìn)行使用,于是一開始我也簡單的綁定了陀螺儀效果,因?yàn)楦杏X那似乎不是很困難。
camera.initDeviceOrientation();按照平時(shí)的陀螺儀綁定的方式,一直無法實(shí)現(xiàn)“真實(shí)”的裸眼 3d 效果。
這個(gè)效果是合成的,文末有鏈接。后來發(fā)現(xiàn),這是裸眼 3d 效果的第二個(gè)難點(diǎn)。
手機(jī)的朝向與陀螺儀
手機(jī)陀螺儀關(guān)于參數(shù)解釋的幾張圖:
這幾張圖很容易讓人產(chǎn)生誤解,當(dāng)然不是說這幾張圖是錯(cuò)的。
首先,alpha,beta,gamma 的值是以地球坐標(biāo)為基準(zhǔn)的,其中,alpha 甚至與手機(jī)的朝向沒有關(guān)系。也就是說,alpha 圖也可以畫成這樣:
這幾張手機(jī)轉(zhuǎn)動(dòng)的都是 alpha 角,而不是只有當(dāng)手機(jī)繞著垂直于屏幕的 z 軸旋轉(zhuǎn)才觸發(fā) alpha 角。beta 角是手機(jī)的 y 軸與地面的角度值:
gamma 角是手機(jī)的 x 軸與地面的角度值:
alpha 與手機(jī)的軸無關(guān),beta,gamma 值與手機(jī)當(dāng)前 yx 軸的位置相關(guān),而另外一個(gè)很容易讓人誤解的就是谷歌開發(fā)者工具里的 sensors:
當(dāng)手機(jī)橫置的時(shí)候,出現(xiàn) alpha:0,beta:90,gamma:-90。
實(shí)際上,手機(jī)里的陀螺儀是不可能同時(shí)出現(xiàn)這 3 個(gè)數(shù)值的,因?yàn)?beta:90 時(shí),意味著手機(jī)垂直于地面,此時(shí) gamma 必然平行與地面,所以 gamma 值為 0。
而 sensors 里出現(xiàn)這個(gè)值,并不是陀螺儀返回的值,實(shí)際上反而是歐拉角輸入的值。
上面的值表示,(比如按 yxz 方向)beta 轉(zhuǎn)過 90 度,此時(shí)手機(jī)豎屏直立,然后 alpha 角不動(dòng),接著 gamma 轉(zhuǎn)-90 度,手機(jī)從豎屏直立橫躺下,到達(dá)了現(xiàn)在這種狀態(tài)。
當(dāng)前這個(gè)狀態(tài)的陀螺儀返回值應(yīng)該是 alpha:0,beta:0,gamma:-90。
了解了陀螺儀角度真正含義后,我們就可以把陀螺儀返回的角度值,先轉(zhuǎn)為歐拉角,再計(jì)算四元數(shù)(避免萬向節(jié)鎖):
var quaternion = new THREE.Quaternion(); var euler= new THREE.Euler(); euler.set( beta, alpha, - gamma, 'YXZ' ); quaternion.setFromEuler( euler );四元數(shù)可以通過四維投影到三維空間的球體來理解,具體四元數(shù)的對(duì)應(yīng)關(guān)系可以查看Visualizing quaternions
通過四元數(shù)記錄手機(jī)選擇角度,然后將裸眼 3d 相機(jī)位置按照對(duì)應(yīng)轉(zhuǎn)動(dòng)角度反向轉(zhuǎn)動(dòng),即可實(shí)現(xiàn)陀螺儀操控的裸眼:
假設(shè)相機(jī)的初始位置是 p1,當(dāng)手機(jī)旋轉(zhuǎn) q1 值時(shí),此時(shí)相機(jī)位置在 p2 處,但是相對(duì)手機(jī)來說相機(jī)依然是在手機(jī)的正前方,所以,相機(jī)需要逆向轉(zhuǎn)動(dòng) q1,從 p2 移到 p1,其中 p2 即為一開始的 p1 值。
用戶視角:
裸眼 3d 只計(jì)算轉(zhuǎn)動(dòng)值,所以還需要初始化轉(zhuǎn)動(dòng)前的角度值,即提前記錄 p1 位置。
結(jié)語:
裸眼 3d 的效果很大程度需要一個(gè)專門定制的模型以及交互引導(dǎo)(手機(jī)拿在手上慢慢轉(zhuǎn))才能最大限度發(fā)揮其效果,目前這項(xiàng)技術(shù)還沒有具體的活動(dòng)落地,但是“視頻版本”的裸眼 3d 效果卻頻頻的在人們的信息流中脫穎而出,也許一個(gè)可以“玩”的裸眼 3d 意外的具有潛力。
參考資料:
https://www.anxious-bored.com/blog/2018/2/25/theparallaxview-illusion-of-depth-by-3d-head-tracking-on-iphone-x
http://www.songho.ca/opengl/gl_projectionmatrix.html
https://www.bilibili.com/video/av90631060
https://eater.net/quaternions
推薦閱讀:
深入理解 MySQL 索引底層原理
騰訊高性能圖計(jì)算框架Plato及其算法應(yīng)用
總結(jié)
以上是生活随笔為你收集整理的裸眼 3D 是什么效果?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何提高自身监控系统的能力?
- 下一篇: 一款 0 门槛轻松易上手的数据可视化工具