- 前言
經過 Image Based Lighting (1)、Image Based Lighting (2) 的研究與討論,
本篇將展現實作結果並和 Unity 內建的 Standard Shader 做分析與比較。
- 比對與分析
我使用 Unity 內建的 Standard Shader 作為對照組,
將兩組使用同樣的渲染參數並排比對,
檢視在 metallic = 0 和 = 1 時的 roughness 變化的結果 (註1),
環境光源貼圖使用我在 Image Based Lighting (1) 提到的下圖 cubemap
上排是 Standard Shader 、 下排是 Image Based Lighting (之後簡稱 IBL) 渲染 shader。
當 metallic = 0 時,roughness(粗糙度)由左至右提升的比對結果
當 metallic = 1 時,roughness(粗糙度)由左至右提升的比對結果
Unity 對於環境光照的實作是參考 "Stupid Spherical Harmonics (SH) Tricks." [1] 的計算,
使用前3階的 Table of spherical harmonics (球諧函數表) 共9個球諧係數來計算環境光照。
比較結果可以看的出來使用 IBL 的環境光照效果會比較強,所以整體顏色會比較飽和,
反射效果也比較明顯。
- 實作程式碼
主要是接續 淺談 physically based rendering (4) 的程式碼,新增間接光照的處理。
其中
是計算間接光照的 Diffuse 部分,可參考 Image Based Lighting (1)
上段程式碼是計算間接光照的Specular 部分,可參考 Image Based Lighting (2)
最後的這一段是計算 Tone Mapping,可參考 Tone Mapping (色調映射)
在 Mobile 上,為了效能考量, 我限制 IBL pre-compute 的輸出結果,
將 prefilter Enviorment map 設定為 512x512 的 cubamp ,並包含 5 個 Mipmap,
BRDF integrate map 也是限制為 512x512,
Diffuse Irradiance 則因為效果不明顯,我使用 32x32 解析度來增加效能。
在 Sony L3 運作並使用 ApowerREC 錄製視頻。
其中
float3 DiffuseIrradiance(float3 albedo, float3 normalDirection, float3 F0, float NdotV, float roughness) { float3 F90 = max(1.0 - roughness, F0); float3 fresnel = F0 + (F90 - F0) * Schlick(NdotV); float3 refract = 1.0 - fresnel; float3 kD = refract * (1.0 - _metallic); float3 irradiance = texCUBE (_IrradianceD, normalDirection).rgb; irradiance = irradiance; return kD * irradiance * albedo; }
是計算間接光照的 Diffuse 部分,可參考 Image Based Lighting (1)
float3 SpecularIBL(float3 reflectDirection, float3 F0, float NdotV, float roughness) { float3 PrefilteredColor = UNITY_SAMPLE_TEXCUBE_LOD(_PrefiliterEnv, reflectDirection, roughness * UNITY_SPECCUBE_LOD_STEPS).rgb; float2 EnvBRDF = tex2Dlod(_IntegrateBRDF, float4(NdotV, roughness, 0.0, 0.0)).rg; return PrefilteredColor * (F0 * EnvBRDF.x + EnvBRDF.y); }
上段程式碼是計算間接光照的Specular 部分,可參考 Image Based Lighting (2)
float3 Approx_ACES(float3 linearCol) { float a = 2.51; float b = 0.03; float c = 2.43; float d = 0.59; float e = 0.14; return clamp((linearCol*(a*linearCol+b))/(linearCol*(c*linearCol+d)+e), 0.0, 1.0); } float3 ACES_tone_mapping(float3 linearCol) { const float exposureBias = 2; return Approx_ACES(linearCol * exposureBias); }
最後的這一段是計算 Tone Mapping,可參考 Tone Mapping (色調映射)
- Mobile 運作效果
在 Mobile 上,為了效能考量, 我限制 IBL pre-compute 的輸出結果,
將 prefilter Enviorment map 設定為 512x512 的 cubamp ,並包含 5 個 Mipmap,
BRDF integrate map 也是限制為 512x512,
Diffuse Irradiance 則因為效果不明顯,我使用 32x32 解析度來增加效能。
在 Sony L3 運作並使用 ApowerREC 錄製視頻。
左手邊為 Unity Standard Shader,右手邊為本篇所展示的 Shader。
- References
1. Peter-Pike Sloan. "Stupid Spherical Harmonics (SH) Tricks." Presented at Game Developers
Conference, San Francisco, CA, February 18-22, 2008.
- 附註
1. 在 Unity Standard Shader 是使用 Smoothness (平滑度) 作為 microfacet 崎嶇參數,
和 roughness 的關係是 roughness = 1 - Smoothness 。