[閱讀筆記] Unity shader 入門精要 #3
《Unity shader 入門精要》的讀書筆記,九到十一章。 更深入的說明光照、貼圖,以及跟時間沾上邊的 shader
第九章:進階光照
- 渲染路徑 (Rendering Path)
- 只有設定了相對應的渲染路徑,shader才能取得對應的值。
- 可在 Player setting 或 Camera 中設定
- https://docs.unity3d.com/Manual/RenderingPaths.html
- 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
- 在 shader 中判斷光源類型:
- 光源屬性:位置、方向、顏色、強度、衰減
- 取得光源的相對位置 :mul
(_LightMatrix0, float4(worldPosition, 1)).xyz;
- 取得顏色與強度的綜合值:_LightColor0
- 對衰減值進行查表:
tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
- 取得光源的相對位置 :mul
- 陰影渲染:
- 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