【從UnityURP開始探索遊戲渲染】專欄-直達
GGX的全稱與基本概念
GGX的全稱:Ground Glass X (或 Generalized Trowbridge-Reitz Distribution)
首次提出:Walter等人在2007年發表的論文《Microfacet Models for Refraction through Rough Surfaces》中提出
GGX是一種法線分佈函數(Normal Distribution Function, NDF),用於描述微表面模型中微觀幾何表面法線的概率分佈。它是Unity URP中PBR渲染的核心組成部分,替代了傳統的Beckmann分佈。
GGX的數學原理
核心公式
在Unity URP中,GGX分佈的實現基於以下公式:
$D_{GGX}(h)=\frac{α_g2}{π[(n⋅h)2(α_g2−1)+1]2}$
其中:
- h:半角向量(光線方向與視線方向的中間向量)
- n:表面法線
- $α_g$:粗糙度參數($α_g=roughness^2$)
Unity URP中的代碼實現
在Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl中:
hlsl
// GGX/Trowbridge-Reitz分佈函數
float D_GGX(float NdotH, float roughness)
{
float a = roughness * roughness; // 粗糙度平方
float a2 = a * a;
float NdotH2 = NdotH * NdotH;
float denom = NdotH2 * (a2 - 1.0) + 1.0;
denom = PI * denom * denom;
return a2 / max(denom, 0.000001); // 避免除零錯誤
}
GGX的核心特性
長尾分佈特性
- 相比Beckmann分佈,GGX具有更長的"尾巴"
- 能更好地模擬真實世界的材質高光衰減
- 產生更自然的反射光暈效果
能量守恆
- $∫_ΩD_{GGX}(h)(n⋅h)dω=1$
- 保證了光線能量在反射過程中不會無故增加或減少
- 是PBR渲染的基礎要求
各向同性/各向異性支持
hlsl
// URP中各向異性GGX實現
float D_GGX_Anisotropic(float NdotH, float HdotX, float HdotY, float ax, float ay)
{
float denom = HdotX*HdotX/(ax*ax) + HdotY*HdotY/(ay*ay) + NdotH*NdotH;
return 1.0 / (PI * ax * ay * denom * denom);
}
GGX與其他分佈函數對比
| 特性 | GGX | Beckmann | Blinn-Phong |
|---|---|---|---|
| 真實度 | ★★★★☆ | ★★★☆☆ | ★★☆☆☆ |
| 性能開銷 | ★★☆☆☆ | ★★★☆☆ | ★☆☆☆☆ |
| 長尾表現 | 優異 | 中等 | 較差 |
| 移動端支持 | 良好 | 一般 | 優秀 |
| URP默認 | 是 | 否 | 僅在SimpleLit中使用 |
GGX在Unity URP中的實際應用
材質粗糙度映射
hlsl
// 粗糙度處理流程
float perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
// 應用紋理採樣
roughness = roughness * _RoughnessMap.Sample(sampler_MainTex, uv).r;
高光反射計算
hlsl
// BRDF.hlsl中的完整鏡面反射計算
half3 BRDF_SpecularGGX(half3 F0, half roughness, half NdotH, half NdotL, half NdotV, half LdotH)
{
half D = D_GGX(NdotH, roughness); // GGX法線分佈
half V = V_SmithGGXCorrelated(NdotL, NdotV, roughness); // 幾何衰減
half3 F = F_Schlick(LdotH, F0); // 菲涅爾反射
return (D * V) * F;
}
環境光反射處理
hlsl
// 環境BRDF計算(使用GGX分佈)
half2 envBRDF = tex2D(_BRDFLUT, float2(NdotV, roughness)).rg;
half3 envSpecular = specularColor * envBRDF.x + envBRDF.y;
GGX的視覺表現特點
粗糙材質表現
- 低粗糙度:鋭利的高光反射
- 中粗糙度:柔和的散射光暈
- 高粗糙度:均勻的漫反射外觀
邊緣響應
- 在材質邊緣產生自然的亮度衰減
- 模擬真實物體的菲涅爾效應
材質連續性
- 粗糙度參數從0到1變化時表現平滑過渡
- 避免傳統模型的突兀變化
性能優化技巧
近似計算
hlsl
// GGX的移動端近似
float D_GGX_Mobile(float NdotH, float roughness)
{
float a = roughness * roughness;
float a2 = a * a;
float d = NdotH * NdotH * (a2 - 1.0) + 1.0;
return a2 / (d * d * PI);
}
預積分技術
- URP使用預計算的BRDF查找紋理(_BRDFLUT)
- 將複雜計算轉移到預處理階段
動態降級
hlsl
#if defined(SHADER_API_MOBILE)
// 移動端簡化版GGX
#else
// 完整精度GGX
#endif
GGX分佈作為Unity URP中PBR渲染的核心,通過其獨特的數學特性和長尾分佈,實現了比傳統模型更真實的材質表現。雖然計算複雜度略高,但其在視覺質量和物理準確性上的優勢使其成為現代實時渲染的標準選擇。
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)