【GPU精粹與Shader編程】(三) 《GPU Gems 1》全書核心內容提煉總結 · 下篇


本文由@淺墨_毛星雲 出品,首發於知乎專欄,轉載請註明出處  

文章鏈接: https://zhuanlan.zhihu.com/p/36499291



題圖背景來自《神祕海域4》。


系列文章前言


《GPU Gems》1~3 、《GPU Pro》1~7 以及《GPU Zen》組成的饕餮盛宴,共11本書,合稱“GPU精粹三部曲“,是遊戲開發、計算機圖形學和渲染領域的業界頂尖大牛們一線經驗的合輯彙編,是江湖各大門派武林絕學經典招式的精華薈萃,是瞭解業界各種高階知識和技法Trick,將自己的遊戲開發、圖形學與渲染能力提升到下一個高度的捷徑。



本文內容概覽與關鍵詞


本篇文章將總結提煉“GPU精粹三部曲“11本書中的第一本《GPU Gems 1》全書的核心內容的下半部分,是【GPU精粹與Shader編程】系列文章正篇的第二篇,全文共1萬5千餘字。

本文內容的關鍵詞:

  • 真實感皮膚渲染(Realistic Skin Rendering)
  • 次表面散射(Subsurface Scattering)
  • 環境光遮蔽(Ambient Occlusion)
  • 實時輝光(Real-Time Glow)
  • 陰影的渲染(Shadow Rendering)
  • 透視陰影貼圖(Perspective Shadow Maps)
  • 逐像素光照的可見性管理(Managing Visibility for Per-Pixel Lighting)
  • 空間BRDF(Spatial BRDFs)
  • 基於圖像的光照(Image-Based Lighting,IBL)
  • 紋理爆炸(Texture Bombing)
  • 顏色控制(Color Controls)
  • 景深 (Depth of Field)
  • 高品質的圖像濾波(High-Quality Filtering)
  • 快速濾波寬度的計算(Fast Filter-Width Estimates )
  • 高動態範圍(High-Dynamic-Range , HDR)


本文的GitHub版本


不少朋友們喜歡看GitHub版本的文章,我也很喜歡。

首先,MarkDown可以很方便地插入快捷導航目錄,能進行瞬間跳轉到指定子章節。其次,GitHub版本的文章中沒有單篇文章的字數限制,少了很多篇幅方面的桎梏。而且因爲Git的便利性,版本管理的優勢,最新的勘誤和修訂第一時間會在GitHub的Repo中進行。

【本文的GitHub版本傳送門】:

QianMo/Game-Programmer-Study-Notes



目錄 · 核心內容導航Highlight


【說明】下文目錄中加粗的標題爲本文將包括的內容,非加粗的標題已在上次的更新(GPU
Gems 1》全書核心內容提煉總結 · 上篇)中發佈。

另外需要注意,本文將原來在上篇中目錄爲次核心內容的“二十一、實時輝光(Real-Time
Glow)”提升爲了主核心內容,現爲“六、實時輝光(Real-Time Glow)”。


本文將進行重點提煉總結的主核心內容有:

  • 一、用物理模型進行高效的水模擬(Effective Water Simulation from Physical
    Models)
  • 二、Dawn Demo中的皮膚渲染(Skin in the Dawn Demo)
  • 三、無盡波動的草地葉片的渲染(Rendering Countless Blades of Waving Grass)
  • 四、次表面散射的實時近似(Real-Time Approximations to Subsurface Scattering)
  • 五、環境光遮蔽(Ambient Occlusion)
  • 六、實時輝光(Real-Time Glow)

本文將進行提煉總結的次核心內容有:

  • 七、水焦散的渲染 (Rendering Water Caustics)
  • 八、 Dawn Demo中的動畫(Animation in the "Dawn" Demo)
  • 九、 改良的Perlin噪聲實現(Implementing Improved Perlin Noise)
  • 十、Vulcan Demo中的火焰渲染(Fire in the "Vulcan" Demo)
  • 十一、衍射的模擬(Simulating Diffraction)
  • 十二、高效的陰影體渲染(Efficient Shadow Volume Rendering)
  • 十三、電影級光照(Cinematic Lighting)
  • 十四、陰影貼圖抗鋸齒(Shadow Map Antialiasing)
  • 十五、全方位陰影映射(Omnidirectional Shadow Mapping)
  • 十六、使用遮擋區間映射產生模糊的陰影(Generating Soft Shadows Using Occlusion Interval Maps)
  • 十七、透視陰影貼圖(Perspective Shadow Maps: Care and Feeding)
  • 十八、逐像素光照的可見性管理(Managing Visibility for Per-Pixel Lighting)
  • 十九、空間BRDF(Spatial BRDFs)
  • 二十、基於圖像的光照(Image-Based Lighting)
  • 二十一、紋理爆炸(Texture Bombing)
  • 二十二、顏色控制(Color Controls)
  • 二十三、景深 (Depth of Field)
  • 二十四、高品質的圖像濾波(High-Quality Filtering)
  • 二十五、用紋理貼圖進行快速濾波寬度的計算(Fast Filter-Width Estimates with Texture Maps)
  • 二十六、OpenEXR圖像文件格式與HDR(The OpenEXR Image File Format and HDR)

PS : 因爲知乎專欄單篇文章字數限制在1萬5千字的原因,本文的“第二部分 · 次核心內容提煉總結”中所有小結的【本章配套源代碼彙總表】子欄目,以及參考文獻,將在下文中略去。需要查看這些額外內容的同學,請移步至本文的GitHub版本:

QianMo/Game-Programmer-Study-Notes



《GPU Gems 1》配套資源與源代碼


這一節提供了一些,《GPU Gems 1》書本的相關鏈接,以及配套源代碼的下載。

PS:配套的不少工程中不僅包含完整的源碼,也直接包含經過編譯後的exe執行文件,可以直接運行後查看效果。

  • 原書全文的Web版本:

developer.nvidia.com/gpugems/GPUGems/gpugems_pref01.html

  • 我維護了的一個名爲“GPU-Gems-CD-Content”的GitHub倉庫,並整理好了《GPU Gems》1~3 書本全部的配套工程與源代碼,逐章內容的快捷導航,以備份、珍貴、快速查閱這些優質資源:

github.com/QianMo/GPU-Gems-Book-Source-Code



第一部分 · 主核心內容提煉總結



四、次表面散射的實時近似(Real-Time Approximations to Subsurface Scattering)


【章節概覽】


次表面散射(Subsurface Scattering),簡稱SSS,或3S,是光射入非金屬材質後在內部發生散射,最後射出物體並進入視野中產生的現象,即光從表面進入物體經過內部散射,然後又通過物體表面的其他頂點出射的光線傳遞過程。


                                                                           圖 次表面散射原理圖示


圖 真實世界中的次表面散射


要產生使人信服的皮膚和其他半透明材質的渲染效果,次表面散射(Subsurface Scattering)的渲染效果十分重要。


圖 有無次表面散射的皮膚渲染對比圖(左圖:使用次表面散射 | 右圖:無次表面散射)


另外需要提出,在《神祕海域4》中皮膚的渲染效果,很令人驚豔。當然,《神祕海域4》中令人驚豔的,遠遠不止皮膚的渲染。

