【从UnityURP开始探索游戏渲染】专栏-直达
Unity URP内置的Particles Lit着色器是专为粒子系统设计的高质量光照模型,其核心作用是为火焰、烟雾、雨雪等动态粒子效果提供逼真的光照交互。该着色器采用URP的物理光照计算模型,支持透明混合、深度碰撞检测等高级特性,但会带来较高的性能开销。
原理与特性
- 光照模型:基于URP的PBR光照计算,支持方向光、点光源和聚光灯的实时交互,通过表面法线计算高光反射
- 混合模式:提供Alpha、Premultiply、Additive和Multiply四种混合模式,分别适用于云雾(Alpha)、玻璃反射(Premultiply)、全息效果(Additive)等场景
- 深度交互:可与深度纹理比对实现粒子碰撞效果,通过CS脚本在渲染管线中同步深度数据
发展沿革
- 2019年:随URP 7.x版本首次推出,最初仅支持基础光照模型
- 2021年:URP 12.x加入深度纹理交互支持,实现粒子碰撞效果
- 2023年:优化移动端性能,在URP 14.x中成为粒子系统默认推荐着色器
Particles Lit 对比 Lit
渲染模式选择
ParticlesLit专为粒子系统设计,提供更灵活的混合模式(如Additive、Multiply等),适合处理透明粒子的叠加效果,而Lit通常用于不透明或标准透明物体渲染。ParticlesLit支持通过Color Mode控制粒子颜色与材质颜色的混合方式(如Multiply、Additive等),可减少过度混合导致的性能损耗。
性能敏感功能裁剪
ParticlesLit默认关闭了Lit中部分高消耗特性(如复杂光照计算),采用简化的光照模型。例如,它避免使用完整PBR计算,转而使用预乘混合(Premultiply)保留高光的同时降低透明渲染开销。此外,粒子系统通常禁用碰撞检测和物理交互,进一步降低CPU负载。
资源复用与批处理
ParticlesLit鼓励材质共享和纹理图集化,通过减少DrawCall提升性能。建议多个粒子系统共用同一材质,且纹理尺寸不超过256x256。相比之下,Lit可能涉及更多独立材质实例,尤其在复杂场景中。
渲染参数优化
ParticlesLit提供针对粒子的特定参数控制:
- 通过Alpha Clipping实现硬边透明(如草叶效果),避免全透明混合的计算开销
- 推荐小尺寸粒子去除Alpha通道,改用Opaque渲染以减少Overdraw
- 限制粒子数量(单发射器 Lit
- 设置Surface Type为Transparent,Blending Mode为Additive
- 绑定粒子贴图并调整颜色参数:
- _MainTex: 火焰序列帧贴图
_Color: RGBA(1,0.5,0,0.8)
_Emission: 2.0
雨打到地上和物体上碰撞产生水花
- 雨水粒子基础配置:
- 使用Rectangle发射器形状并旋转90度使粒子垂直下落
- 设置Velocity over Lifetime的World空间模式确保雨滴始终朝Y轴降落
- 通过Linear参数添加XYZ方向偏移模拟风力效果
- 碰撞检测模块:
- 启用粒子系统的Collision模块,选择World碰撞模式
- 设置Dampen参数为1使碰撞后粒子完全停止
- 调整Bounce参数控制水花溅射力度
- 水花效果生成:
- 使用Sub Emitters模块在粒子消亡时触发子发射器
- 子粒子系统采用Horizontal Billboard渲染模式保持水平显示
- 通过Size over Lifetime曲线控制水花扩散动画
- RainCollisionController.cs
- using UnityEngine;
- [RequireComponent(typeof(ParticleSystem))]
- public class RainCollisionController : MonoBehaviour {
- private ParticleSystem _mainSystem;
- private ParticleSystem _splashSystem;
- void Start() {
- _mainSystem = GetComponent<ParticleSystem>();
- var collision = _mainSystem.collision;
- collision.enabled = true;
- collision.type = ParticleSystemCollisionType.World;
- // 获取子发射器系统
- _splashSystem = transform.GetChild(0).GetComponent<ParticleSystem>();
- }
- void Update() {
- // 动态调整粒子发射速率
- var emission = _mainSystem.emission;
- emission.rateOverTime = Mathf.Lerp(50, 500, WeatherManager.Instance.RainIntensity);
- }
- }
复制代码 - RainCollisionController.cs
- Shader "Custom/Ripple" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- _Speed ("Animation Speed", Range(0,5)) = 1.0
- }
- SubShader {
- Tags { "Queue"="Transparent" }
- Blend SrcAlpha OneMinusSrcAlpha
- Pass {
- HLSLPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- // 着色器代码...
- ENDHLSL
- }
- }
- }
复制代码 - 性能优化
- 纹理数组替代:使用Texture2DArray将多张纹理合并为单一资源,通过索引值(存储在SplatMap的R/G通道)选择纹理,减少采样次数。例如:
- hlsl
- half4 var_Main = SAMPLE_TEXTURE2D_ARRAY(_TexArray, sampler_TexArray, uv, splat.r * 255) * splat.b;
- half4 var_Sec = SAMPLE_TEXTURE2D_ARRAY(_TexArray, sampler_TexArray, uv, splat.g * 255) * (1 - splat.b);
- half4 finalRGB = var_Main + var_Sec;
复制代码 - 高度混合增强:结合高度图(存储在SplatMap的B通道)实现更自然的过渡效果,通过比较各层高度值动态调整权重
Shader Graph应用
实现雨滴效果:
- 创建新的Shader Graph,选择URP Particle Lit模板
- 添加Texture Sample节点连接Main Texture输入口
- 使用Custom Function节点实现法线扰动:
- hlsl
- void RainDistortion_float(float2 uv, out float3 normal){
- normal = float3(frac(uv.x * 10), frac(uv.y * 5), 1);
- }
复制代码
- 输出口连接Normal和Base Color通道
- RainParticle.shadergraph
- {
- "m_Nodes": [
- {
- "m_Type": "UnityEditor.ShaderGraph.Texture2DNode",
- "m_Outputs": [{ "m_Name": "Out" }],
- "m_Inputs": [{ "m_Name": "Texture", "m_DefaultValue": "Assets/Textures/RainDrop.png" }]
- },
- {
- "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode",
- "m_Outputs": [{ "m_Name": "normal" }],
- "m_Code": "RainDistortion_float"
- }
- ],
- "m_Edges": [
- { "m_OutputSlot": 0, "m_InputSlot": "BaseColor" },
- { "m_OutputSlot": 1, "m_InputSlot": "Normal" }
- ]
- }
复制代码 该示例通过Shader Graph创建动态雨滴效果,包含纹理采样和法线扰动功能,需配合粒子系统使用
<blockquote>
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |