本文是在CSDN一個公開課的演講,現整理釋出於知乎,為筆者原創。歡迎VR愛好者與從業者相互交流學習。

VR(Virtual Reality),似乎從2016年起,成為了一個人人都喜歡掛在嘴邊的新鮮名詞,好像不談論VR就像你不認識特斯拉不聽薛之謙不看愛樂之城一樣,暗示著與時代的“脫節”。如果你偶然得知身邊有人在做“VR專案”,那就好像是發現了下一個

馬克·扎克伯格

一樣,相信他一定會成為時代的“弄潮兒”。不過,大多數人對於VR的理解,也僅僅停留在“

虛擬現實

”這四個字上面。那麼,VR究竟是怎樣的,它的實踐原理又是什麼,本文將嘗試用較為簡單的語言,來闡述這一“

現在與未來的風口

”。

本文將主要從紅極一時Google CardBoard到號稱很可能改變未來人們遊戲的方式的Oculus Rift來與大家探討VR的實現原理與前景。首先,我們一起來看兩個簡單卻基本的問題:

1. 為什麼目前的VR被稱為光學VR?

答:因為人們對世界的認識,是透過

人眼觀察世界

。目前一切的VR,都是透過扭曲光線,讓光線進入視網膜,欺騙眼睛來實現的。

2. 什麼情況下會有脫離光學的VR?

答:人類可以脫離眼睛溝通這個世界的時候(笑)。

這兩個問題看似簡單,實則涉及到本文的一個核心要點:

光學

。不管是VR(Virtual Reality 虛擬現實),還是AR(Augmented Reality 增強現實),還是號稱象徵著未來的MR(Mix reality 混合現實),都脫離不了光學。本文會將

VR的基礎實現原理

儘量講一遍,由於讀者對行業的瞭解程度關係,可能不會講得太深入。但是,如果有朋友希望瞭解一些更深入的東東,歡迎大家在文章下留言評論,我會盡力與大家交流解答。

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

最廉價的VR體驗裝置——Google CardBoard一代

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

曾擊敗Xbox One與PS4獲得“最佳硬體獎”的遊戲裝置——Oculus Rift CV1

以上兩個,就是比較有代表性的

HMD

(做筆記以後出去談VR的時候又有了一個專(zhuang)業(bi)名詞了呢),

HMD是Head Mount Display的縮寫,也就是俗稱的頭顯

,這是VR最核心的裝置,只有有了這個東西,關於VR的一切才有可能。

上面的兩個裝置,一個是最原始的Google Cardboard,一個是大名鼎鼎的“三大頭顯”之一:Oculus rift CV1,CV1看起來相較於Google Cardboard顯得十分高大上,充滿了科技感與時尚感。但究其核心,還是那些東西:

一個塑膠外殼,兩個鏡片,一個顯示器。

看到這裡有些小夥伴可能不免失望,原來所謂的科技最前沿,就是這3樣東西呀。不急,下面我們來繼續探究其中的原理。

首先我們來看一個大致的結構圖:

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

這是一個典型的VR眼鏡功能模擬,主要包括

三部分

人眼

凸透鏡

OLED成像螢幕

看起來大家會覺得更簡單了,好像我隨便

找個螢幕,找個透鏡,再找個盒子,就組成了一個VR裝置

(瞬間化身科技公司大佬可以指點江山了)。那麼究竟實時是否如此呢?答案是:

是的!

大家沒看錯,國內一大把各種魔鏡,都是這麼做的。那麼究竟怎麼做呢? 下面為大家介紹一條

創(fa)新(jia)創(zhi)業(fu)之路:

首先,先去市場(淘寶),購買一大把透鏡,從幾毛到幾塊一塊都有,然後找一撥人(例如公司員工),大家一塊一塊看,最終大家公認哪一款效果最好,然後定了,就這款了!再用手工做一個手版的盒子,裝上鏡片,再拉上這幫人一起看效果,慢慢調,當效果大家覺得湊合的時候,那麼,引數定下來了,一款VR眼鏡誕生了!

這種VR眼鏡,被稱作

人海VR

,常見於市面上幾十、一百塊的各種盒子,在華強北據稱一年出貨量幾千萬個。這類盒子的體驗效果可以預見是非常差的,容易使人暈眩,基本上可以看做是一個玩具。

那麼,一款優秀的HMD應該是怎麼樣的呢?筆者個人認為

以下兩點至關重要

完全符合人體結構

儘量輕便,降低存在感,也就是說,你戴上去跟沒戴一樣

第二點是小型化問題,目前不考慮,我們來詳細講講第一點。

要做好完全符合人體結構,或者說盡量的去符合人體結構,至少有

以下因素需要考慮

人眼觀察角度(也可以叫視場角,簡稱FOV——Field of View)

