【从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.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开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |