【從UnityURP開始探索遊戲渲染】專欄-直達
菲涅爾效應基本流程
菲涅爾效應(F)在BRDF中描述光線在不同入射角下的反射率變化,其計算流程通常分為三個步驟:
- 基礎反射率確定:0°入射角時的反射率(F₀)
- 角度依賴計算:根據入射角變化調整反射率
- 金屬/非金屬處理:區分導體和絕緣體的不同表現
主要菲涅爾模型實現
1. Schlick近似模型
原理:
- 對完整菲涅爾方程的簡化近似
- 使用有理函數替代複雜計算
公式:
$F_{Schlick}(v,h)=F_0+(1−F_0)(1−(v⋅h))^5$
特點:
- 計算效率高
- 精度足夠實時渲染使用
- 在掠射角(90°)強制反射率為1
Unity URP實現:
hlsl
// Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl
half3 F_Schlick(half u, half3 F0)
{
return F0 + (1 - F0) * pow(1 - u, 5);
}
2. 完整菲涅爾方程
原理:
- 基於麥克斯韋電磁學方程
- 考慮光的偏振特性
公式:
$F_{完整}=\frac12[(\frac{g−c}{g+c})^2+(\frac{c(g+c)−1}{c(g−c)+1})^2]$
其中 $c=v⋅h, g=\sqrt{n^2+c^2−1}$
特點:
- 物理精確但計算複雜
- 主要用於離線渲染
3. Spherical Gaussian近似
原理:
- 用高斯函數近似菲涅爾曲線
- 特別適合移動端
公式:
$F_{SG}(v,h)=F_0+(1−F_0)2^{(−5.55473(v⋅h)−6.98316)(v⋅h)}$
特點:
- 無pow函數計算
- 適合低精度硬件
Unity URP的選擇與實現
核心方案:Schlick近似 + 金屬工作流
完整實現代碼:
hlsl
// URP中的菲涅爾計算
half3 F_Fresnel(half3 F0, half u)
{
half t = pow(1 - u, 5); // Schlick的(1-cosθ)^5項
return saturate(F0 + (1 - F0) * t); // 基礎Schlick公式
}
// 實際應用時:
half3 F = F_Fresnel(F0, saturate(dot(viewDir, halfDir)));
選擇原因:
-
性能與質量平衡:
- 僅需1次pow運算
- 視覺誤差小於2%,人眼難以察覺
-
金屬/非金屬統一處理:
hlsl // F0基礎反射率計算 half3 F0 = lerp(0.04, albedo, metallic); // 0.04是非金屬基礎反射率 -
能量守恆:
- 保證反射光能量不超過入射光
- 與GGX+Smith模型完美配合
-
藝術家友好:
- 通過metallic參數直觀控制
- 反射顏色直接取自albedo貼圖
優化實現細節
-
移動端優化版:
hlsl half3 F_FresnelMobile(half3 F0, half u) { half t = exp2((-5.55473 * u - 6.98316) * u); // SG近似 return saturate(F0 + (1 - F0) * t); } -
各向異性擴展:
hlsl half3 F_Anisotropic(half3 F0, half u, half anisotropy) { half t = pow(1 - u, 5); return F0 + (max(1 - anisotropy, 0.1) - F0) * t; } -
多散射補償:
hlsl half3 F_MultiScatter(half3 F0, half u, half roughness) { half3 F = F_Fresnel(F0, u); half3 Favg = F0 + (1 - F0) / 21; // 平均菲涅爾 return F + (Favg - F) * roughness * 0.9; }
各模型性能對比
| 模型 | 指令數 | 特殊函數 | 移動端適用性 | 物理精度 |
|---|---|---|---|---|
| Schlick | 6-8 | pow() | ★★★★☆ | ★★★☆☆ |
| 完整方程 | 20+ | sqrt等 | ★☆☆☆☆ | ★★★★★ |
| Spherical Gaussian | 5-7 | exp2() | ★★★★★ | ★★☆☆☆ |
| URP實現 | 7-9 | pow() | ★★★★☆ | ★★★★☆ |
為什麼Schlick成為行業標準
歷史驗證:
- 自1994年提出以來經過大量實踐驗證
- 被所有主流引擎採用(Unreal, Unity, Frostbite等)
硬件友好:
- 現代GPU對pow函數有硬件優化
- 不需要複雜分支判斷
參數直觀:
hlsl
// 基礎反射率設置示例
float3 F0 = float3(0.04, 0.04, 0.04); // 塑料
float3 F0 = float3(0.95, 0.64, 0.54); // 銅
擴展性強:
- 容易與各向異性、清漆層等效果結合
- 支持多散射補償等高級特性
Unity URP選擇Schlick近似是在實時渲染約束下做出的最優權衡,能夠在保持物理合理性的同時滿足性能要求,特別是在移動平台上表現出色。隨着硬件發展,雖然更精確的模型變得可行,但Schlick因其簡潔有效仍然是實時渲染的首選方案。
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)