[閱讀筆記] Unity shader 入門精要 #3

《Unity shader 入門精要》的讀書筆記,九到十一章。 更深入的說明光照、貼圖,以及跟時間沾上邊的 shader

第九章:進階光照

  • 渲染路徑 (Rendering Path)
  • Forward Rendering Path
    • 對所有光照與 fregmant 進行深度測試,通過則計算光照,寫入 Frame Buffer
    • 對硬體需求較低,但不適合處理大量光照
    • LightMode Tags 分成 ForwardBase 跟 ForwardAdd 兩種
    • Base Pass 會進行環境光跟自發光計算,並處理一個逐像素平行光照,預設有陰影,需要使用編譯命令 #pragma multi_compile_fwdbase
    • Addition Pass 逐像素處理剩餘光照,預設無陰影,需要設定 Blend,並使用編譯命令 #pragma multi_compile_fwdadd
    • 如果需要陰影資料的 Addition Pass,則改用 #pragma multi_compile_fwdadd_fullshadows
  • Deferred Rendering Path
    • 對所有光照與 fregmant 進行深度測試,通過則將資料寫入 G Buffer,再用第二個 Pass 計算,寫入 Frame Buffer
    • 硬體需求較高,但是可以應對較多的光照
    • 不支持完整的抗鋸齒 (AA,anti-aliasing)、不能處理半透明
  • Vertex Lit Rendering Path:Unity 5.0 後已淘汰,屬於 Forward Rendering Path 的特例
  • 四種光源:平行光、點光源、聚光燈、面光源
    • 在 shader 中判斷光源類型:#ifdef USING_DIRECTIONAL_LIGHT
  • 光源屬性:位置、方向、顏色、強度、衰減
    • 取得光源的相對位置 :mul(_LightMatrix0, float4(worldPosition, 1)).xyz;
    • 取得顏色與強度的綜合值:_LightColor0
    • 對衰減值進行查表:tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  • 陰影渲染:
    • Unity 會取得物件底下 LightMode Tags 為 ShadowCaster 的 Pass,將攝影機置於光源位置,取得一系列的場景深度 (Shadow Map),用於判斷其他物件是否位於陰影中,透過設置適當的 Fallback 即可讓物件有此功能。
    • 陰影生成分為 產生陰影地圖在物體上透過採樣陰影地圖渲染陰影 兩步驟,Unity 的 Mesh Render 可以設定是否產生或接受陰影。
  • AutoLight.cginc 提供了可以用於計算陰影的內建方法,使物體可以接受陰影:
    • SHADOW_COORDS (int) - 呼叫於 vertex shader 的輸入結構定義,用於儲存陰影採樣的座標結構宣告,需要一個傳入值,為一個尚未使用的 texcoord 編號
    • TRANSFER_SHADOW (struct) - 呼叫於 vertex shader 中計算座標,需要將輸出結構作為傳入值。
    • SHADOW_ATTENUATION (struct) - 呼叫於 fragment shader,需要輸入結構作為傳入值,會回傳一個 fixed 變數,代表光線比例,跟漫反射及高光數值相乘即可。
    • 上面三個方法是使用 #define 進行定義,所以有一些額外的命名規則要遵守。
    • UNITY_LIGHT_ATTENUATION - 綜合了光照衰減採樣及陰影地圖採樣的方法。

第十章:進階紋理貼圖 (More Texture)

  • Cubemap
    • SkyBox 是將六張貼圖 (或者一張展開圖) 合併為一個立方體進行採樣的效果,為 Cubemap 的一種。
    • 動態生成的 Cubemap 可以用 Camera.RenderToCubemap 方法完成。
  • Cubemap 應用
    • 反射紋理:利用入射方向 (攝影機方向)、法線方向取得反射方向後進行採樣。
    • 折射紋理方法類似反射,但計算原理公式不同。
    • 因為反射折射與漫反射屬於類似的物理效應,所以會用 **一個可設定的比例 **混和兩者的顏色,替代原本漫反射的位置。
    • 另有 Schlick Fresnel 等式用於決定折射比例,可以渲染物體邊緣透光的效果:http://www.jordanstevenstechart.com/physically-based-rendering
  • Render Texture
    • 在專案中建立 Render Texture:可以調整解析度
    • GrabPass、OnRenderImage:解析度與螢幕大小相同,GrabPass 不適合在移動設備上使用
  • 使用 GrabPass 需要對應兩個變數:
    • GrabPass { “NAME” }
    • sampler2D NAME;
    • float4 NAME_TexelSize;
  • Procedural Texture
    • 使用腳本生成的 Texture 賦予 Material
    • Unity 另外支援透過 Substance Designer 所繪製的 Procedural Material
  • 本章提到的一些內建方法
    • reflect (入射方向, 法線方向) 可以計算反射方向
    • refract (單位入射方向, 單位法線方向, 折射係數) 可以計算折射方向
    • texCUBE (cubemap, direction) 對 cubemap 進行採樣
    • lerp (a, b, amount)
    • ComputeGrabScreenPos (頂點座標) 取得螢幕上的座標

第十一章:動畫

  • Unity shader 內建的時間變數:
    • _Time = (t/20, t, 2t, 3t),t 為自場景加載後的時間
    • _SinTime =  (t/8, t/4, t/2, t),t 為經過 sin 運算的時間
    • _CosTime 類上
    • unity_DeltaTime = (dt, 1/dt, smoothDt, 1/smoothDt)
  • 相關應用:
    • 逐格動畫
    • 無限滾動特效
    • 頂點動畫:水波動、Billboarding (讓平面永遠面向攝影機)
  • 頂點動畫注意事項
    • 需要避開 WorldSpace 的運算,否則必須 DisableBatching
    • 需要另外撰寫 ShadowCaster shader 來做陰影的動畫
  • 本章提到的一些內建方法
    • floor (float) 取高斯值
    • V2F_SHADOW_CASTER 內建方法計算所需的 v2f 定義
    • TRANSFER_SHADOW_CASTER_NORMALOFFSET (struct) 於 vertex shader 中計算陰影,傳入值為一個 v2f 結構
    • SHADOW_CASTER_FRAGMENT (struct) 於 fragmant shader 中輸出結果到 shadow map