人雙眼之間的距離(俗稱瞳距,簡稱IPD——Interpupillary distance)

人眼到鏡片的距離

鏡片到螢幕的距離

螢幕成像的大小計算

螢幕成像的反畸變

螢幕成像的渲染幀率

螢幕的重新整理延遲

……

一款優秀的HMD,至少要考慮到這8點。其實除了這8點,還有其他更復雜的東西,例如

自動對焦,運動模糊

等。下面,我們會側重談談這8點應該如何來考慮,做到最好。

要考慮設計一款優秀的HMD,首先要想明白一個問題,

VR的沉浸感

從何而來?要知道這一點就需要先了解視網膜成像原理:

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

透過視網膜成像,人眼觀察著這個世界。VR如何欺騙了眼睛呢?答案是:

凸透鏡

再看下圖:

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

上圖很好的表述了一個觀點:

你看到的世界不一定是真實的

。你以為看到的是紅色的虛像世界,實際你所看到的,只是藍色螢幕中的一方天地。

為什麼我們需要一塊透鏡?嘗試一下,伸出一根手指,放在你的眼前1釐米,你會發現,你看不清你的手指。很詭異是不是?人眼的成像是有距離的,透鏡是為了把近距離的影象放大成一個虛像,增加成像距離。

透過該圖,很容易得出一些結論:

HMD不能漏光。一旦漏光,談不上什麼沉浸感了

人眼到鏡片最合適的距離,就是鏡片的焦距稍稍往前。

由此我們可以知道,鏡片儘量設計到焦距夠小(便於鏡片覆蓋眼睛)

螢幕到透鏡的距離,跟鏡片的散射角度有關

(參考一下藍線傾斜即可)

最理想的狀態是,人眼觀察角度與紅線部分重合

(基本上不可能達到理想狀態,因為HMD是固定的,而人與人眼睛是不同的)。

好了,根據這四點結論,我們可以比較輕易判斷,對於一款HMD而言,合適的鏡片至關重要,直接決定了HMD的最終質量。因此,在

VR鏡片

上,各大公司可謂不遺餘力。除了所謂的

光學鏡片

,最近還在熱炒各種概念,例如

菲涅爾鏡片

(Fresnel lens)

,光場鏡片

(這塊獨立出來都是一個很複雜的概念,由於篇幅有限,這裡不打算細講)。

既然一款鏡片如此重要,那麼,如何才能設計出一款足夠牛逼的鏡片?需要重點關注哪些引數?下面幾個引數非常重要:

視場角(FOV)

符合人眼構造的成像系統

清晰度

視場角多少合適?有一種主流的看法是:

合理範圍內,視場角越大越好

。那麼,什麼叫做

“合理範圍內”

?,可以理解為:

沒有導致明顯的透視變形之前

(關於透視變形,這是3d的基礎概念,不打算科普,大家度娘一下就能找到)

儘量達到人眼最大視場角。

由於人的眼珠是可以轉動的,單眼最大理論視場角大概在150度左右。那麼,FOV要達到150度嗎?其實不是,FOV大小還跟螢幕解析度有關,當解析度不足夠的時候,FOV越大,會導致紗窗效果越明顯。關於這個,計算也很簡單,只需要計算觀察範圍面積(透過FOV和觀察距離),再用螢幕畫素 / 觀察面積,就能夠得到每平方cm有多少個畫素。單位範圍內畫素越小,效果越差。如果是做開發的應該能輕易算出來。

因此,在目前大部分裝置上,視場角並沒有越大越好,

普遍在90 - 100之間,最高的貌似也就105左右

符合人眼的成像系統,這個又是什麼意思呢?

熟悉3d圖形學的朋友會知道:

3d中,透視投影變換主要是三個矩陣:world, view, projection

。前兩個是座標變換,不在今天的討論範圍,第三個,卻是實打實的投影模擬。但是,在普通3d遊戲中,這個投影模擬的不是人眼視網膜,而是一個計算機顯示器視窗,所以,這個矩陣的計算引數一般有:

Y方向FOV,視窗寬高比,最近可視距離,最遠可視距離

。大概演算法如下:

float thetaY(mFOVy / 2。0f);

float tanThetaY = tan(thetaY);

// Calc matrix elements

float w = (1。0f / tanThetaY) / mAspect;

float h = 1。0f / tanThetaY;

float q, qn;

q = -(mFarDist + mNearDist) / (mFarDist - mNearDist);

qn = -2 * (mFarDist * mNearDist) / (mFarDist - mNearDist);

// [ w 0 0 0 ]

// [ 0 h 0 0 ]

// [ 0 0 q qn ]

// [ 0 0 -1 0 ]

Matrix4 dest = Matrix4::ZERO;

dest[0][0] = w;

dest[1][1] = h;

dest[2][2] = q;

