馬萬峰,黎婭娟
(四川大學計算機學院,成都 610065)
隨著圖形學理論的進展和顯卡計算能力的提升,使得實時虛擬現實(VR)和增強現實(AR)應用在PC端乃至移動端實現成為可能,尤其是發展到現在AR應用已經被廣泛應用于交互游戲和手機自拍中。對于AR應用需要解決兩個關鍵的問題,物理一致性和光照一致性,同時對于透明物體的渲染,還需要考慮融合問題[1]。目前來說很多大的公司都在發力AR,例如谷歌已經正式發布了ARCore,ARKit已經跟新到了2.0版本,已經有超過千萬的安裝數量。同時,包括三星、小米、華為也在各自手機上開展AR體驗,微信、支付寶等也有AR攝影。
目前功能性AR主要集中在各種短視頻、特效相機、虛擬全景旅游,用戶目前更多的是體驗AR所帶來的那種新鮮感[2]。2015年左右,AR圖書或者AR識圖卡[3]特別火,一度帶動了圖書行業的小高潮,AR+教育成為當時特別火熱的話題。通過AR技術,將紙質圖文知識以生動酷炫的3D場景/模型呈現,帶來全新的閱讀體驗。AR家居,也是非常典型的應用場景,尤其是結合AR空間深度感知技術,真正為用戶解決家居擺放、購買等需求。
國內外互聯網巨頭目前仍然還在持續不斷地對AR進行投入,目前市面上越來越多的產品,我們都能看到在產品上面集成了AR功能。
但是與此同時也帶來了一個非常嚴重的問題,AR渲染不僅僅包括物理場景的探測,還包括周圍光照環境的實時探測,特別是當AR與透明物體結合在一起時將會帶來更多的挑戰。包括預計算和在光照計算上做出一些妥協[5],以及改進渲染算法是一件非常重要的事情,尤其是在目前更多的AR體驗來源于移動端,但是移動端GPU和CPU通常計算能力還是不夠,如何能夠減輕渲染時對硬件帶來的負擔是一個越來越重要的課題,本文將會聚焦光照一致性算法效率提升和與透明物體渲染結合,能夠更好地用于移動端。
本文提出了一種方法,能夠將應用于非透明物體的Cook-Torrance光照模型進行改進,利用紋理偏移方法與透明物體背后的場景進行偏移混合,同時利用多種方式改進渲染效率,最終在可接受的渲染時間內實時渲染出了透明眼鏡并能夠與頭部模型混合,隨著頭部的轉動而進行對應的運動,用于自拍體驗中。
本文提出的方法,首先通過解析視頻或者實時相機拍攝得到的每一幀的含有人頭部的圖片,通過圖像解析算法得到對應的虛擬頭部模型的變換矩陣,包括平移、旋轉矩陣,每次人的頭部發生任何改變,將會對M(Model)、V(View)、P(Projection)矩陣產生影響,并反饋得到。
接下來對眼鏡進行渲染,眼睛的光照渲染包括Diffuse光照,Specular光照,透過眼鏡之后的折射光照,前面兩種光照可以通過IBL(Image Based Lighting)部分進行處理,折射光照可以通過紋理偏移直接對基礎人像紋理進行采樣并與前面的光照進行混合。然后,再通過對頭部模型作用MVP矩陣,從而讓頭部模型與拍攝或者解析視頻得到的真實頭部保持一致。
在光照渲染結束之后,需要進行深度一致性的判斷,先繪制頭部模型,再繪制虛擬眼鏡模型。頭部模型繪制之后打開深度測試,保證在頭部模型外邊的眼睛部分片段能夠得到顯示。
最終,再進行了深度一致性檢測和光照一致性渲染之后,得到了最終的AR渲染結果。
另外本算法還對IBL渲染算法中包括切線空間,重要性采樣進行了改進,提升了渲染效率。
本節內容主要介紹AR眼鏡渲染的IBL算法部分和透明混合部分實現細節。IBL算法部分采用Cook-Torrance BRDF光照模型,但是這種光照模式主要是用來渲染不透明的物體表面的Diffuse光照和Specular光照,并不涉及到透明物體渲染過程中折射光線的問題。本文通過結合IBL算法和紋理偏移算法將兩者結合起來,IBL仍然用來實現Diffuse光照和Specular光照,透明物體的后面的折射光照通過光線在頂點法線,折射率,折射放縮因子等共同作用下得到。從而能夠得到虛擬眼鏡的光照效果。
本文采用的Cook-Torrance BRDF光照模型主要基于三個原理:基于微平面表面模型、能量守恒、應用基于物理的BRDF。用金屬度,粗糙度這兩個參數來對模型材質進行控制。
所有的PBR技術都是基于微平面理論,任何材質在達到微觀尺度下都是由一個個平坦的鏡面構成,這樣可以用粗糙度來描述這些鏡面分布的朝向一致性的概率[6]。對于一束平行入射光線,粗糙度越高,將會產生分布范圍更廣泛,但是更加暗淡的鏡面反射,這是由于能量守恒定律的限制。
另外對于金屬材質而言是沒有Diffuse光照的,對于鐵銹等材質,金屬度將會為介于0到1的某個值,用來更好地表現材質的特性。
IBL技術不是通過直接分析光照,而是把周圍整個環境作為一個大的光源來照亮物體,可以用一個HDR(High Dynamic Range)天空盒來捕獲真實場景光照,并且把天空盒上面的每個像素作為一個光源。用這種方式來對放入其中的虛擬物體進行渲染將會讓虛擬物體在光照上與場景有更好的融合感。
解決光照渲染問題最主要的是要解決Cook-Torrance反射率方程的實時積分問題。對此可以將其分為Diffuse光照部分和Specular光照部分分別進行預處理計算[7]來提升渲染的效率,并在最后進行光照的合成。主要目標是解決在所有的分布在法線方向半球入射光線Wi積分。我們需要能夠在給定入射光線方向就能夠檢索環境的輻照度,這個可以根據Cubemap采樣進行獲取。