圖 基於次表面散射的皮膚渲染 @《神祕海域4》


本章即描述了次表面散射的幾種實時近似方法,關於皮膚的渲染,也關於近似地去模擬透明材質的幾種不同方法。


【核心內容提煉】


4.1 次表面散射的視覺特性(The Visual Effects of Subsurface Scattering)


要重現出任何視覺效果,經常的做法是考察這種效果的圖像,並把可視的外觀分解爲其組成要素。在觀察半透明物體的相片和圖像時,能注意到如下幾點,即次表面散射(Subsurface
Scattering)的視覺特性:

1、首先,次表面散射往往使照明的整體效果變得柔和。

2、一個區域的光線往往滲透到表面的周圍區域,而小的表面細節變得看不清了。

3、光線傳入物體越深,就衰減和散射得越嚴重。

4、對於皮膚來說,在照亮區到陰影區的銜接處,散射往往會引起微弱的傾向於紅色的顏色偏移。這是由於光線照亮表皮並進入皮膚,接着被皮下血管和組織散射和吸收,然後從陰影部分離開。且散射在皮膚薄的部位更加明顯,比如鼻孔和耳朵周圍。


                                                                       圖 次表面散射原理圖示


4.2 簡單的散射近似(Simple Scattering Approximations)


近似散射的比較簡單技巧是環繞照明(Warp Lighting)。正常情況下,當表面的法線對於光源方向垂直的時候,Lambert漫反射提供的照明度是0。而環繞光照修改漫反射函數,使得光照環繞在物體的周圍,越過那些正常時會變黑變暗的點。這減少了漫反射光照明的對比度,從而減少了環境光和所要求的填充光的量。環繞光照是對Oren-Nayar光照模型的一個粗糙的近似。原模型力圖更精確地模擬粗糙的不光滑表面(Nayar and Oren 1995)。

下圖和代碼片段顯示瞭如何將漫反射光照函數進行改造,使其包含環繞效果。

其中,wrap變量爲環繞值,是一個範圍爲0到1之間的浮點數,用於控制光照環繞物體周圍距離。

圖 環繞光照函數的圖表

float diffuse = max(0, dot(L, N));

float wrap_diffuse = max(0, (dot(L, N) + wrap) / (1 + wrap));


爲了在片元函數程序中的計算可以更加高效,上述函數可以直接編碼到紋理中,用光線矢量和法線的點積爲索引。

而在照明度接近0時,可以顯示出那種傾向於紅的微小顏色漂移,這是模擬皮膚散射的一種廉價方法。而這種偏向於紅色的微小顏色漂移,也可以直接加入到此紋理中。

另外也可以在此紋理的alpha通道中加入鏡面反射高光光照的功率(power)函數。可以在示例代碼Example 16-1中的FX代碼展示瞭如何使用這種技術。對比的圖示如下。

                          圖 (a)沒有環繞光照的球體 (b)有環繞光照明的球體 (c)有環繞光照明和顏色漂移的球體

Example 16-1 摘錄納入了環繞照明的皮膚Shader效果的代碼(Excerpt from the Skin
Shader Effect Incorporating Wrap Lighting)

// 爲皮膚着色生成2D查找表(Generate 2D lookup table for skin shading)

float4 GenerateSkinLUT(float2 P : POSITION) : COLOR

{

    float wrap = 0.2;

    float scatterWidth = 0.3;

    float4 scatterColor = float4(0.15, 0.0, 0.0, 1.0);

    float shininess = 40.0;

    float NdotL = P.x * 2 - 1; // remap from [0, 1] to [-1, 1]

    float NdotH = P.y * 2 - 1;

    float NdotL_wrap = (NdotL + wrap) / (1 + wrap); // wrap lighting

    float diffuse = max(NdotL_wrap, 0.0);

    // 在從明到暗的轉換中添加顏色色調(add color tint at transition from light to
    dark)

    float scatter = smoothstep(0.0, scatterWidth, NdotL_wrap) *

    smoothstep(scatterWidth * 2.0, scatterWidth,

         NdotL_wrap);

    float specular = pow(NdotH, shininess);

    if (NdotL_wrap <= 0) specular = 0;

    float4 C;

    C.rgb = diffuse + scatter * scatterColor;

    C.a = specular;

    return C;

}

// 使用查找表着色皮膚(Shade skin using lookup table)

half3 ShadeSkin(sampler2D skinLUT,

    half3 N,

    half3 L,

    half3 H,

    half3 diffuseColor,

    half3 specularColor) : COLOR

{

    half2 s;

    s.x = dot(N, L);

    s.y = dot(N, H);

    half4 light = tex2D(skinLUT, s * 0.5 + 0.5);

    return diffuseColor * light.rgb + specularColor * light.a;

}


4.3 使用深度貼圖模擬吸收(Simulating Absorption Using Depth Maps)


吸收(Absorption)是模擬半透明材質的最重要特性之一。光線在物質中傳播得越遠,它被散射和吸收得就越厲害。爲了模擬這種效果,我們需要測量光在物質中傳播的距離。而估算這個距離可以使用深度貼圖(Depth Maps)技術[Hery 2002],此技術非常類似於陰影貼圖(Shadow Mapping),而且可用於實時渲染。

                                                                  圖 使用深度貼圖計算光在物體中的傳播的距離

深度貼圖(Depth Maps)技術的思路是:

在第一個通道(first pass)中,我們從光源的視點處渲染場景,存儲從光源到某個紋理的距離。然後使用標準的投射紋理貼圖(standard projective texture mapping),將該圖像投射回場景。在渲染通道(rendering pass)中,給定一個需要着色的點,我們可以查詢這個紋理,來獲得從光線進入表面的點(di)到光源間距離,通過從光線到光線離開表面的距離(do)裏減去這個值,我們便可以獲得光線轉過物體內部距離長度的一個估計值(S)。如上圖。

原文中詳細分析了此方法的實現過程,也附帶了完整的Shader源碼,具體細節可以查看原文,這裏因爲篇幅原因就不展開了。

                                                圖 使用深度貼圖去近似散射,物體上薄的部位傳輸更多的光

也有一些更高端的模型試圖更精確地模擬介質內散射的累積效應。

一種模型是單次散射近似(Single Scattering Approximation),其假設光在材質中只反彈一次,沿着材質內的折射光線,可以計算有多少光子會朝向攝像機散射。當光擊中一個粒子的時候,光散射方向的分佈用相位函數來描述。而考慮入射點和出射點的菲涅爾效應也很重要。

另一種模型,是近似漫反射(Diffusion Approximation),其用來模擬高散射介質(如皮膚)的多次散射效果。



4.4 紋理空間的漫反射(Texture-Space Diffusion)


次表面散射最明顯的視覺特徵之一是模糊的光照效果。其實,3D美術時常在屏幕空間中效仿這個現象,通過在Photoshop中執行Gaussian模糊,然後把模糊圖像少量地覆蓋在原始圖像上,這種“輝光”技術使光照變得柔和。

