【光照】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模型:

c 复制代码
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

    c 复制代码
    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 复制代码
csharp
// C#控制光源示例using UnityEngine.Rendering.Universal;

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

高级配置参数‌:

csharp 复制代码
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)

    c 复制代码
    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开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

相关推荐
天人合一peng8 小时前
unity 生成标记根据背景色标记变色
unity·游戏引擎
天人合一peng12 小时前
unity 生成标记根据背景色变色为明显的颜色
unity·游戏引擎
魔士于安12 小时前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
CandyU212 小时前
Unity —— 数据持久化
unity·游戏引擎
zh路西法12 小时前
【Unity实现Oneshot胶卷显形】游戏窗口化与Win32API的使用
游戏·unity·游戏引擎
凡情17 小时前
android隐私合规检测
android·unity
小贺儿开发17 小时前
Unity3D 本地 Stable Diffusion 文生图效果演示
人工智能·unity·stable diffusion·文生图·ai绘画·本地化
mxwin1 天前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F1 天前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身1 天前
Lua脚本事件检查工具
unity·lua·工具