Stories

Detail Return Return

【光照】Unity中的[經驗模型] - Stories Detail

【從UnityURP開始探索遊戲渲染】專欄-直達

圖形學第一定律:“看起來對就對”

URP光照模型發展史

  • 2018年‌:URP首次發佈(原LWRP),繼承傳統前向渲染的Blinn-Phong簡化版
  • 2019年‌:URP 7.x引入Basic Shader的簡化光照模型
  • 2020年‌:URP 10.x整合PBR核心(GGX+Smith)
  • 2022年‌:URP 14.x新增Screen Space Global Illumination (SSGI)

核心原理架構

URP的經驗光照模型基於‌能量守恆近似‌和‌藝術家友好設計‌原則,通過數學簡化實現實時渲染效率。其核心公式體系包含:

光能分佈模型‌:

$L_o = L_d + L_s + L_a$

$L_d = k_d * (N·L) * I$

$L_s = k_s * (N·H)^n * I$

$L_a = k_a * I_a$

  • $L_d$:蘭伯特漫反射(Lambert)
  • $L_s$:Blinn-Phong鏡面反射
  • $L_a$:環境光分量

微表面近似‌:

URP的SimpleLit使用改進的Blinn-Phong模型:

hlsl
float spec = pow(max(0, dot(N, H)), _Glossiness * 256);
float3 specular = _SpecColor * lightColor * spec;

實現Blinn-Phong風格的光照模型

  • 使用URP標準庫Lighting.hlsl實現光照計算

  • 包含完整的頂點-片段着色器結構

  • 實現Blinn-Phong風格的光照模型

  • 支持主方向光的漫反射+鏡面反射計算

  • SimpleLit.shader

    
    Shader "Custom/SimpleLit"
    {
        Properties
        {
            _BaseColor("Color", Color) = (1,1,1,1)
            _SpecColor("Specular", Color) = (0.5,0.5,0.5)
            _Gloss("Glossiness", Range(0,1)) = 0.5
        }
    
        SubShader
        {
            Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
    
            HLSLINCLUDE
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    
            CBUFFER_START(UnityPerMaterial)
            float4 _BaseColor;
            float4 _SpecColor;
            float _Gloss;
            CBUFFER_END
    
            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
            };
    
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float3 normalWS : TEXCOORD0;
                float3 viewDirWS : TEXCOORD1;
            };
            ENDHLSL
    
            Pass
            {
                HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                Varyings vert(Attributes IN)
                {
                    Varyings OUT;
                    OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
                    OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS);
                    OUT.viewDirWS = GetWorldSpaceViewDir(TransformObjectToWorld(IN.positionOS.xyz));
                    return OUT;
                }
    
                half4 frag(Varyings IN) : SV_Target
                {
                    // 標準化向量
                    float3 N = normalize(IN.normalWS);
                    float3 V = normalize(IN.viewDirWS);
                    
                    // 獲取主光源
                    Light mainLight = GetMainLight();
                    float3 L = mainLight.direction;
                    float3 H = normalize(L + V);
                    
                    // 漫反射計算
                    float NdotL = max(0, dot(N, L));
                    float3 diffuse = _BaseColor.rgb * mainLight.color * NdotL;
                    
                    // 鏡面反射計算
                    float NdotH = max(0, dot(N, H));
                    float spec = pow(NdotH, _Gloss * 256);
                    float3 specular = _SpecColor.rgb * mainLight.color * spec;
                    
                    // 組合輸出
                    return half4(diffuse + specular, 1);
                }
                ENDHLSL
            }
        }
    }
    

實際應用步驟

創建材質‌:

  • 在Project窗口右鍵 → Create → Material
  • Shader選擇"Example/SimpleLit"

光源配置‌:

csharp
// C#控制光源示例using UnityEngine.Rendering.Universal;

public class LightController : MonoBehaviour {
    public Light2D urpLight;
    void Update() {
        urpLight.intensity = Mathf.PingPong(Time.time, 1.5f);
    }
}

高級配置參數‌:

csharp
// URP Asset配置路徑
Edit → Project Settings → Graphics → Scriptable Render Pipeline Settings

關鍵參數:

  • Main Light Shadows
  • Additional Lights Count
  • Reflection Probes

性能優化建議

  • 移動平台使用SimpleLit代替Lit
  • 控制Additional Lights數量(建議≤4)
  • 使用Light Layers分層渲染
  • 靜態物體啓用Baked Global Illumination

最新版URP(2023.2)已支持光線追蹤擴展包,可通過Package Manager添加Ray Tracing模塊實現混合渲染管線。

核心光照模型實現類

類名 功能
UniversalForwardRenderer 主渲染管線入口
Lighting.hlsl 包含所有光照計算函數
BRDF.hlsl 實現PBR核心算法
MainLight.hlsl 主方向光處理
AdditionalLights.hlsl 附加點光源/聚光燈

URP內置光照模型類型

graph TB A[URP Shader] --> B[SimpleLit] A --> C[Lit PBR] A --> D[Unlit] B --> E[Blinn-Phong變體] C --> F[GGX+Smith]

URP實現架構

graph LR A[URP Asset] --> B[ForwardRenderer] B --> C[Lighting Pass] C --> D[MainLight.hlsl] C --> E[AdditionalLights.hlsl] D --> F[Blinn-Phong計算] E --> G[逐光源疊加]

關鍵HLSL實現

URP光照計算核心代碼路徑:

Packages/com.unity.render-pipelines.universal/ShaderLibrary/
├── Lighting.hlsl         # 光照入口
├── MainLight.hlsl        # 主方向光處理
├── AdditionalLights.hlsl # 附加光源
└── BRDF.hlsl            # PBR基礎函數

URP中快速調用標準光照模型實現

腳本位置

  • URP內置的SimpleLit.shaderLit.shader(位於Packages/com.unity.render-pipelines.universal/Shaders/
  • 關鍵變量:_SpecularIntensity(控制高光強度)和_Smoothness(控制反射模糊度)

核心計算邏輯

  • Lambert漫反射‌:通過dot(worldNormal, worldLightDir)計算基礎光照

  • Phong/Blinn-Phong鏡面反射‌:其中halfDir為半角向量(normalize(lightDir + viewDir)

    hlsl
    // Phong模型
    float3 specular = pow(max(0, dot(reflectDir, viewDir)), _SpecularIntensity);
    // Blinn-Phong模型
    float3 specular = pow(max(0, dot(normal, halfDir)), _SpecularIntensity);
    

‌Lighting.hlsl直接調用以上計算公式-調用入口

  • 在Shader的SurfaceInput.hlsl中定義光照輸入結構體InputData
  • 通過UniversalFragmentBlinnPhong函數處理光照,這些都定義在Lighting.hlsl中。
  • 在Lighting.hlsl中有以下經驗光照的函數可直接調用
    • LightingLambert
    • LightingSpecular
    • CalculateBlinnPhong
    • UniversalFragmentBlinnPhong

【從UnityURP開始探索遊戲渲染】專欄-直達

(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)

Add a new Comments

Some HTML is okay.