而在紋理空間中模擬漫反射[Borshukov and Lewis 2003],即紋理空間漫反射(Texture-Space Diffusion)是可能的,我們可以用頂點程序展開物體的網格,程序使用紋理座標UV作爲頂點的屏幕位置。程序簡單地把[0,1]範圍的紋理座標重映射爲[-1,1]的規範化的座標。

另外,爲了模擬吸收和散射與波長的相關的事實,可以對每個彩色通道分爲地改變濾波權重。

                                       圖 (a)原始模型 (b)應用了紋理空間漫反射照明的模型,光照變得柔和


                                                                        圖 基於紋理空間漫反射照明的效果

同樣,原文中詳細分析了此方法的實現過程,也附帶了完整的Shader源碼,具體細節可以查看原文,這裏因爲篇幅原因就不展開了。


再貼幾張基於次表面散射的皮膚渲染效果圖,結束這一節。


                                                                        圖 基於次表面散射的皮膚渲染


                                                          圖 基於次表面散射的皮膚渲染 @《神祕海域4》


                                                                圖 基於次表面散射的皮膚渲染 @《神祕海域4》

【核心要點總結】


文中提出的次表面散射的實時近似方法,總結起來有三個要點:

1) 基於環繞照明(Warp Lighting)的簡單散射近似,Oren-Nayar光照模型。

2) 使用深度貼圖來模擬半透明材質的最重要特性之一——吸收(Absorption)。

3)基於紋理空間中的漫反射模擬(Texture-Space Diffusion),來模擬次表面散射最明顯的視覺特徵之一——模糊的光照效果。



【本章配套源代碼彙總表】


Example 16-1 摘錄納入了環繞照明的皮膚Shader效果的代碼(Excerpt from the Skin Shader Effect Incorporating Wrap Lighting)

Example 16-2 深度Pass的頂點Shader代碼(The Vertex Program for the Depth Pass)

Example 16-3 深度Pass的片元Shader代碼(The Fragment Program for the Depth Pass)

Example 16-4 使用深度貼圖來計算穿透深度的片元Shader代碼(The Fragment Program Function for Calculating Penetration Depth Using Depth Map)

Example 16-5 用於展開模型和執行漫反射光照的頂點Shader代碼(A Vertex Program to Unwrap a Model and Perform Diffuse Lighting)

Example 16-6 用於漫反射模糊的頂點Shader代碼(The Vertex Program for Diffusion Blur)

Example 16-7 用於漫反射模糊的片元Shader代碼(The Fragment Program for Diffusion Blur)


【關鍵詞提煉】


皮膚渲染(Skin Rendering)

次表面散射(Subsurface Scattering)

紋理空間漫反射(Texture-Space Diffusion)

環繞照明(Warp Lighting)

深度映射(Depth Maps)




五、環境光遮蔽(Ambient Occlusion)



【章節概覽】


在某種意義上,這篇文章屬於環境光遮蔽的啓蒙式文章。

環境光遮蔽(Ambient Occlusion),簡稱AO,是一種用於計算場景中每個點對環境光照的曝光程度的一種着色渲染技術。

本章講到了如何使用有效的實時環境光遮蔽技術,對物體遮蔽信息及環境進行預處理,綜合這些因素給物體創建逼真的光照和陰影。

                                                                          圖 有無環境光遮蔽的對比

                                                                          圖 有無環境光遮蔽的對比


【核心內容提煉】


5.1 概述


首先,本文中講到,環境光遮蔽(Ambient Occlusion)一般而言有兩種理解:

1)將環境光遮蔽視爲“智能”的環境光項,其在模型表面的變化取決於在每點可見多少外部環境。

2)將環境光遮蔽視爲一個漫反射項,其能有效地支持複雜分佈的入射光線。


文中將考慮上述的第二種解釋。

其基本思路是,假如預處理一個模型,計算它上面每個點可以看到多少外部環境,可以相反地計算有多少環境被模型的其他部分遮擋,然後在渲染時使用這個信息計算漫反射着色項的值。其結果是模型上的裂縫變暗,而模型的暴露部分會接收更多的光線,因此更明亮。這種效果實質上比使用標準的着色模型更逼真。

另外,這個方法可以擴展爲使用環境光作爲照明源,用代表各個方向入射光的環境貼圖沒來決定物體上每個點光的顏色。爲了這個特性,除了記錄在點上可以看到多少外部環境之外,也記錄大部分可以光從哪個方向到達。這兩個量有效地定義了從外面進入場景的未被遮擋的方向圓錐體,可以一起用來做爲來自環境貼圖的極端模糊的查詢,模擬着色點上來自感興趣的方向圓錐體的全部入射照度。



5.2 預處理步驟(The Preprocessing Step)


給定一個任意的着色模型,環境光遮蔽算法需要知道模型上每點的兩個信息:

(1)該點的“可到達度(accessibility)”- 即該點上方半球的哪一部分未被模型的其他部分遮擋;

(2)未被遮擋的入射光的平均方向。

通過下圖在平面上說明這兩個概念。給定在表面上的點P,其法線爲N,P點上半球的2/3被場景中其他幾何體遮擋,半球另外的1/3不被遮擋。入射光的平均方向用B表示,其在法線N的右側。大致來說,在P點的入射光的平均顏色,可以通過求圍繞B矢量的未遮擋入射光的圓錐體的平均值得到。

                                                                          圖 可到達度和平均方向的計算

下面貼出的僞代碼顯示了我們的基本方法。在每個三角形的中心,我們產生一組以表面法線爲中心的半球形光線,跟蹤每道光線進入場景,記錄哪些光線與模型相交,標誌不能從環境接收的光線,以及不被遮擋的光線。接着我們計算不被遮擋的光線的平均方向,這給出了入射光平均方向的近似值。(當然,我們計算的方向實際上可能會被遮擋,但我們選擇忽略不計這個問題。)

Example 17-1 計算環境光遮蔽量的基本算法僞代碼 (Basic Algorithm for Computing Ambient Occlusion Quantities)

For each triangle {

    Compute center of triangle

    Generate set of rays over the hemisphere there

    Vector avgUnoccluded = Vector(0, 0, 0);

    int numUnoccluded = 0;

    For each ray {

        If (ray doesn't intersect anything) {

            avgUnoccluded += ray.direction;

            ++numUnoccluded;

        }

    }

    avgUnoccluded = normalize(avgUnoccluded);

    accessibility = numUnoccluded / numRays;

}

生成這些光線的簡單方法是使用拒絕採樣法(rejection sampling):檢測在x,y和z爲-1到1區間的3D立方體中隨機生成的光線,並拒絕不在單位半球中與法線相關的光線。

能通過這次檢測的光線方向可視分佈理想的光線方向。列表17-2的僞代碼表示出了此方法的實現思路。

當然,也可以用更復雜的蒙特卡洛(Monte Carlo)採樣法來得到更好的樣本方向的分佈。

Example 17-2 使用拒絕採樣法計算隨機方向的算法僞代碼(Algorithm for Computing
Random Directions with Rejection Sampling)

while (true) {

    x = RandomFloat(-1, 1); // random float between -1 and 1

    y = RandomFloat(-1, 1);

    z = RandomFloat(-1, 1);

    if (x * x + y * y + z * z > 1) continue; // ignore ones outside unit

    // sphere

    if (dot(Vector(x, y, z), N) < 0) continue; // ignore "down" dirs

    return normalize(Vector(x, y, z)); // success!

}

另外,用圖形硬件代替光線追蹤軟件,有可能加速遮擋信息的計算。



5.3 使用環境光遮蔽貼圖進行渲染(Rendering with Ambient Occlusion Maps)


使用環境光遮蔽貼圖進行着色的基本思想是:

可以直接在着色點處使用之前已計算好的,有多少光線能到達表面的,優質的近似值信息。


影響這個數值的兩個因素是:

(1)在此點上方半球的哪個部分不被點和環境貼圖之間的幾何體遮擋。

(2)沿着這些方向的入射光是什麼。


下圖顯示了兩種不同的情況。在左圖中,只能看到着色點上面的一小部分分享,由方向矢量B和圍繞它的方向圓錐體所表示,該點的可到達度非常低。而在右圖中,沿着更大範圍的方向有更多的光線到達給定點。


圖 不同量的可見度的近似(左圖:由於附近的幾何體的遮擋比較嚴重,這點得到的照度較小;右圖:沿着更寬方向的圓錐體,更大量的光能到達這點,照度較左圖更大)


在預處理中計算的可訪問性值告訴我們哪一部分半球可以看到環境貼圖,而可見方向的平均值給出一個近似方向,圍繞它計算入射光。雖然這個方向可能指向一個實際被遮擋的方向(例如,如果半球的兩個獨立區域未被遮擋,但其餘的部分被遮擋,平均方向可能在這兩者之間),但在實踐中其通常運行良好。

                                                            圖 使用可到達度信息和環境貼圖渲染的光照場景

                                                         圖 有無使用環境光遮蔽貼圖進行渲染的對比圖

另外需要注意,實時環境光遮蔽的常用廉價方案是預先計算網格表面幾個位置的平均可見性值,存儲於貼圖中,然後將這些值在運行時與圖形硬件提供的未遮擋光照相乘。



【核心要點總結】


給定一個任意的着色模型,環境光遮蔽算法需要知道模型上每點的兩個信息:

1)該點的可到達度(accessibility)。

2)未被遮擋的入射光的平均方向。


文中提出的環境光遮蔽方法,總結起來有三個要點:

  • 採用了多種在實踐中運行良好的近似方法。
  • 主要爲預處理操作,將相對昂貴的計算事先準備好,且僅計算在渲染時進行快速着色所需的正確信息。
  • 預處理不依賴於光照環境貼圖,因此可以輕鬆使用場景中的動態照明。


【本章配套源代碼彙總表】


Example 17-1 計算環境光遮蔽量的基本算法僞代碼(Basic Algorithm for Computing Ambient Occlusion Quantities)

Example 17-2 使用拒絕採樣法計算隨機方向的算法僞代碼(Algorithm for Computing Random Directions with Rejection Sampling)

Example 17-3 使用可到達度和環境映射進行着色的片元Shader(Fragment Shader for Shading with Accessibility Values and an Environment Map)

Example 17-4 latlong( )函數的定義(The latlong() Function Definition)

Example 17-5 computeBlur( )函數的定義(The computeBlur() Function Definition)



【關鍵詞提煉】


環境光遮蔽(Ambient Occlusion)

拒絕採樣(Rejection Sampling)

環境光遮蔽貼圖(Ambient Occlusion Maps)





六、實時輝光(Real-Time Glow)


【章節概覽】


這章講到2D光照效果中的輝光(Glow)和光暈(Halo),展示瞭如何通過圖像處理方法完全地改善畫面及3D人物的渲染感官。

                                                       圖 遊戲中的Glow結合Bloom,得到出色的畫面效果


                                                      圖 Unreal Engine的logo,即是採用了Glow效果


【核心內容提煉】


光源的輝光(Glow)和光暈(Halo)是自然界中到處可見的現象,他們提供了亮度和氣氛強烈的視覺信息。

                                                圖 給強化後的武器加上Glow效果,該武器顯得更加強力 @TERA

                                                      圖 Glow效果在遊戲中的運用 @Unreal Engine 4

在觀看計算機圖形、膠片和印刷品時,到達眼睛的光強度是有限的,因此,辨別光源強度的唯一方法是通過它們周圍產生的輝光(Glow)和光暈(Halo),具體可以參考[Nakamae et al.1990]。這些輝光可以再現強烈光線的視覺效果,並使觀察者感知非常明亮的光源。即使物體周圍的微妙光暈也會讓人覺得它比沒有光輝的物體更亮。

在日常生活中,這些發光和光暈是由大氣中或我們眼中的光散射引起的(Spencer 1995)。使用現代圖形硬件,可以通過幾個簡單的渲染操作來再現這些效果。這使得我們可以使用明亮而有趣的物體來填滿實時渲染的場景,物體會顯得更爲逼真或更具表現力,並且這是克服圖形渲染中傳統的低動態範圍圖形過於平庸的優雅手段之一。

                                                      圖 有輝光和沒有輝光的一個Tron 2.0中的角色對比

有幾種方法可以創建場景中的輝光。對於小的類似的點,可以把一個平滑的“輝光”紋理應用到公告牌幾何體上,而讓公告板幾何體在屏幕範圍內跟隨物體運動。

對於大的輝光源或複雜的輝光形狀,要創建輝光,最好對2D場景的渲染進行後處理。這章重點講到了後處理的實時輝光處理方法。如下圖。

圖 場景實時輝光的步驟 (a)正常地渲染場景(b)塗抹所渲染的輝光源,以產生(c)中的 一個輝光紋理,將其加到正常的場景畫面中,以產生(d)中最終的輝光效果。


渲染後處理輝光的步驟:

Step 1、輝光的指定和渲染(Specifying and Rendering the Sources of Glow)

Step 2、模糊輝光源(Blurring the Glow Sources)

Step 3、適配分步卷積(Adapting the Separable Convolution)

Step 4、在GPU上進行卷積(Convolution on the GPU)

圖 有效地創建模糊的兩步分解法

上圖展示瞭如何有效地創建模糊的兩步分解法:首先,在一根軸上模糊於(a)中的輝光源的點,產生(b)中所示的中間結果,然後在另一個軸上模糊這個結果,產生顯示在(c)中的最終模糊。

圖 有輝光和無輝光的Tron 2.0中的英雄 Jet

(a)用標準方法渲染3D模型(b)爲一個由美術同學創建的輝光源紋理的渲染,目的是指定輝光面積的圖案和強度(c)爲將輝光應用到標準的渲染結果後,得到的富有表現力的英雄角色效果。


另外,在輝光中使用的這個卷積和模糊方法還可以用於多種其他效果。它能用來計算景深效果的不同聚焦度,景深的信息可以用來控制模糊度。它也能用來模糊投影的紋理陰影的邊緣,並且累積深度陰影映射的接近百分比過濾(percentage-closer filtering )結果。


而大面積的卷積能被應用於一個環境映射,以創建一個近似的輻照度映射,從而得到更逼真的場景照明(Ramamoorthi和Hanrahan 2001有相關論述)。用大面積的卷積也可以實現許多非真實感渲染技術和其他的特別效果。其中包括鍍着霜的玻璃、模擬衍射的透鏡搖曳,以及渲染皮膚時用的近似次表面散射。