(1)IBL中Specular光照
如果把位置p永遠當作是環境貼圖的中心,那么Diffuse光照積分僅僅依賴于Wi。所以我們就能夠預計算一個新的Cubemap存儲每個采樣方向Wo的Diffuse光照積分結果。

為了計算所有的光線對頂點的影響,需要沿著法線向量方向構造半球,在半球中的所有光線將會對頂點光照產生影響。如圖1所示。

圖1 半球積分
由于直接對Wi進行積分非常困難,可以將其轉換為球面坐標并在上面進行積分,另外由于在越靠近半球下方單位相同角度劃分時將會有更大的面積,需要在結果上乘以權重sin(theta)。

圖2 計算積分時轉化為球面坐標進行計算
輸入一張Cubemap環境貼圖進行IBL中Diffuse光照計算之后將會得到一張模糊化的Irradiance Cubemap。可以直接根據頂點的法線方向采樣Irradiance Cubemap得到最終的Diffuse光照。

圖3 環境貼圖進行Diffuse光照部分積分后效果圖
(2)IBL中Specular光照
Cook-Torrance的Specular光照部分在積分部分上不是常量,積分結果不僅取決于光照入射方向還取決于視線方向。在每所有的入射光線方向,并且包括所有可能的觀察實現方向的積分代價過于昂貴不能實時計算出來。本文使用split-sumapproximation方法來解決這個問題。

第一部分叫做pre-filtered environment map,把粗糙度考慮在內,是一個含有不同mipmap等級的Cubemap,當粗糙度越大時,反射現象越模糊[8]。
并且由于我們在做預計算時此時并不知道觀察方向,我們可以做進一步妥協,假定觀察方向,也就是Specular反射方向總是等于頂點法線方向,用這種方式來去多的觀察方向,同時和前面計算Diffuse光照的時候一樣,也假定物體的位置均是在Cubemap的中心位置。這樣就能直接預計算出含有mipmap等級的Specular光照第一部分。粗糙度等級越高,生成的pre-filtered environment紋理越模糊。

圖4 環境貼圖進行Specular第一部分光照積分后效果
第二部分是Specualar光照的BRDF積分部分。如果我們假定入射的光線在每個方向是完全的白色,我們就能根據給定的粗糙度和由法線和入射光線構成的角度計算出對應的BRDF積分值[9]。這是一張二維的與輸入的環境貼圖的無關的紋理。用采樣得到的值分別對基礎反射率F0進行放縮和偏置,就能夠得到最終的材質反射率數值。

