【GPU精粹與Shader程式設計】(五) 《GPU Gems 2》全書核心內容提煉總結 · 下篇
本文由@淺墨_毛星雲 出品,首發於知乎專欄,轉載請註明出處
本文核心內容為《GPU Gems 2》中講到的真實感水體渲染,以及真實感頭髮渲染、通用的折射模擬、改進的Perlin噪聲等次核心內容。
前言
之前和同事們討論水體渲染時,大家說到目前業界水體實時渲染效果領先的遊戲引擎,是Cry Engine。Cry Engine中的水體渲染可謂目前水體渲染方案中的集大成者,汲取了圖形業界近幾十年水體渲染各種思路的精華。以下是Cry Engine 中的水體渲染實時畫面:
注意這是6年前Cry Engine 3的水體渲染實時畫面,很多人感覺其效果已經達到了近乎真實。
而目前的Cry Engine 5,渲染質量還會更勝一籌。
值得開心的是,Cry Engine已經開源,其水體渲染的具體shader實現程式碼可以在Cry Engine原始碼中找到,以下是其中核心程式碼Water.cfx的傳送門,感興趣的朋友不妨瞭解一下:
值得注意的是,本文中提到的一些渲染水體的策略與思路,在Cry Engine 5實現水體渲染中,也有所體現。
OK,下面開始正題。
目錄 · 本文核心內容Highlight
本文將進行重點提煉總結《GPU Gems 2》中的主核心內容有:
- 一、將頂點紋理位移用於水的真實感渲染(Using Vertex Texture Displacement for
Realistic Water Rendering)
本文將進行提煉總結《GPU Gems 2》中的次核心內容有:
- 二、利用畫素著色器分支的高效模糊邊緣陰影(Efficient Soft-Edged Shadows Using Pixel Shader Branching)
- 三、通用的折射模擬(Generic Refraction)
- 四、快速三階紋理過濾(Fast Third-Order Texture Filtering)
- 五、高質量反走樣的光柵化(High-Quality Antialiased Rasterization)
- 六、快速預過濾線條(Fast Prefiltered Lines)
- 七、Nalu Demo中的頭髮動畫與渲染(Hair Animation and Rendering in the Nalu Demo)
- 八、使用查詢表加速顏色變換(Using Lookup Tables to Accelerate Color Transformations)
- 九、實現改進的Perlin噪聲(Implementing Improved Perlin Noise)
- 十、高階高質量過濾(Advanced High-Quality Filtering)
- 十一、Mipmap層級測定(Mipmap-Level Measurement)
I、核心章節提煉篇
一、將頂點紋理位移用於水的真實感渲染(Using Vertex Texture Displacement for Realistic Water Rendering)
【內容概覽】
真實地渲染出水的質感是一個困難的問題,因為水錶面的運動具有高度的視覺複雜性,且水的光影效果也很複雜。而這章中,介紹了為遊戲《太平洋戰機》開發的對海水的真實感渲染技術。
圖 《太平洋戰機》中的海水渲染
【核心要點】
1.1 水體渲染模型的分析
Gems2中這篇文章問世期間(2005年),當時最真實的水體渲染實現方法是基於流體動力學和快速傅立葉變換(FFT)[Tessendorf 2001],但遺憾的是這種方法需要大量的計算,不適用於互動應用程式。
大多數遊戲當時使用的是很簡單的水模型,而其中的大多數採用了法線貼圖來生成視覺細節,優點是計算量小,缺點是很多時候不能提供足夠的真實感,並且不能真實重現水面的波浪。
而本文中介紹了一種能達到簡單法線貼圖方法的速度,但渲染質量類似於FFT方法的水面渲染技術。
1.2 實現思路概覽
本文的水體渲染主要實現思路是基於法線貼圖計算光照的渲染演算法。因為法線圖在高頻的波浪中能夠真實地產生精細的細節,所以將它用於光照的計算。除此之外,還對水模型的幾何表面做了大振幅低頻波浪的擾動。
1.3 水體的表面模擬
水體表面的模型是基於幾張高度圖(Height maps)的疊加,這些高度圖在空間和時間上不斷重複。每張紋理表示一個“諧波(harmonic)”或“倍頻(octave)”頻譜,然後這些紋理被疊加到一起,類似傅立葉分析中的做法。
而這些紋理之所以稱為高度圖,因為其中每個值代表了對應點相對於水平面的高度值。高度圖對於美術同學來說建立非常容易,與建立和渲染灰度圖一樣簡單。利用高度圖,水的動畫引數規約成一些獨立的波,美術同學只要繪出它們的形狀就可以很容易地控制水的動畫。高度圖也對頂點紋理有用:因為可以很容易地對頂點進行豎直方向的位移。
圖18-2 一張用於水面位移的高度圖
通過用不同的空間和時間範圍來結合若干高度圖,可以得到視覺上非常複雜的動畫:
係數A和B以及求和的項數是由經驗決定的,以求達到美學角度上最好的結果,同時減少重複圖案的痕跡。在《太平洋戰機》中,疊加4張高度圖用於計算光照,其中最大範圍的兩張用於位移貼圖。這對模擬動態的海洋表面來說已經足夠了,可選範圍為10cm到40km(10釐米到40千米)之高。
1.4 實現細節概述
可以把所有需要實現的計算分為兩部分:
- 幾何位移計算
- 光照計算
因為水面細分得很精細,所以可以只在片段程式級實現光照計算,而把位移對映的工作移交給頂點級,以減輕片段的負擔。需要注意,如果在頂點級實現光照計算可能產生明顯的走樣,尤其是遠處的物體。
1.5 對高度圖取樣
文中的實現是在每個頂點上對高度圖進行取樣,並且在頂點程式中計算應該取的位移值。為了計算取樣,使用了一箇中心在相機位置的徑向柵格(radial grid)。這個柵格的細分特點是離視點越近則提供越多的細節,如下圖所示
下面的方程表示了徑向柵格上的頂點位置的計算方法:
其中,i=[0..N - 1], j = [0..M - 1]。選擇a0,a1,使
使用這種方法,可以得到根據距離細分的柵格,也體現了一個簡單的層次細節LOD策略。其他方案,如ROAM或SOAR地形渲染演算法,也可以用於此處,但是它們需要在CPU上進行大量計算,會減弱使用頂點紋理的優勢。而我們也可以嘗試在GPU中渲染自適應鑲嵌柵格的高度域。
下面的程式碼列出了著色器的實現細節,用一個徑向柵格對單張高度圖進行取樣。
float4 main(float4 position : POSITION,
uniform sampler2D tex0,
uniform float4x4 ModelViewProj,
uniform float4 DMParameters, // displacement map parameters
uniform float4 VOfs) : POSITION
{
// Read vertex packed as (cos(), sin(), j)
float4 INP = position;
// Transform to radial grid vertex
INP.xy = INP.xy * (pow(INP.z, 4) * VOfs.z);
// Find displacement map texture coordinates
// VOfs.xy, DMParameters.x - Height texture offset and scale
float2 t = (INP.xy + VOfs.xy) * DMParameters.x;
// Fetch displacement value from texture (lod 0)
float vDisp = tex2D(tex0, t).x;
// Scale fetched value from 0..1:
// DMParameters.y - water level
// DMParameters.z - wavy amplitude
INP.z = DMParameters.y + (vDisp - 0.5) * DMParameters.z;
// Displace current position with water height
// and project it
return mul(ModelViewProj, INP);
}
1.6 提高渲染質量與優化效能的一些方案
1.6.1 為雙線性過濾打包高度值
訪問頂點紋理的代價十分昂貴,在舊的GeForce 6系列的硬體上,一個頂點紋理的訪問會在頂點程式中產生明顯的延遲。所以比較合適的策略是把頂點程式中訪問紋理的次數降到最低。另一方面,過濾紋理值非常必要,否則影象質量就會顯著降低。
為了減小插值時紋理訪問的次數,可以用一種特別的方法建立紋理,這樣使每個紋理包含了一次雙線性紋理查詢必需的所有資料。因為高度圖本質上是單通道的紋理,可以把四個高度值打包到一張四通道紋理的一個紋素內,以實現優化。
1.6.2 使用分支避免不需要的工作
即使使用了優化的紋理過濾,渲染水體時,訪問紋理的次數仍然很高,這會嚴重影響效能。一種方法是減少渲染的頂點數,但是這將全面地降低視覺上的細節並且增加失真度。
需要渲染的水體含有大量的幾何資料,但其中有些三角面完全在螢幕之外。對這樣的三角形,頂點程式仍然要進行處理,這其實是一種浪費。如果能跳過在相機視野之外三角形的相關計算,就可以在每個頂點上節約大量的工作。
以下的偽程式碼表達了這個方法的實現:
float4 ClipPos = mul(ModelViewProj, INP);
float3 b0 = abs(ClipPos.xyz) < (ClipPos.www * C0 + C1);
if (all(b0))
{
// Vertex belongs to visible triangle,
// Perform texture sampling and displace vertex accordingly
}
在上面的程式碼中,使用了裁剪空間的頂點位置來確定當前的頂點是否位於視野之中,然後只對需要的頂點進行復雜運算即可。
1.6.3 使用渲染到紋理策略(Render-to-Texture)
仍然可以使用上文提到的,用一張浮點紋理來壓縮儲存高度紋理的方法,先將其作為單獨的pass來執行,以提高執行速度。而在頂點著色器裡面實現多次昂貴的插值操作就變得沒有太多必要。另外,可以用一個更緊湊的16位浮點紋理格式來儲存原始的高度圖。也可以儲存一系列高度圖序列幀作為三維紋理的切片,以使動畫更加流暢。
經過上述優化,我們的渲染迴圈變成了如下兩個pass:
(1)通過使用將單個四邊形渲染為32位浮點紋理的特殊畫素著色器,來組合高度貼圖。而此紋理中的各個紋素對映到徑向柵格的各個頂點。
(2)使用生成的高度貼圖作為頂點紋理來平移徑向柵格頂點。
1.6.4 處理波浪的背面
大量的光照計算是在畫素著色器中實現的。其假設了水面是水平的,而這個假設在某些情況下可能導致視覺效果的走樣。
在下圖所示的情況下,我們看到了波浪的背面,它在平面上是能被看見的,但是因為幾何位移的關係它會背向觀察者,所以在現實世界中並不應該出現。而這樣的錯誤會在波浪的頂部產生奇怪的過亮區域。
圖 渲染走樣的產生
圖注:波浪(綠色)的背面也可能被渲染出來,儘管它並不應該出現。調整計算光照的法線將大大減少這種錯誤。
為了儘量減少這種錯誤,可以將計算光照時使用的法線稍微做調整,將他們朝向觀察者方向“傾斜”一些,這樣他們會更接近於波浪的正向面。
1.7 渲染區域性擾動的策略
有時渲染渲染因為浮起物或者掉入水中的物體引起的波浪區域性的起伏。這對遊戲來說尤為重要,因為遊戲需要產生類似於爆炸,船的行進痕跡等效果。因為很難繼承物理上正確的方法將其用於這個基於高度圖的水面模型中來,所以這裡只根據經驗討論一些簡單的方法。
1.7.1 解析型形變模型(Analytical Deformation Model)
造成區域性波浪起伏最簡單的方法是把頂點的位移值做成一個解析上的擾動,把擾動和頂點著色器中計算好的頂點位置結合起來。
實現區域性波浪起伏最簡單的方法是通過將頂點位移與頂點著色器中計算的頂點位置相結合,來解析地擾動位移的頂點位置。對爆炸而言,可以用下面的公式:
其中,r是水平面上該點到爆炸中心的距離,b是一個常數,I_0,ω和k的值根據一個給定的爆炸及其引數決定。
在渲染時,可以使用和普通水體渲染時相同的徑向柵格,尤其是在爆炸點。
1.7.2 動態位移貼圖(Dynamic Displacement Mapping)
另一個選擇是將所有的區域性建立的位移量直接渲染到頂點紋理,本質上是和GPU通用程式設計(GPGPU)類似的方法。這樣,在第一個pass中生成頂點紋理,而在後續pass中,用此紋理來進行實際的水體渲染。另一個好處是,通過在畫素著色器中過濾基礎高度圖和累加倍頻程(octaves),可以把一些工作從頂點著色器轉移到畫素著色器中。
為了計算位移量,既可以採用前面提到的解析型模型,也可以用自動控制單元(cellular-automata)的方法,將區域性位移進行逐幀衍變。也可以考慮風的效果,對紋理沿著適當的方向進行模糊。
圖 用位移貼圖渲染的水錶面(左)和不用位移圖渲染的水錶面(右)對比
1.7.3 泡沫的生成(Foam Generation)
在波浪足夠強時,可以通過製造泡沫來加強真實感。最簡單的方法是把一個預先建立的泡沫紋理在高於某一高度H0的頂點上進行混合。泡沫紋理的透明度根據以下公式進行計算:
其中,H_max是泡沫最大時的高度,H_0是基準高度,H是當前高度。
泡沫紋理可以做成動畫來表示泡沫的產生和消失的進化過程。這個動畫序列既可以由美術同學製作,也可以由程式生成。
【核心要點總結】
本文的水體渲染實現思路是基於法線貼圖計算光照的渲染演算法,水體表面的模型為基於幾張高度圖(Height maps)的疊加。在每個頂點上對高度圖進行取樣,並且在頂點程式中計算應該取的位移值。計算取樣方面,使用了一箇中心在相機位置的徑向柵格(radial grid),以及結合了一些優化的策略。
1.提高渲染質量與優化效能的方案
1)為雙線性過濾打包高度值:因為高度圖本質上是單通道的紋理,可以把四個高度值打包到一張四通道紋理的一個紋素內,以實現優化。
2)使用分支避免不需要的工作:使用裁剪空間的頂點位置來確定當前的頂點是否位於視野之中,然後只對需要的頂點進行復雜運算即可。
3)使用渲染到紋理策略(Render-to-Texture)
4)處理波浪背面:將計算光照時使用的法線稍微做調整,將他們朝向觀察者方向“傾斜”一些,這樣他們會更接近於波浪的正向面。
2.渲染區域性擾動的策略
1)解析型形變模型(Analytical Deformation Model)
2.動態位移貼圖(Dynamic Displacement Mapping)
3.泡沫的生成:預先建立的泡沫紋理在高於某一高度H0的頂點上進行混合,其中泡沫紋理的透明度根據公式進行計算。
【配套原始碼】
這篇文章公開了其詳細的實現原始碼,具體可以在這裡找到:
其中shader程式碼位於fpWaterDM.cg,vpWaterDM.cg兩個檔案中。其中也提供了可執行的demo exe,其執行效果如下:
【關鍵詞】
水渲染(Water Rendering)
頂點紋理位移(Vertex Texture Displacement)
高度貼圖(Height Mapping)
雙線性過濾(Bilinear Filtering)
II、次核心章節提煉篇
二、利用畫素著色器分支的高效模糊邊緣陰影(Efficient Soft-Edged Shadows Using Pixel Shader Branching)
【章節概覽】
在計算機圖形學中,渲染真實的陰影一直是難題之一,尤其是軟陰影(soft shadow)的渲染。且陰影是一種非常重要的視覺資訊,它們有助於確立場景中物體的空間相對關係。
這章介紹了一種通過片段著色器中的PCF技術達到的實時渲染模糊(軟)邊界陰影的快速方法。
【核心要點】
文中首先講到陰影渲染技術中最常見的兩種流派模板陰影/陰影體(Stencil Shadow / Shadow volume)和陰影貼圖(Shadow Map)。
兩種方法都各有其優缺點。且提到了這兩種方法都不能直接用於“超出框”的模糊邊界陰影。
隨後這章介紹了一種以互動速率渲染模糊陰影的方法,其能高質量地模擬真實的模糊陰影。該方法使用了百分比鄰近過濾(Percentage-Loser Filtering, PCF)技術,在片段著色器中不斷對陰影圖自適應地多次取樣。這章自適應的取樣方法與取樣方法與取樣數固定的方法相比,能在保證高效能的同時提高畫面質量。
圖 基於文中方法實時渲染出的模糊邊緣陰影
【關鍵詞】
軟陰影(Soft Shadows)
模糊邊緣陰影(Soft-Edged Shadows)
模板陰影/陰影體(Stencil Shadow /Shadow volume)
陰影貼圖(Shadow Map)
百分比鄰近過濾(Percentage-Loser Filtering, PCF)
三、通用的折射模擬(Generic Refraction)
【章節概覽】
本章介紹了一種折射的實現方案,思路是對場景中非折射的物體生成一幅影象,把該影象當做紋理,然後對查詢該紋理的座標進行擾動來達到模擬折射的目的。這種技術效率很高,而且很多情況下都有效。
【核心要點】
折射(Refraction)是當光從一種媒介穿到另一種折射率不同的媒介(如從空氣到水,從空氣到玻璃等)時產生的彎曲現象。
要模擬折射有很多種方法:其中一些方法是先預計算環境對映,然後在執行時使用;而其他方法是直接在執行時計算環境對映。這些技術的缺點是耗費大量的紋理儲存空間並損失執行效率,尤其是當場景中有很多折射表面時,需要不同的環境對映。
而目前的水折射模擬技術的另一個問題是他們需要渲染兩遍:第一個pass通過水麵上的幾何資訊來生成折射圖,另一個pass渲染水面。這種方案的效能很低,尤其對複雜的場景而言。
本章介紹了一種簡單的技術來克服這些問題。從介紹基本想法開始,把現有的後臺快取當做一個折射貼圖來用,並且通過對紋理座標進行位移來模擬折射的效果。最基本的實現可能導致走樣,因此文中討論瞭如何將幾何圖形從折射圖貼圖中標註出來。最後演示了一些用該方法渲染真實的水和玻璃的通用技術。
圖 彩色玻璃的渲染步驟(a)折射 (b)環境凹凸對映 (c)最終的合成
這章給出的模擬折射的方法,雖然不是基於物理的,但是能得到質量很好的結果,且速度非常快。
但此方法的缺陷是,當應用到不同顏色的折射表面上時,在表面重疊的地方會得到不正確的結果。只要折射表面的顏色相近,結果看上去就是正確的。一個正確的解決方案就是,對摺射網格從後到前進行排序,然後每次渲染一個折射網格時都更新一次折射圖。或者用另一個不夠準確的方案,對摺射網格從後到前進行排序,在用alpha混合來渲染它們。
【關鍵詞】
折射(Refraction)
水的渲染(Water Rendering)
玻璃的渲染(Glass Rendering)
四、快速三階紋理過濾(Fast Third-Order Texture Filtering)
【章節概覽】
對可程式設計圖形硬體可以在使用片段著色器上使用通用的卷積過濾器來實現高質量的紋理過濾,如立方(cubic)過濾器[Bjorke 2004]。這些方法通常有許多缺點:它們需要進行多次紋理取樣,而且無法對mipmap的紋理進行反失真處理。
而在本章中,介紹了一種能有效減少三階紋理過濾需要輸入的紋理數量的方法,使用了1D、2D及3D空間中的三次B樣條(B-spline)曲線的卷積核和它的一階、二階導數來解決這些過濾問題。
【核心要點】
高階紋理過濾的主要效能瓶頸是需要大量的紋理取樣作為輸入。通常是通過對輸入紋理進行重複最近鄰近(Repeated Nearest-Neighbor)取樣實現。為了減少採樣的次數,基於線性取樣來建立過濾器,這種方法能大量減少紋理取樣的次數,尤其是2D和3D過濾。特別是能通過8次三線性紋理取樣來完成一個需要64次累加操作的三立方(tricubic,也譯作三重三次)過濾器。
圖 三次B樣條(Cubic B-Spline)和其導數
(a)f_1和過濾器權重w_i(x)的卷積
(b)三次樣條曲線的一階導數;(c)三次樣條曲線的二階導數
總而言之,本章介紹了一個能有效減少高階紋理過濾需要的對輸入紋理進行取樣的次數。而前提是假設一個線性取樣操作和一個最鄰近取樣一樣快(至少不慢太多)。對三階過濾器核(如三次B樣條)曲線過濾器進行了優化,讓它只需要非常少的線性紋理取樣次數。
而事實上,片元著色器裡的程式碼更像一個手工寫的線性插值程式,而不是一個立方過濾器。
【關鍵詞】
紋理過濾(Texture Filtering)
高階過濾(Higher-Order Filtering)
B樣條過濾( B-Spline Filtering)
三次B樣條(Cubic B-Spline)
快速遞迴三次卷積(Fast Recursive Cubic Convolution)
五、高質量反走樣的光柵化(High-Quality Antialiased Rasterization)
【章節概覽】
這章介紹了一種分塊的超取樣(supersampling)技術,使用任意寬度和高取樣率的自定義過濾器,可以用來渲染任意解析度的影象,以實現高質量的反走樣光柵化。
【核心要點】
如上所言,文中介紹了一種分塊的超取樣(supersampling)技術,描述瞭如何把一個影象分成塊(tiles,也稱為buckers),用高解析度渲染每一塊,然後降取樣(downsample,即收縮)每一塊以達到最終解析度,在即使構造的片元程式中使用分離式的降取樣。文中也介紹瞭如何在影象分塊之間進行正確的重疊和延伸的細節問題。文中提供的程式碼可以很輕易地整合到現有的渲染系統中,而不需要對現有的程式碼進行大的改動。
圖 將影象分解成tiles
對於最終影象的每一個分塊,總體演算法如下:
(1)把影象塊渲染到一個大的離屏緩衝區中,調整投影矩陣,以現有的渲染程式碼把3D幾何體用高取樣率的解析度渲染出來。
(2)把高解析度的影象塊用一個分離式的過濾器核進行降取樣,通過使用實時生成的片元程式在螢幕上渲染兩個全屏的四邊形來實現。
(3)把低解析度的影象塊累加到最終影象中,或通過把影象塊的資料讀回到CPU中,或使用另外一個片元程式把影象塊加入到最終影象中。
【關鍵詞】
反走樣光柵化(Antialiased Rasterization)
分塊超取樣(tiled supersampling)
降取樣(downsample)
六、快速預過濾線條(Fast Prefiltered Lines)
【章節概覽】
這章介紹了一種簡單有效的繪製反走樣(抗鋸齒)的線條的方法。
【核心要點】
本章提到的預過濾(Prefiltered)方法最早由McNamara, McCormack, 和 Jouppi在2000年提出,其有諸多優點。首先該方法能使對稱的過濾器在執行時提供固定的開銷;其次,和一般硬體支援的過濾器不同,本方法不僅僅對只處於畫素內的點進行取樣,它能支援更大範圍的過濾器,反走樣的結果是硬體無關的,這保證了在不同GPU上能得到相同的反走樣結果。
圖 比較細線和粗線的反走樣效果
總之,通過對從中心到邊界不同距離處,把直線和過濾器的卷積結果進行卷積,並將結果儲存在一個查詢表中來預過濾線條。
該方法允許相同的執行時開銷開使用任意的對稱過濾器。而且,該演算法只需要很少的CPU和GPU運算、頻寬及儲存空間開銷。這些特性使這種演算法對大部分的實時渲染程式都有實用價值,如繪製圍欄、電線以及遊戲中其他細長的物體。
【關鍵詞】
預過濾線條(Prefiltered Lines)
反走樣/抗鋸齒(Antialiasing )
線條的反走樣(Antialiasing Lines)
七、Nalu Demo中的頭髮動畫與渲染(Hair Animation and Rendering in the Nalu Demo)
【章節概覽】
這章講到了NVIDIA公司的Nalu Demo中的頭髮動畫和渲染技術。
圖 Nalu的頭髮
【核心要點】
NVIDIA的Nalu demo中,要達到的目標是渲染在水中飄動的金色長髮。這章將介紹用於實時達到這個目標所用的技術。這種技術包含一個模擬頭髮運動系統,一個計算頭髮自陰影的陰影生成演算法,還有一個通過每一串頭髮來模擬光線散射的發射模型。把這些結合起來,就能實時創建出極其真實的頭髮渲染效果。
在Nalu頭髮的後臺著色處理中,有一個在每幀裡生成頭髮幾何和控制動感與碰撞的系統。基本上分成兩部分:幾何生成器和動感/碰撞的計算。
這些頭髮是由4095條用直線圖元來渲染的獨立髮絲組成。僅僅在渲染頭髮上就使用了123000個頂點。讓所有這些頂點通過動力學和碰撞檢測就將慢得無法接受,因此使用受控髮絲(control hair):儘管需要渲染成千次,但Nalu的髮型能通過一組每組幾百根髮絲來描述和控制。所有開銷大的動態計算都運用於這些受控髮絲。
頭髮的實時反射模型方面,選用了Marschner反射模型(2003)。而在渲染頭髮的陰影方面,採用了一種針對渲染頭髮陰影設計的近似陰影——非透明陰影圖(Opacity shadow maps)(Kim and Neumann 2001)。
圖 基於Marschner反射模型的頭髮渲染
圖 Marschner反射模型的查詢紋理(Lookup Textures)
【關鍵詞】
頭髮渲染(Hair Rendering)
頭髮動畫(Hair Animation)
Marschner反射模型(Marschner Reflectance Model)
非透明陰影圖(Opacity Shadow Maps)
八、使用查詢表加速顏色變換(Using Lookup Tables to Accelerate Color Transformations)
【章節概覽】
這章中,介紹了一種利用三維查詢表的演算法來實時處理高解析度影象的方法。
【核心要點】
在函式的計算開銷很大,但是把計算結果快取起來的開銷比較小時,用查詢表(Lookup
Table,簡稱LUT)優化這種函式的計算是一種非常好的方法。通過預先把一些常見輸入的對應結果計算出來,花費不多的查詢操作就能代替開銷較大的執行時計算。如果查詢比開頭開始計算結果(或者有不斷重複的相同輸入)要快,那麼使用查詢表就能提高程式效能。
這章中,介紹了一種利用三維查詢表的演算法來實時處理高解析度影象的方法。這種方法有非常出色的效能,它與執行顏色操作的數量無關,與顏色操作的複雜度也無關,即能獨立於顏色運算的數量和顏色變換的複雜度。涉及到的主要實現有,把查詢表對映到GPU、著色器的實現、系統整合以及把三維查詢表擴充套件到高動態範圍影象等步驟。
圖 一個三維的查詢表
圖 顏色校正流水線的比較。左圖為傳統的顏色校正流水線,通過傳送低解析度的影象來用作硬體加速的基礎。右圖為基於三維查詢表的加速流水線。
【關鍵詞】
查詢表(Lookup Table, LUT)
顏色變換(Color Transformations)
九、實現改進的Perlin噪聲(Implementing Improved Perlin Noise)
【章節概覽】
這章上接《GPU Gems 1》中奧斯卡得主大牛Ken Perlin撰寫的第五章[Perlin
2004],《GPU Gems 1》中Ken Perlin的章節討論了該如何使用3D紋理實現過程噪聲的快速近似,在這裡描述一個改進噪聲演算法的GPU實現,其也完全符合用CPU進行實現。
【核心要點】
Perlin演算法由兩個主要階段組成。
第一階段在3D空間的每個整數(x,y,z)位置產生一個可重複的偽隨機值。這可以以多種方式思想,但是Perlin的演算法是使用一個雜湊函式。雜湊函式基於一個包含以隨機順序0~255的整數排列的表(這張表可以在實現之間進行標準化,以便它們產生相同結果)。首先,這張表是基於位置的x座標索引,然後將y座標新增到表中該位置的值中,並使用結果再次在表中查一次表。然後為z座標重複一次此過程。對z座標重複此過程後,結果為每個可能的(x,y,z)位置的偽隨機整數。
在演算法中的第二階段,將上述偽隨機整數用於索引入一個3D梯度向量的表中。在“改良的”演算法中,只用8個不同的梯度。這個梯度和噪聲空間中的小數位置求點積可以得到一個標量值。最後的值通過空間中相鄰8個點的噪聲值插值獲得。
Perlin改良的噪聲演算法是將CPU實現的排列表和梯度表儲存在陣列中。由於畫素著色器當時不支援索引入常量儲存器中,所以將這些表儲存在紋理中,並使用紋理查詢來訪問它們。紋理定址設為環繞(或重複)模式,因此不必考慮擴充表以避免索引越過陣列結尾,如同在CPU實現中一樣。
本章介紹了對畫素著色器中的程式化噪聲的實現。程式化噪聲是豐富渲染外觀一個重要的部分,而且它可以用於凹凸貼圖和其他效果。
圖 基於過程凹凸貼圖的pixel著色器噪聲
【關鍵詞】
Perlin噪聲(Improved Perlin Noise)
改進的Perlin噪聲(Improved Perlin Noise)
十、高階高質量過濾(Advanced High-Quality Filtering)
【章節概覽】
這章提供了一個基於GPU紋理過濾的實現細節和解決方案,其中重點放在紋理插值和反走樣問題。
【核心要點】
本章闡述了一系列用於渲染紋理表面的高質量紋理過濾方法。這些技術可以用來執行許多常見的影象任務,如縮放、扭曲、銳化等。除此之外,用這些方法渲染簡單的帶紋理的3D場景時,還可以提供比圖形硬體上的標準過濾器更好的渲染效果。
這章提到的技術是為質量最優的渲染而設計的,對高幀率的實時互動的程式和遊戲來說依然顯得昂貴,它更適合哪些渲染質量比速度更重要的程式,如醫療和科學影象、照片和電影編輯、圖片合成、視訊格式轉換、專業3D渲染等。它也能用於遊戲中與解析度無關的紋理準備(預處理)當中。
另外,文中還介紹了一種適合用於增強重建影象的銳化過濾方法——衝擊過濾衝擊過濾(Shock Filtering),其能把紋理插值平滑地變換成陡峭的變換。
圖 衝擊過濾(Shock Filtering)方法
【關鍵詞】
GPU紋理過濾(GPU-based texture-filter)
紋理插值( texture interpolation)
反走樣/抗鋸齒(antialiasing )
衝擊過濾(Shock Filtering)
十一、Mipmap層級測定(Mipmap-Level Measurement)
【章節概覽】
這章講到了使用“偽著色”(false-colored)的mipmap來代替原來的多級紋理進行場景渲染的方法。這樣的mipmap每層都有不同的比對色。且這章展示瞭如何用GPU來自動化偽著色的整個過程。
【核心要點】
偽著色(false-colored)的mipmap,結合基於GPU的方法,可以高效地運用在遊戲引擎中,可見的mip層次將被動態地反饋入引擎的紋理管理程式以減少記憶體消耗量。而所節省的記憶體可以用來增加別處的紋理解析度,改進場景的華麗程度。Climax在Leviathan引擎中對地形場景使用了這項技術,使紋理空間節約了80%的記憶體,並沒有任何可察覺的視覺質量損失。
圖 對地形場景應用偽著色mipmap方法
圖(a)地形場景適用Climax的Leviathan引擎渲染(b)通過下圖“定標紋理”,將原紋理替換成偽著色的mipmap後的效果。可以看到最高的層(黃顏色)幾乎不可見。
圖 定標紋理
【關鍵詞】
紋理管理(texture management)
偽著色(false-colored)
Mipmap層級(Mipmap-Level)
本文的GitHub版
不少朋友們喜歡看GitHub版本的文章,我也很喜歡。
首先,MarkDown可以很方便地插入快捷導航目錄,能進行瞬間跳轉到指定子章節。其次,GitHub版本的文章中沒有單篇文章的字數限制,少了很多篇幅方面的桎梏。而且因為Git的便利性,版本管理的優勢,最新的勘誤和修訂,以及新文章的更新,第一時間會在GitHub的Repo中進行。
【本文的GitHub版本傳送門】:
附錄:配套資源與原始碼下載
這裡提供了一些,《GPU Gems 2》書本的配套資源以及原始碼的下載地點。
PS:配套的不少工程中不僅包含完整的原始碼,也直接包含經過編譯後的exe執行檔案,可以直接執行後檢視效果。
《GPU Gems 2》全文的Web版本:
也有維護一個名為“GPU-Gems-Book-Source-Code”的GitHub倉庫,以備份《GPU Gems》系列書籍相關的珍貴資源,《GPU Gems 2》的隨書CD和原始碼可以在這裡下載到:
以上。