大片的模糊和卷積能有效地在多種圖像硬件上實時地計算,而處理和創建這些效果的代碼可以容易地封裝成幾個C++類或一個小庫。

總之,屏幕輝光是一種很讚的效果,能夠容易地擴展到幾乎每一種情形,並且變化多端,通過其還夠延伸創建出很多其他的效果。最終的效果雖然細微但卻有張力,值得在各種遊戲中採用。

圖 Glow效果在遊戲中的運用 @Unreal Engine 4

圖 有了Glow效果的武器,會顯得更強力更炫酷


【核心要點總結】


渲染後處理輝光的步驟:

Step 1、輝光的指定和渲染(Specifying and Rendering the Sources of Glow)

Step 2、模糊輝光源(Blurring the Glow Sources)

Step 3、適配分步卷積(Adapting the Separable Convolution)

Step 4、在GPU上進行卷積(Convolution on the GPU)


【關鍵詞提煉】


實時輝光(Real-Time Glow)

光暈(Halo)

後處理(Post-Processing)

圖像處理(Image Processing)




第二部分 · 次核心內容提煉總結


十六、使用遮擋區間映射產生模糊的陰影(Generating Soft Shadows Using Occlusion Interval Maps)



【章節概覽】


這章介紹了一種渲染軟陰影的技術,稱爲遮擋區間映射(Occlusion Interval Maps),能夠正確地在靜態場景中渲染出光源沿着預定路徑移動時產生的模糊陰影。之所以叫遮擋區間映射,是因爲此算法使用紋理貼圖來存儲這種光源可見、而本身被遮擋的區間。



【核心要點】


對於需現實的加油站的Demo,文章一開始本打算使用一種預計算的可見度技術,例如球諧光照(Spherical Harmonic Lighting [Sloan et al.2002])來實現,但可惜的是無法達到目的,因爲球諧光照適用的是非常低頻的光照,不適用於像太陽那樣小面積的光源。所以後來才開發出遮擋區間映射這種新的預計算可見度的技術,它能夠支持實時太陽照射的軟陰影。通過把問題簡化爲在固定軌道上的線性光源來達到目的。

需要注意,遮擋區間映射(Occlusion IntervalMaps)技術有一些侷限性,只對沿固定軌道傳播的單條光線的靜態場景適用。這意味着它對人物和其他動態物體的陰影無效。但是其適用於靜態戶外場景中的陰影渲染。並且此技術因爲遮擋區間映射對每個通道需要8位的進度,紋理壓縮將導致視覺效果失真。因此,必須禁用紋理壓縮,從而增加了紋理用量。

使用遮擋區間映射(Occlusion Interval Maps)技術,通過損失一定運行性能來獲得在靜態場景上實時運行的軟陰影算法。遮擋區間映射(Occlusion Interval Maps)可以用作靜態光照貼圖的替代品,從而實現動態效果,可以得到從日出到日落光照明變化的動態效果。如下圖。

圖 加油站入口

注意加油站牆上的陰影在圖形的左上方有清楚的邊界,但是它朝着右下方變得模糊而柔軟。這種相聯繫的清晰和模糊的變化是真實感軟陰影的重要性質,而這是由遮擋區間映射得到的。

圖 汽車上方的木板在篷布上形成的陰影

上圖中汽車篷布上的木板形成了複雜的陰影。這對算法來說是最壞的情況。這些木頭條使得篷布上的遮擋區間映射必須存儲在5個不同的紋理中,對於場景中的大多數物體,4個紋理就足以取得所有的陰影。


【關鍵詞提煉】


陰影渲染(Shadow Rendering)

軟陰影(Soft Shadows )

遮擋區間映射(Occlusion Interval Maps)



十七、透視陰影貼圖(Perspective Shadow Maps: Care and Feeding)


【章節概覽】


透視陰影貼圖(Perspective Shadow Maps, PSMs)是由Stamminger和Drettakis在SIGGRAPH 2002上提出的一種陰影貼圖(Shadow Maps)流派的方法。

透視投影貼圖方法的基本思想是,爲了減少或消除陰影貼圖的失真走樣,對投射到大像素區域的物體取最大的陰影貼圖紋素密度。

這章提出了一種優化透視陰影貼圖(Perspective Shadow Maps)方法的新思路,對其三種缺陷都一一進行了改進。


【核心要點】


這章首先講到動態陰影的創建,目前主要有兩個算法流派:

  • 陰影體(shadow volumes)/模板陰影(stencil shadows)
  • 陰影貼圖(Shadow Maps)

陰影體和陰影貼圖算法之間的不同之處在於,是涉及到物體空間(object space)還是圖像空間(image space)。

  • 陰影體(Shadow Volumes)是物體空間(Object Space)的陰影算法,通過創建表示陰影遮擋的多邊形結構來工作,這意味着我們始終具像素精確但較“硬”的陰影。此方法無法處理沒有多邊形結構的對象,比如經過alpha測試修改的幾何圖形或經過位移映射的幾何體(displacement mapped geometry)。此外,繪製陰影體需要大量的填充率,這使得很難將它們用於密集場景中的每個對象上,特別是在存在多個燈光時。
  • 陰影貼圖(Shadow Maps)是圖像空間(Image Space)的陰影算法,它可以處理任何物體(如果能夠渲染一個物體,就能得到它的陰影),但是存在走樣(aliasing,鋸齒)的問題。走樣時常發生在有較寬或全方位光源的大場景中。問題在於陰影映射中使用的投影變換會改變陰影貼圖像素的大小,因此攝像機附近的紋理像素變得非常大。因此,我們必須使用巨大的陰影貼圖(四倍於屏幕分辨率或更高)來實現更高的質量。儘管如此,陰影貼圖在複雜場景中卻比陰影體要快得多。


透視陰影貼圖(Perspective Shadow Maps, PSMs)是由Stamminger和Drettakis 在SIGGRAPH 2002上提出的一種陰影貼圖(Shadow Maps)流派的方法,通過使用在投射後空間(post-projective space)中的陰影貼圖來去除其中的走樣,而在投射後空間中,所有近處的物體都比遠處的大。不幸的是,使用原始算法很困難,因爲只有要某些情況下才能正常工作。


以下是透視陰影映射算法的三個主要問題和解決方案:


1、當光源在攝像機後面的時候,有一個虛擬的攝像機錐體。若在錐體內保持所有潛在的陰影投射體,陰影質量就會變得很差。

解決方案:是對光源矩陣使用特別的投射變換,因爲投射後空間可以使用某些在通常空的世界空間中不能做的投射技巧。它使我們可以建立特殊的投射矩陣,可以看做“比無限遠更遠”。


2、光源在攝像機空間中的位置對陰影質量影響很大,對於垂直的方向光,完全沒有走樣問題,但是當光源朝向攝像機並迎面靠近它時,陰影映射走樣就很嚴重。

解決方案:把整個單位立方體保持在一個陰影貼圖紋理中,對於遇到的問題,有兩個辦法,每個辦法僅解決問題的一部分:單位立方體裁剪法,把光源攝像機對準單位立方體的必要部分;立方體映射法,使用多個紋理來存儲深度信息。