圖5 BRDF二維圖像
對于渲染透明玻璃的材質,折射是光從一種媒介穿到另一種折射率不同的媒介時產生的彎曲現象;
對基本場景生成一副圖像,把該圖像當作紋理,然后對查找該紋理的坐標進行擾動來模擬折射。
基本步驟:
●第一步是把場景集合渲染到一張紋理上,并忽略折射網格(眼鏡模型)。這張紋理可以用來確定哪些物體在折射后方可見的,折射體會在隨后渲染,把這張紋理記為S;
●第二步是畫折射的網格,用擾動過的紋理坐標從紋理S中查找對應的值來模擬折射效果。這種擾動可以用一個發現圖N來完成,用到了法向圖的XY通道,用它們乘以一個很小的值作為紋理坐標的偏移量;
●最后用得到的偏移紋理坐標采樣場景中的背景圖S,就能夠得到折射數據。
在渲染眼鏡之前,預渲染生成包含Diffuse光照的irradiance貼圖,包含Specular光照的prefilter貼圖和放縮偏置基礎反射率的BRDF二維貼圖。同時還需要傳入環境貼圖已經包含頭像的背景貼圖。
基本步驟:
●在View空間下進行計算;根據視線方向,法線方向和玻璃材質的折射率分別計算得到反射光線和折射光線;
●在菲涅耳函數中輸入法線向量方向,視線方向,基礎反射率和粗糙度,便能夠得到反射系數,即反射光線占整體反射加Diffuse光照的比率;進而根據求出Specular光照比例為ks=F,Diffuse光照比例為kd=(1-F)*金屬度;
●接下來便可得到Diffuse光照為:
vec3 irradiance=texture(irradianceMap,ViewNormal3f).rgb;
vec3 diffuse=irradiance*albedo;
●可得到Specular光照為:
vec3 prefilteredColor=textureLod(prefilterMap,Reflect-View3f,roughness*5).rgb;vec2 brdf=texture(brdfLUT,vec2(max(dot(ViewNormal3f,ViewEyeDirect3f),0.0),roughness)).rg;
vec3 specular=prefilteredColor*(F*brdf.x+brdf.y);
●最終得到IBL部分光照為:vec3 ambient=(kd*diffuse+specular)*ao;
●接下來計算折射光照,需要先通過折射光線方向對紋理xy位置進行偏移,再對包含頭像的背景紋理進行采樣,就能得到折射的顏色;
tex+=(normalize(RefractView3f).xy*0.12f);
vec3 refractcolor3f=texture(BackColor,tex).rgb;
●進行包含Diffuse光照,Specular光照,折射光照包含一定比例的混合,同時對最終的顏色進行Tonemap色調映射,將其限制為0到1之間。
Vec3 color=ambient*0.5+refractcolor*0.8;
color=vec3(1.0f)-exp(-color.rgb*2.5f);
在渲染眼鏡之前,首先需要把得到的每一幀的包含人頭部的幀渲染出來,由于需要在折射數據中需要對其采樣并混合,需要將其深度設置為1。再渲染頭部模型,因為眼睛需要戴在頭部模型上面,需要渲染頭部模型保留其深度。最后在渲染虛擬眼睛的時候需要執行深度測試,無縫保留在當前視線下所能真正看到的眼鏡部分,進入頭部模型的眼鏡片段由于執行深度測試將會被丟棄掉。
基本步驟:
●綁定幀緩沖,渲染場景的數據將會被渲染到幀緩沖紋理中,以便后續處理。同時開啟深度測試,并設置深度測試函數參數為小于等于。
●渲染背景紋理,即解析視頻得到的每一幀圖像或者拍攝到的視頻中每一幀圖像。
●設置深度函數參數為小于;渲染頭部模型,此時僅僅在shader中渲染深度。在片段著色器中不執行任何內容。
●開始渲染虛擬眼鏡,在第一次渲染背景時,背景所在的深度全部設置為1。在接下來渲染頭部模型時,由于執行了深度測試,頭部模型的深度將會占據屏幕并對其進行賦值。再接下來進行眼鏡渲染時,由于原有的頭部模型深度已經保存下來,執行深度測試之后,進入頭部模型的虛擬眼鏡片段將會被丟掉。從而保證眼鏡不會出現在人頭部里面的情形,保證了在空間深度下的視覺一致性問題。
在這一節中我們將會給出在不同的輸入視頻,不同的光照環境,不同的角度下,虛擬眼鏡戴在頭部上的效果。實驗環境為 NVIDIA 1060,Win10,VS2013,本文算法的實驗輸入源為提前準備好的真實環境的全景圖,測試的視頻。

圖6 同一背景在不同頭部角度下的渲染結果

圖7 不同背景在相似頭部角度下的渲染結果
我們所提出的方法,通過將傳統的渲染不透明表面物體的Cook-Torrance光照模型與紋理偏移融合起來,IBL光照部分用來作為Diffuse光照和Specular光照,紋理偏移采樣到的背景作為折射光照。通過這種方式提供了一種通用折射渲染方式,同時,由于提供的是真實環境的光照環境貼圖,并將其用于AR眼鏡,將會導致AR眼鏡效果看起來更加真實。在實現過程中,做出一些妥協,包括虛擬眼睛的各個頂點位置均位于Cubemap中心,預計算時的視線方向與法線向量保持一致等,使得能夠對光照貼圖進行預計算,在后期只需要通過方向進行紋理采樣并進行混合即可,極大地提高了渲染效率。
在以后的研究中,將會根據相機拍攝的場景得到不完整的環境貼圖,并通過諸如最近像素法等恢復出整個場景的其他沒有照到的部分,用其進行渲染,做到真正的虛擬眼鏡光照效果在不同的環境條件下都能夠保持對應的光照正確性。