天天看點

完全了解Unity中PreCompute Realtime GI及其優化(一)

   Unity作為目前最流行的遊戲開發引擎,在移動端也提供了良好的光照效果,幫我們建構更加真實的遊戲場景。我們知道,一個遊戲場景的真實與否,效果是否出色,有一部分來自光照。逼真的光照,總能表現出令人贊歎的效果。但要完全模拟現實中的光照,對CPU來說卻是一件不可能完成的任務。通常,我們會使用一些方法來近似模拟這些效果。比如烘焙光,光照貼圖,陰影貼圖等。    在Unity中的預計算全局光照有兩種,烘培光和預計算全局光。後者在Unity中被稱作Precompute Realtime GI,準确的說應該稱為預計算實時全局光。那麼問題來了,既然是實時,又怎麼是預計算的呢?

一.什麼是預計算實時全局光

我們知道,無論是烘焙全局光照,還是預計算實時全局光照,都是Unity為了提供更複雜的光照效果,同時避免實時光照計算在運作時帶來的大量的性能消耗而産生的解決方案。Unity中的預計算實時全局光,和烘焙全局光類似。不同的是,它不但預計算了我們在建構場景時,已經設定好的光在該表面中的反射,同時它還計算了任意可能的光,在該表面會造成的反射效果,這就是它和烘焙全局光不同的地方。

烘焙全局光隻能處理靜态的物體,并且其光源在運作時和烘焙時需要保持一緻,可以認為是一個完全靜态的場景。預計算全局光将各種可能的光照的反射資訊預計算後,編碼儲存起來,供運作時使用。因為,雖然也要求針對靜态的物體,但卻可以處理在運作時,有一定改變的光源。它的适應性比烘焙全局光更好。是以我們可以通過它獲得更好的光照效果,和比較好的運作時性能表現。當然,在預計算階段,它要做的工作就相對要多一點,這也是我們要針對它進行優化的原因。

二.概念

現在我們已經了解了什麼是預計算實時全局光,在進一步介紹如何使用和優化預計算全局光之前,我覺得有必要先給大家介紹下其中要涉及到的幾個概念。

(1)texel紋素

所謂的紋素,就是根據一個uv坐标,在貼圖上采樣出的那一個像素,被稱為紋素。紋素擁有了在指定uv坐标下的貼圖資訊。如果是材質貼圖,就包含了色彩資訊。對于本篇所讨論的光照貼圖而言,就是相應的光照資訊。

(2)Realtime Resolution 實時光照分辨率

決定了在世界空間下,1機關能擁有多少紋素。

比如當該值為1時,就代表了Unity中的1機關擁有一個紋素。當其大于1是,就代表1機關擁有更多的紋素,其小于1時,代表需要多個機關來使用1個紋素。因為一個單元需要的紋素越多,那麼相應的light map的分辨率就越大。分辨率的上升,會帶來細節的提升,但是也會對記憶體,性能造成影響。這在後面我們會進一步解釋。

值得注意的時,unity對于這個概念的說明其實很容易造成了解上的誤區,使我們認為,這個值其實就是直接決定了最終生成的light map的分辨率。實際上,這個值仍隻是一個系數,它間接影響light map的分辨率。它将和後面提到的lightmap parameter參數中的Resolution相乘來得到最終的分辨率大小。最終的分辨率大小是基于每個物體的,并不是說我們設定了Realtime Resolution後,整個場景的光照貼圖就是統一按這個分辨率生成了。

Q:那麼Realtime Resolution有什麼用呢,為什麼不直接使用lightmap parameter參數中的Resolution呢? A:這是因為,如果沒有這樣一個參數的化,就需要手動的為每一個需要烘焙進light map的物體設定lightmap Parameter,通過其中的lightmap Resolution來指定分辨率。當場景中我們有大量的物體時,這個工作就變的不是很有效率了。是以通過Realtime Resolution可以對場景的大部分物體指定一個預設的分辨率,來簡化這一過程。

其實,在lightmap的Setting視窗中,也是可以指定一個lightmap Parameter的。Unity可以使用這個lightmap parameter資料來指定場景預設的lightmap的分辨率,這樣就不需要增加一個Realtime Resolution的概念。但可能是考慮到如果這樣的話,對分辨率的調整就需要修改項目中所有的lightmap parameter,而不能簡單的通過調整一個Realtime Resolution來進行縮放吧。這個屬于我的分析,是以也不要太在意,重要的是了解Realtime Resolution的作用和使用方法。

(3)Vexel 體素

體素也不是Unity所獨創的一個概念,百度的話,可以得到如下的解釋:

 一如其名,是數字資料于三維空間分割上的最小機關,體素用于三維成像、科學資料與醫學影像等領域。

其實簡單的了解,我們可以認為是3D空間的像素。我們知道像素在2D中是正方形的,那麼相應的體素就是正方體了。那麼一個3D空間的模型體素話後,就是有許多的正方體構成的(想象一下MineCraft)

(4)Cluster 簇

如果使用Google翻譯,那翻譯成的是叢集,但是我認為從其概念上代表的更像是一個機關,是以我用簇來代替,因為在磁盤系統中有簇這個概念,而我覺得在這裡,unity想表示的更接近這個概念,是以我就用簇來翻譯cluster,如果有更恰當的翻譯,也歡迎告知。

好,言歸正傳。簇簡單的了解就是場景的體素化代理。在這裡,我想解釋的是代理(proxy)這個過程,了解了它,也就能很好的了解簇了。代理,在這裡是我們使用體素來表示靜态場景幾何模型的表面,并将這些體素用于光照計算的這樣一個過程。我們将複雜的幾何表面,通過體素化,簡化為一個個由立方體所代表的表面。然後由這些立方體的某一個表面組成我們要進行光照計算的幾何表面。這時,這些體素就被稱為簇(cluster)

(5)UV Shell

UV Shell是一個美術更能了解的概念。因為這在拓展UV上會經常接觸到。我并不是專業的美術,隻是學過一點皮毛,是以這裡就勉為其難的從開發的角度說一些我對這個概念的認知。 UV Shell是拓展模型UV時,一塊模型拓展後的區域就是shell,一個模型可能會被拓展成一個shell,或是多個,這取決于拓展的方式方法和技術。

我們知道一個模型可能有很多的面(這裡不是值頂點構成的三角形面,而是從更直覺的認知上看到的面)。比如一個正方體,就有六個面。展uv時,我們可以将這6個面展成一個(cubemap)區域,也可以展成6個區域。那麼這個區域就是shell。如果對于更複雜的模型,同樣的,也許我們有辦法将整個模型的面展成一個區域,也可能因為面的複雜度,我們要展成多個區域。無論如何,知道區域就是shell就可以了

(6)UV Chart

和UV Shell相關的概念,就是uv chart。這個概念應該是unity中提出的。首先我們需要記住,chart是一個正方體的小塊。我們展好的shell,它的輪廓則是任意的,我們用N個chart來覆寫這個輪廓的區域,那麼最終形成的一塊邊全是由正方形組成的區塊,就是uv chart

總結:

     以上就先把相關涉及到的概念和知識點做一個簡單的說明,接下來就會來介紹預計算全局光照中具體的概念的作用和相關的優化方法。

繼續閱讀