3、最初的文章沒有討論過偏置(bias)問題。偏置是隨透視陰影貼圖而帶來的問題,因爲紋素的面積以不均勻方式分佈,這意味着偏置不再是常量,而是與紋素的位置有關。

解決方案:使用在世界空間中的偏置(而且不再分析雙投射矩陣的結果),然後把這個世界空間偏置轉換到投射後空間。

                                                       

圖 得到的陰影實時渲染結果(多邊形10w ~ 50w個,分辨率1600x1200)


【關鍵詞提煉】


陰影渲染(Shadow Rendering)

陰影貼圖(Shadow Maps)

透視陰影映射(Perspective Shadow Maps,PSMs)

緊鄰百分比過濾(percentage-closer filtering ,PCF)

單位立方體裁剪法(Unit Cube Clipping)


十八、逐像素光照的可見性管理(Managing Visibility for Per-Pixel Lighting)


【章節概覽】


這章講到了可見性在逐像素渲染光照場景中的作用,也考慮如何使用可見性減少必須渲染的批次數量,從而改善性能。


【核心要點】

如下僞代碼說明在一個場景中必須渲染的批次數:

For each visible object

  For each pass in the ambient shader

    For each visible batch in the object

      Render batch

For each visible light

  For each visible shadow caster

    For each pass in the shadow shader

      For each shadow batch in the object

        Render batch

  For each lit visible object

    For each pass in the light shader

      For each visible batch in the object

        Render batch

正如僞代碼所述,爲了減少批次數,可以進行一些與非可見性相關的優化。最應該優化的是渲染每個光照所必須的通道數。批次數隨通道數線性增加,因此,我們應該最小化受限於CPU的遊戲通道數。

我們可以使用可見性來減少批數。其中,爲了減少批次,各個部分(可見部分、光源部分、光照部分、陰影部分)的集合分開討論並生成。

可見性不僅能有效改善CPU的性能,也同樣可以改善GPU的性能。對模板體執行逐像素光照時,填充率的消耗(模板體的填充或多次渲染大的物體)很快就變成了瓶頸,但可以使用剪切矩形(scissor rectangle)限制顯卡渲染的面積,解決此問題。

逐像素的照明需要大量的批次數和極高的填充率,所以要減少渲染的物體數和它們影響的屏幕面積。而使用這章中介紹的標準可見性算法和技術,可以充分改善運行性能。

圖 不在可見集合中的對象可能會影響渲染場景


【關鍵詞提煉】


逐像素光照(Per-Pixel Lighting)

可見性管理(Managing Visib1ility)

性能優化(Performance Optimization)

批次(Batch)



十九、空間BRDF(Spatial BRDFs)


【章節概覽】


這章主要先聊到了空間雙向反射分佈函數(SBRDF),接着文章討論了壓縮SBRDF表達式,以及由離散光或環境貼圖所照明的SBRDF的渲染方法。



【核心要點】


SBRDF是紋理貼圖和雙向反射分佈函數(BRDF)的組合。紋理貼圖存儲了反射或其他的屬性,它們沿着2D表面上的空間變化,而BRDF存儲的是表面上單個點的反射,包括從入射角到出射角的全部分佈。

圖 SBRDF的定義域

SBRDF對標準點光源或方向光源照明的SBRDF表面,文中直接貼圖了Shader源碼,具體可以參考原文。

SBRDF除了可以用點光源或方向光源照明之外,還可以用環境貼圖中所有方向的入射光進行照明。關鍵是在渲染前用BRDF的一部分卷積環境貼圖。對於大多數的BRDF表達式,必須分別處理各個不同的BRDF。但因爲一個SBRDF可能有上百萬個不同的BRDF,所以這樣做不可能。這篇文章採取的的做法是,簡單地用一個Phong葉片卷積環境貼圖,葉片可以選擇不同的鏡面指數,如n=0、1、4、16、64、256、這些貼圖能存儲在不同級別的立方體mipmap中。隨後,SBRDF紋素的n值就指細節層次(LOD),用於在立方體貼圖中採樣適當mipmap級別。

圖 用藍色的油漆和鋁BRDF得到的SBRDF渲染效果


【關鍵詞提煉】


雙向反射分佈函數(BRDF)

空間雙向反射分佈函數(SBRDF)

離散光(Discrete Lights)

環境貼圖(Environment Maps)



二十、基於圖像的光照(Image-Based Lighting)



【章節概覽】


這篇文章打破了當時立方體貼圖環境(Cube-Map Environment)用法的桎梏,深入研究了更多可能的逼真光照效果。文章主要研究了基於圖像的光照(Image-Based Lighting,IBL),包括局部化的立方體映射,類似於使用基於圖像的局部光照(Localizing
Image-Based Lighting),然後介紹瞭如何把哪些重要的技巧用於着色模型,包括逼真的反射、陰影和漫反射/環境項。



【核心要點】


立方體貼圖通常用於創建無限遠環境的反射效果。但是使用少量Shader算法,我們可以將物體放置在特定大小和位置的反射環境中,從而提供高質量的基於圖像的光照(Image-Based
Lighting,IBL)。


在室內環境移動模型時,最好是使用近距離的立方體貼圖,距離的大小與當前的房間類似。當模型在房間移動時,根據模型在房間中的位置,適當地放大或縮小放射。這種方法得到的模擬效果使人感到更爲可靠和逼真。尤其在包含窗戶,屏幕和其他可識別光源的環境中。而只要加入很少的Shader數學就能將反射局部化。具體可以看原文貼出的Shader源碼。

圖 不同位置上的局部反射

另外,我們可以將3D幾何體做成立方體貼圖,並且在正常地渲染環境的時候,把貼圖應用到該環境的物體上。也可以使用貼圖作爲環境,把它投射到較簡單的幾何體上。

立方體貼圖也能用來決定漫反射光照。Debevec的HDRShop程序能夠從映射立方體光照環境積分出全部的漫反射貢獻度,那麼通過把表面法線帶入預先卷積的立方體貼圖,能夠簡單地查詢漫反射貢獻。

基於圖像的光照爲複雜的光照計算提供了綜合而廉價的替代品,將一點數學加入紋理方法,可以大大拓寬“簡單”IBL效果,給3D圖像提供更強的的方位感。


【關鍵詞提煉】


基於圖像的光照(Image-Based Lighting,IBL)

立方體貼圖環境(Cube-Map Environment )

基於圖像的局部光照(Localizing Image-Based Lighting)



二十一、紋理爆炸(Texture Bombing)



【章節概覽】


這章介紹了紋理爆炸(Texture Bombing)和相關的細胞技術,它們能在Shader中增加視覺的豐富性,圖像的多樣性,並減少大塊紋理圖案的重複性。



【核心要點】



紋理爆炸(Texture bombing)是一種程序化技術,它把小塊圖像以不規則的間隔放置。有助於減少團案的失真。

紋理爆炸的基本思想是把UV空間分爲規則的單元柵格。然後使用噪聲或者僞隨機函數,把一個圖像放在任意位置上的各個單元中。最終的結果是在背景上對這些圖像的合成。