dest[2][3] = qn;

dest[3][2] = -1;

mProjectionMatrix = dest;

問題來了,我們做VR,適合採用這種方式嗎?答案是:這樣可以做,但是效果不夠理想,因為並沒有符合人體結構。

在瞭解“

符合人體結構

”這個概念前,大家可以做一個小實驗。嘗試閉上一隻眼睛,然後只用一隻眼睛,盡力前後左右看,你覺得這是一個正投影嗎?也就是說,上下,左右看到的角度大小,是一樣的嗎?很顯然,我們基本能夠確定,上下,左右能觀察到的範圍,並不對稱,這才是真正的人體結構。

因此,我們計算的投影矩陣,理想的狀態,不能是正矩陣。理想的資料是多少?這裡我給出Oculus的一個眼睛資料:上下左右角度分別為:41。65, 48, 43。98, 35。57。

那麼,這個角度範圍就是最理想的範圍了嗎?答案是:不是。既然不是(正常人平均值大概是56、74、91、65),作為VR界的領軍人物,難道Oculus不知道這個事情嗎,為什麼不直接用最合適的範圍角度?很簡單,問題在於光學鏡片的設計,光學鏡片並不能為所欲為的設計這個視場角(還有一個原因還是螢幕解析度),所以現在的VR大熱菲尼爾鏡片應運而生。

菲尼爾鏡片

好處多多,可以有其他很多好處例如清晰度,畸變……

據說希拉里的眼鏡就是菲涅爾鏡片哦

綜上所述,我們大概理清了鏡片的一些重要的引數和合適設計,下面,我們來講講重要的

成像

以及

反畸變

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

原圖(左)經過VR觀看的效果(右)

關於成像與反畸變的一些問題解答:

VR成像跟普通的3d遊戲成像有什麼不同?

Projection Matrix不同

。參見上一條,Projection的計算不能採用傳統的正矩陣計算。

View Matrix不同。

考慮到IPD(瞳距),View Matrix的計算應該分左右眼,position的計算應該是:

LeftPosition = position + rotation * (-IPD / 2);RightPosition = position + rotation * (IPD / 2)

;其實就是左右眼分別沿x軸的

正負方向

偏移IPD的一半。

渲染方式不同

。正常的3d渲染是單屏,而VR是需要先渲染兩隻眼睛,得到

render texture

,然後再把左右眼貼圖渲染一遍到螢幕。

由於第三個特性,VR渲染跟傳統渲染相比,有很多細節需要注意

。例如到底使用延遲渲染還是使用向前渲染,抗鋸齒應該怎麼處理,模糊怎麼處理……一句話概括:VR有可能使得傳統的渲染模式發生改變。典型的例如Google Day Dream本身推薦使用放大RTT的做法來實現抗鋸齒(跟FSAA類似)。

VR成像的內容不算太多,更重要的是反畸變。

為什麼要反畸變?

答:

因為正常的東西,透過凸透鏡去看,是變形的

(隨便拿塊透鏡試試便知)。所以我們不能夠直接把render texture直接貼到螢幕上,需要把圖片做一個反畸變,然後透過透鏡的畸變,觀看的畫面變成了正常。

那麼問題來了,這個反畸變應該如何做?

我們先來看看大名鼎鼎的Google CardBoard的實現方式。

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

這是一張放爛了的圖,Google文件專用。在他們的開發文件裡,他們號稱使用了布朗畸變模型(細節可以在這裡看到:https://en。wikipedia。org/wiki/Distortion_(optics),又或者google一下vr

lens distortion

,資料很多)。這裡,我就不做純粹的搬運工,直接複製貼上,來幫大家分析一下要點:

首先,得到鏡頭的中心點

(中心點由於是垂直透過,沒有角度,無畸變)

任意點的畸變,先計算該點到圓心的半徑

根據鏡頭K1、K2的引數,計算出畸變後的座標

紋理取樣時,根據這個偏移做UV偏移,取樣

這個是大概過程。目測很多好奇的群眾會跟我一樣,好奇這個K1、K2從何而來?我其實也很好奇,但是由於Google的文件語焉不詳,很詭異的是,Google文件裡面還提及到手工調節這兩個引數,言下之意是:如果你根據鏡片廠商提供的這兩個引數,沒有達到最好的效果,請手動調節這兩個引數,以達到最好的效果。

再來看看同樣大名鼎鼎的Oculus Rift的實現方式。其實Oculus早期採用了跟Google一樣的方式(誰模仿誰不知道),

只不過兩個引數K1、K2變成了四個:K1,K2,K3,K4

,其實這樣做意義不大,最早期的資料,K3很接近0,K4直接是0,幾乎不起作用,後期陸陸續續有各種改動。但是,Oculus越做越好,後面徹底摒棄了之前的方式,

