【從UnityURP開始探索遊戲渲染】專欄-直達
漫反射基本流程
漫反射遵循蘭伯特定律(Lambert's Cosine Law),其核心流程如下:
- 法線準備:獲取表面法線向量(通常來自頂點法線或法線貼圖)
- 光源方向計算:確定光源到表面點的單位方向向量
- 點積運算:計算法線向量與光源方向的點積(N·L)
- 能量約束:使用saturate函數將結果限制在[0,1]範圍
- 顏色混合:將結果與光源顏色和表面反照率(albedo)相乘
數學表達式:
$漫反射 = 光源顏色 × 表面反照率 × max(0, N·L)$
漫反射基本原理
漫反射遵循蘭伯特定律(Lambert's Law),描述光線在粗糙表面均勻散射的現象。其核心特點是:
- 光線入射角度影響反射強度
- 表面法線方向決定反射分佈
- 與觀察角度無關的各向同性反射
蘭伯特定律 Lambert’s law
$Cdiffuse=(Clight*Mdiffuse)max(0,n·I)$
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
半蘭伯特
$Cdiffuse=(Clight*Mdiffuse)(a(n·I)+b)$
絕大多數a和b都為0.5
$Cdiffuse=(Clight*Mdiffuse)(0.5(n·I)+0.5)$
Unity URP中的實現細節
核心實現位置
URP中的漫反射計算主要分佈在以下文件:
Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
實現原理
- 法線處理:
- 世界空間法線轉換
- 法線貼圖支持
- 雙面渲染處理
- 光源計算:
- 主光源方向計算
- 附加光源循環處理
- 點光源/聚光燈方向計算
- 漫反射核心:
- 使用half精度優化
- 能量守恆處理
- 多光源疊加支持
關鍵代碼實現
-
UnityURP_漫反射實現
hlsl // 簡化版Lambert漫反射實現 half3 DiffuseLighting(Light light, half3 normalWS, half3 albedo) { half NdotL = saturate(dot(normalize(normalWS), light.direction)); return light.color * albedo * NdotL; } // 完整光照計算入口 half3 UniversalFragmentBlinnPhong(InputData inputData, SurfaceData surfaceData) { // 初始化光照結果 half3 color = surfaceData.emission; // 主光源漫反射計算 Light mainLight = GetMainLight(); color += DiffuseLighting(mainLight, inputData.normalWS, surfaceData.albedo); // 附加光源計算 uint pixelLightCount = GetAdditionalLightsCount(); for (uint lightIndex = 0; lightIndex < pixelLightCount; ++lightIndex) { Light light = GetAdditionalLight(lightIndex, inputData.positionWS); color += DiffuseLighting(light, inputData.normalWS, surfaceData.albedo); } return color; }
快速調用方法
在URP着色器中調用漫反射的標準方式:
自定義着色器方式:
hlsl
// 片元着色器示例
half4 frag(Varyings input) : SV_Target
{
// 初始化表面數據
SurfaceData surfaceData;
InitializeStandardLitSurfaceData(input.uv, surfaceData);
// 準備光照輸入數據
InputData inputData;
InitializeStandardLitInputData(input, surfaceData.normalTS, inputData);
// 計算漫反射光照
half4 color = UniversalFragmentBlinnPhong(inputData, surfaceData);
return color;
}
Shader Graph可視化方式:
- 使用"Dot Product"節點計算N·L
- 使用"Multiply"節點混合顏色
- 連接至"Fragment"輸出的Base Color通道
URP選擇此方案的原因
性能優化:
- 使用half精度計算
- 內置光照循環優化
- 最小化分支預測
物理一致性:
- 線性空間計算
- 正確的光照衰減(通過顏色與距離和陰影衰減相乘做到)
擴展性:
- 支持多光源場景
- 與PBR工作流兼容
- 可擴展自定義光照模型
跨平台支持:
- 適配移動端TBDR架構
- 支持SRP Batcher優化
- 兼容各種渲染路徑
在URP中,這種實現方式既保持了經典光照模型的直觀性,又通過現代渲染管線的優化手段確保了高性能表現,特別適合需要跨平台部署的項目。
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)