由於要組合數以百計的圖像,因此實際上這種合成(composite)圖像的方法效率並不高。而程序化(Procedural
)計算圖像雖好,但是又不適合合成。這篇文章主要講了圖像合成和程序化生成這兩種方法,可以發現他們各有優劣。

圖 紋理爆炸效果圖

很顯然,紋理爆炸也可以擴展到3D中,即3D程序化爆炸(Procedural 3D Bombing)

圖 程序化的3D紋理爆炸效果

紋理爆炸有一種有趣的變化是在平面上畫Voronoi區域。簡言之,給定一個平面和那個平面上的一系列的點,接近那個點的面積就是點的Voronoi區域。Voronoi圖案類似於樹葉和皮膚上的單元形狀、龜裂的泥土或爬蟲類的皮。如下圖。

圖 Voronoi區域

總之,紋理爆炸和相關的細胞技術可以給Shader增加視覺的多樣性。使用存儲在紋理中的僞隨機數表和一個小程序,可以增大一個圖像或一組圖像的變化,並減少大塊紋理區域的重複。


【關鍵詞提煉】


紋理爆炸(Texture Bombing)

3D程序化爆炸(Procedural 3D Bombing)

Voronoi區域(Voronoi Region)




二十二、顏色控制(Color Controls)



【章節概覽】


這章將在遊戲中圖像處理的討論,擴展到技術和藝術上控制顏色的方法和應用,包括將圖像從一些的色彩空間中移入移出,以及快速地給任何2D或3D場景加上精美的色調。



【核心要點】


色彩校正(Color Correction)是幾乎所有印刷和膠片成像應用的一部分。色彩校正可用於將彩色圖像從一個色彩空間移動到另一個色彩空間。

我們在電視、雜誌和電影中剪刀的大部分圖像,都經過了非常小心的彩色校正和控制。對於這個過程的理解,可以幫助開發者在實時應用程序中得到同樣華美的視覺效果。

色彩校正通常有兩種做法:一是各個通道的校正,分別是改變紅色、綠色和藍色各成分;二是混色操作,基於紅、綠、藍各個成分的同時操作,得到每個通道的輸出值。

色彩校正的機理可以簡潔而容易地在一個shader中描述。重要的是,美術和程序員使用的普通工具就能有效地控制他們。在這章中,運用Photoshop創建控制資源,然後通過像素shader應用到實時程序中。

在Photoshop中提供了一些基於通道校正的工具。如級別(levels)和曲線(Curves)工具。

其中曲線是仿製了化學中的交叉處理(cross-processing)外觀,確切地說,就是在C41化合物中處理E6叫絕所產生的假顏色外觀。這樣的處理已在印刷、電影和電視領域使用多年。

圖 重新創建交叉處理效果的Photoshop曲線

圖 僞交叉處理 (a)原始圖 (b)曲線調節之後

可以使用下面幾行shader代碼運用於輸出顏色,使用色彩校正紋理映射,可以隨意地用曲線工具重新創建任何色彩變化:

float3 InColor = tex2D(inSampler, IN.UV).xyz;
float3 OutColor;
OutColor.r = tex1D(ColorCorrMap, InColor.r).r;
OutColor.g = tex1D(ColorCorrMap, InColor.g).g;
OutColor.b = tex1D(ColorCorrMap, InColor.b).b;

也就是說,使用每個原始的紅、綠和藍像素的灰度值,確定在梯度紋理中我們尋找的相關位置,然後由梯度紋理本身定義對新顏色的重映射,即由複雜曲線調節所定義的新顏色,如下圖。

圖 對紅、綠、藍通道重映射結果


【關鍵詞提煉】


顏色控制(Color Controls)

色彩校正(Color Correction)

基於通道的顏色校正(Channel-Based Color Correction)

灰度變換(Grayscale Conversion)

色彩空間變換(Color-Space Conversions)

圖像處理(Image Processing)





二十三、景深 (Depth of Field)



【章節概覽】


本章主要介紹如何使用GPU創建實時的景深(Depth of Field)效果。

圖 實時景深效果 @Crysis 2


【核心要點】


物體在距離鏡頭的一個範圍之內能夠清晰成像(經過聚焦),在那個範圍之外(或近或遠)則成像模糊,這種效果就是景深。在相機業和電影業中,景深經常用來指示對場景的注意範圍,並且提供場景深度的感覺。在本章中,把這個聚焦範圍遠的區域稱爲背景(background),在這個範圍前的區域稱爲前景(foreground),而在範圍外的面積稱爲中景(midground)。


景深效果由透鏡的物理性質產生。若要穿過攝像機透鏡(或人眼鏡的晶體)的光輝聚到膠片(或人的視網膜)上的一個點,光源必須與透鏡有着特定的距離。在這個距離上的平面稱爲焦平面(plane in focus)。不在這個精確距離上的任何東西,投影到膠片上的區域(而不是一個點)稱爲模糊圈(circle of confusion,CoC)。Coc的直徑與透鏡尺寸和偏離焦平面的距離成正比。偏離距離小到一定程度,CoC會變得比膠片的分辨率更小,攝影師和攝影師稱這個距離爲聚焦(in focus),而在這個範圍之外的任何東西都是沒有對準聚點的(out of focus,模糊的)。如下圖。

圖 薄的透鏡

圖 模糊圈(circle of confusion)

這章中主要綜述了5種近似景深效果的技術。

1、基於光線追蹤的景深(Ray-Traced Depth of Field)[Cook et al. 1984]

2、基於累積緩衝的景深(Accumulation-Buffer Depth of Field)[Haeberli and Akeley
1990]

3、分層景深(Layered Depth of Field)[Scofield 1994]

4、前向映射的Z緩衝景深(Forward-Mapped Z-Buffer Depth of Field) [Potmesil and
Chakravarty 1981]

5、反向映射的Z緩衝景深(Reverse-Mapped Z-Buffer Depth of Field)[ Arce and Wloka
2002, Demers 2003]



【關鍵詞提煉】


景深(Depth of Field)

基於光線追蹤的景深(Ray-Traced Depth of Field)

基於累積緩衝的景深(Accumulation-Buffer Depth of Field)

分層景深(Layered Depth of Field)

前向映射的Z緩衝景深(Forward-Mapped Z-Buffer Depth of Field)

反向映射的Z緩衝景深(Reverse-Mapped Z-Buffer Depth of Field)

圖像處理(Image Processing)





二十四、高品質的圖像濾波(High-Quality Filtering)


【章節概覽】


這章描述了圖像濾波和可以用於任意尺寸圖像的效果,並將各種不同的濾波器核心(kernel),在分析計算後應用於各式2D和3D反走樣問題中。


【核心要點】