採用了全新的Distortion Mesh的渲染方式

。我們的鏡片,同樣採用了這種方式,核心做法是:

設計好鏡片

根據鏡片的引數(大概20多個),生成一個畸變模型

畸變模型的UV要分為RGB三塊,三組UV

貼圖渲染的時候,分別做RGB取樣,得到新的顏色的RGB,組合成新顏色

大概shader代如下:

static char* defaultDistortionVertexShaderSrc =

“float4x4 ProjView;float4 MasterCol;”

“void main(in float4 Position : POSITION, in float2 TexCoordR : TEXCOORD0, in float2 TexCoordG : TEXCOORD1,in float2 TexCoordB : TEXCOORD2,”

“ out float4 oPosition : SV_Position, out float4 oColor: COLOR0, out float2 oTexCoordR : TEXCOORD0, out float2 oTexCoordG : TEXCOORD1, out float2 oTexCoordB : TEXCOORD2)”

“{ oPosition = Position;”

“ oColor = MasterCol;”

“ oTexCoordR = TexCoordR;”

“ oTexCoordG = TexCoordG;”

“ oTexCoordB = TexCoordB;}”;

static char* defaultDistortionPixelShaderSrc =

“Texture2D Texture : register(t0); SamplerState Linear : register(s0);”

“float4 main(in float4 Position : SV_Position, in float4 Color: COLOR0, in float2 TexCoordR : TEXCOORD0, in float2 TexCoordG : TEXCOORD1, in float2 TexCoordB : TEXCOORD2) : SV_Target”

“{ float4 TexColR = Texture。Sample(Linear, TexCoordR);”

“ float4 TexColG = Texture。Sample(Linear, TexCoordG);”

“ float4 TexColB = Texture。Sample(Linear, TexCoordB);”

“ return float4(TexColR。r * Color。r, TexColG。g * Color。g, TexColB。b * Color。b, 1); }”;

那麼,

兩種方式的差別是什麼?是什麼原因導致了兩大巨頭分別採用了不同的實現方式?

我個人的判斷是:Oculus的方式,效果明顯要優於Google的方式,

最明顯的問題,在光線經過透鏡的時候,RGB由於波長不同,折射率是不一樣的

,這部分在高中物理裡有講過。

所以紋理反畸變的時候,必須要做rgb偏移,不然,一定會有色差問題,並且邊緣地方越加明顯。

既然如此,難道Google不知道嗎,為什麼不也採用Oculus的方式?我的看法:

Google希望做的是一個開放的系統,希望適配所有的鏡片與手機

。這可以理解為是

從商業角度去考慮

而使用Distortion Mesh的方式,不可能做到這一點或者說很不容易做到這一點(我其實覺得可以開放驅動介面的方式也是可以實現的,詳情請看Windows適配各種硬體),但是,Google採用了最簡單暴力的方式,這樣的話,讓移動平臺的VR蒙上了陰影(Google最新推出的DayDream系統、盒子、樣機。黃牛價大概7000多,幾乎沒有色差矯正)。

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

配合手機使用的Daydream View頭盔和控制器

2016,號稱VR元年,但是,風風火火看似聲勢浩大的開局,交出的成績單卻不盡如人意,很大程度上在於體驗效果並沒有達到預期。

為了相容大量不適合vr的手機而選擇了一種效果更差的方式。簡而言之,這是一種體驗效果與商業模式的動態博弈。

這種方式的是否可取,以目前看來, 我個人認為,還是要優先深耕技術與體驗效果,再進一步考慮

商業成本

與盈利的問題,好的體驗感一定會有消費者來買單。

為什麼Distortion Mesh方式效果要優於Google的實現方式?很簡單,這就像3d渲染的兩種方式,光線跟蹤與光柵化。

眾所周知,目前的實時渲染都是光柵化,再配合少量光線跟蹤,純光線跟蹤的Real Time,三五年內看不到希望。而Distortion Mesh的方式,就是光線跟蹤,根據設計好的鏡片,做一個光線模擬,計算,生成各個頂點的RGB偏移。而Google的計算方式,希望透過一條公式計算匹配所有的鏡片,在未來菲涅爾鏡片爛大街的時候,會更顯無力。以上是我個人判斷。

“V”來已來——淺談光學VR實現原理

“V”來已來——淺談光學VR實現原理

上面簡述了

光學VR

實現的一些基本原理,希望能夠對對VR行業有興趣的小夥伴有所幫助,更多的細節問題,如果大家有興趣可以一起探討。行業的發展需要技術的沉澱與市場的逐步認可與接收,

大多數人長期徘徊在“等風來”的時期。現在,風口已至,是否能夠迎風直上,讓我們拭目以待。

本文作者:

深圳市奇境資訊科技有限公司

劉粵桂