姜删懔 发表于 2025-10-1 17:41:00

【光照】Unity中的[经验模型]

【从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 --> B    A --> C    A --> D    B --> E    C --> FURP实现架构

graph LR    A --> B    B --> C    C --> D    C --> E    D --> F    E --> G[逐光源叠加]关键HLSL实现

URP光照计算核心代码路径:

Packages/com.unity.render-pipelines.universal/ShaderLibrary/
├── Lighting.hlsl         # 光照入口
├── MainLight.hlsl      # 主方向光处理
├── AdditionalLights.hlsl # 附加光源
└── BRDF.hlsl            # PBR基础函数URP中快速调用标准光照模型实现

‌脚本位置‌


[*]URP内置的SimpleLit.shader和Lit.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开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 【光照】Unity中的[经验模型]