GPU可以提供一些快速濾波的訪問紋理的方法,但是僅限於幾種類型的紋理過濾,並不是對每種紋素格式都適用。若我們自己建立自己的圖像濾波方法,可以得到更好的質量和靈活性,但需要了解硬件和程序濾波之間存在的質量和速率的矛盾。
對濾波圖像所考慮的內容也同樣適用於3D渲染,尤其是把模型紋理化(光柵化)的時候,即把3D數據(和潛在的紋理信息)轉換爲一個新的2D圖像的時候。
而混合過濾方法(Hybrid filtering approaches)可以提供一個最佳的中間路徑,即藉助硬件紋理單元解析的着色。
GPU着色程序不同於CPU的主要之處在於:一般來說,CPU數學操作比紋理訪問更快。在像RenderMan這樣的着色語言中,texture()是最費時的操作之一,而在GPU中的情形恰恰相反。
圖像濾波( image filtering)的目的很簡單:對於給定的輸入圖像A,我們想要創建新的圖像B,把源圖像A變換到目標圖像B的操作就是圖像濾波。最一般的變換是調整圖像的大小、銳化、變化顏色,以及模糊圖像等操作。
源像素的模式,以及它們對圖像B像素的相對共享,就稱爲濾波的核心(filter kernel)。而把核心御用到源圖像的過程叫做卷積(convolution):即使用特殊的核心卷積源圖像A的像素,創建新圖像B的像素。
如果核心只是把像素簡單地進行平均,我們稱這個模型爲盒式濾波器(box filter),因爲模型是一個簡單的長方形(所有像素都在盒中)。每個採樣的紋素(即,從紋理來的一個像素)的權重相等。盒式濾波器很容易構造,運行速度快,是GPU中硬件驅動過的一種濾波核心。
如果我們正好使用小的核心,可以把它作爲參數直接代入Shader,下圖顯示的樣本代碼執行3 x 3的濾波運算,對編入索引的紋素和其臨近單元,賦予W00到W22的加權值,先求加權和,然後除以預計算的總和值(Sum)把它們重規範化。
圖 中心在W11的3x3濾波核心的像素佈局
我們可以自己定義各種核心,如可以基於兩個常數的3 x 3核心做邊緣檢測,後文也接着講到了雙線性濾波核心(Bilinear Kernel),雙立方濾波核心(Bicubic Filter Kernel),屏幕對齊的核心(Screen-Aligned Kernels)等內容。
圖 雙線性和雙立方濾波的效果
(題外話:不知道爲什麼,看這個小男孩,莫名覺得長得像冠希哥……)
(a)原始圖像,注意眼睛上方的長方形。(b)用線性濾波把矩形的子圖像區域放大32倍;(c)用雙立方濾波把相同的區域放大32倍。

【關鍵詞提煉】


高品質圖像濾波(High-Quality Filtering)
邊緣檢測(Edge Detection)
雙線性濾波(Bilinear Filtering)
雙三次濾波(Bicubic Filtering)
三次濾波(Cubic Filtering)


二十五、用紋理貼圖進行快速濾波寬度的計算(Fast Filter-Width Estimates with Texture Maps)


【章節概覽】

這章描述基於紋理映射在2D空間中進行快速過濾寬度計算(Fast Filter-WidthEstimates)的方法。即使硬件profile對複雜函數的局部偏導函數不提供直接支持,基於本文提出的紋理操作技巧,也可以得到結果。

【核心要點】

Cg標準庫提供了ddx()和ddy()函數,計算任意量關於x和y像素的導數。換言之,調用ddx(v),可以求出變量v在x方向的當前像素與下一個像素之間的變化量,調用ddy(v)同樣也可以求出y方向的情況。
那麼,下面貼出的這個filterwidth()函數,可以很容易地計算任何值在像素之間變化的速率,以及程序紋理說需要過濾的面積。
float filterwidth(float2 v)
{
     float2 fw = max(abs(ddx(v)), abs(ddy(v))); 
     return max(fw.x, fw.y);
}
上述filterwidth()函數,僅在支持ddx()和ddy()函數的profile下工作,但可惜的是一些硬件profile不支持這兩兩個函數。而本文提出的這個trick,可以使用紋理映射硬件,進行與filterwidth()函數本質上相同的運算。
而這個技巧的關鍵在於,用函數tex2D()所做的紋理貼圖查詢,可以自動地對紋理查詢進行反走樣,而不考慮所代入的紋理座標。也就是說,基於在相鄰像素上所計算的紋理座標,硬件可以爲每個查詢決定要過濾的紋理面積。
紋理映射的這個性質,可以用來替代濾波寬度函數filterwidth(),而無需調用ddx()和ddy()。我們以這樣的一種方式執行紋理查詢:通過它可以推測所過濾的紋理貼圖面積,這裏是推測需要過濾的程序化棋盤格紋理面積。這種解法分爲兩步:(1)爲特定的紋理座標選擇mipmap級別;(2)利用上述技巧來決定過濾寬度。
最終,這個trick可以在很多情況下很好的計算濾波寬度,運行性能幾乎與基於求導的計算濾波寬度函數filterwidth()相同。

【關鍵詞提煉】

快速濾波寬度估算(Fast Filter-Width Estimates)
在着色器中求導(Derivatives in Shaders)
用紋理計算過濾寬度(Computing Filter Width with Textures)


二十六、OpenEXR圖像文件格式與HDR(The OpenEXR Image File Format and HDR)


【章節概覽】


這章中,大名鼎鼎的工業光魔公司的Florian Kainz、Rod Bogart和Drwe
Hess介紹了OpenEXR標準,這是一種當時新的高動態範圍圖像(HDRI)格式,在計算機成像的頂級電影中正在快速推廣。對於基於圖像照明的開發者而言,OpenEXR是關鍵的工具。


【核心要點】

OpenEXR是由工業光魔( Industrial Light & Magic,ILM )公司開發的高動態範圍圖像( high-dynamic-range image,HDRI)文件格式。OpenEXR網站是 openexr.org ,上面有關於此格式的全部細節。

下圖是一個例子,說明了需要HDR存在的原因。

如下圖是一張顯示相當高的動態範圍的場景,場景中左邊的油燈的火焰比中間小盤子下的陰影大約亮100000倍。

圖 高動態範圍場景

圖像曝光的方式導致了一些區域的亮度超過了1.0,在計算機顯示屏上,這些區域被裁剪(clipped)掉,並顯示爲白色或不自然的飽和桔色色調。

我們可以通過把圖像變暗來校正白色和橘色區域,但是如果把原始圖像存儲在低動態範圍文件格式中,如JPEG格式,把它變暗就會產生相當難看的圖像。如下圖。

圖 普通文件格式導致明亮的像素值被不可逆地裁剪,使得明亮的區域變灰,並且細節丟失,得到極不自然的效果

而如果原始圖像存儲在高動態範圍文件格式中,如OpenEXR,保存明亮的像素值,而不是把他們裁剪到1.0,然後把圖像變暗,就可以產生依舊自然的效果。如下圖。

圖 上述變暗的圖的高動態範圍版本。在明亮的區域中顯示出了其他細節,顏色看起來很自然

文章隨後還講到了OpenEXR的文件結構、數據壓縮、使用、線性像素值、創建和使用HDR圖像相關的內容。有興趣的同學可以查看原文,這裏就不再贅述了。


【關鍵詞提煉】


高動態範圍(High-Dynamic-Range , HDR)

高動態範圍圖像(High-Dynamic-Range Image,HDRI)

OpenEXR




至此,《GPU Gems 1》全書核心內容提煉總結 ,上下兩篇,完。


With best wishes.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章