【從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
- 限制粒子數量(單發射器<50,屏幕總數<200)以控制頂點處理壓力
底層實現差異
ParticlesLit在Shader代碼中顯式優化了類型轉換和初始化(如half4 color = (half4)0),避免編譯器警告並提升執行效率。而Lit更側重通用物體渲染的精度和功能完整性。
綜合來看,ParticlesLit通過簡化光照模型、優化混合策略、限制資源消耗等方式,在保證粒子視覺效果的同時實現比Lit更高的渲染效率.
Particles Lit 的四種混合模式
ParticlesLit着色器提供了四種混合模式,主要用於控制粒子效果與背景的視覺融合方式
Alpha混合模式
通過材質的Alpha值控制透明度,0為完全透明,1為視覺上不透明但仍參與透明渲染通道。適用於需要漸變消失的效果,如雲朵消散。其特點是保持粒子顏色純度,但可能丟失高光細節。
Premultiply(預乘Alpha)
保留反射和高光特性,即使表面透明時仍能顯示鏡面效果。典型應用是透明玻璃或冰晶材質,僅反射光可見而本體透明。該模式需配合預乘處理的紋理使用,避免邊緣黑邊問題。
Additive(疊加)
將粒子顏色與背景色相加,產生增亮效果。適用於發光體如火焰、全息投影,能突出高亮區域但易導致過曝。火星特效常採用此模式增強核心亮度。
Multiply(相乘)
使粒子顏色與背景色相乘,產生變暗效果。模擬彩色玻璃透光或陰影疊加,適合風格化場景的氛圍營造。需注意暗部細節可能丟失。
應用選擇建議
- 性能考慮:Additive和Multiply計算量較低,Premultiply消耗較大
- 視覺特性:動態火焰推薦Additive,半透明物體用Alpha,材質反射需求選Premultiply
- 移動端優化:可改用Mobile/Particles/Additive等簡化着色器
混合模式可通過材質Inspector面板的"Blending Mode"下拉菜單切換,需配合Render Face(渲染面)和Alpha Clipping(透明剪切)等參數調整最終效果
深度紋理比對實現深度交互的碰撞效果
深度紋理獲取與處理
首先需啓用相機的深度紋理渲染功能,通過勾選RenderPipelineAsset中的DepthTexture選項生成場景深度圖。深度紋理存儲的是歸一化設備座標(NDC)的z分量值,經過非線性透視投影變換後,使用公式d=0.5*z+0.5將深度值映射到[0,1]範圍。正交投影的深度計算則是線性的,需區分處理。
碰撞檢測原理
通過比較屏幕空間中的頂點距離與場景深度緩衝區的值來實現碰撞判定。具體步驟包括:
- 訪問屏幕位置:獲取當前頂點在屏幕空間的座標和深度值。
- 深度差值計算:用場景深度值減去頂點深度值,得到兩者間的距離差。
- 邊緣梯度控制:通過調整場景位置的偏移量,可精確控制碰撞邊緣的漸變效果。
效果增強技術
- Alpha混合修正:將碰撞區域的Alpha值通過
1-操作反轉,並與菲涅爾效應疊加,可生成發光邊緣的視覺效果。 - 紋理變形技術:參考流體模擬中的UV座標動畫方法,通過動態扭曲紋理貼圖增強交互的真實感。例如Valve在《Portal 2》中採用滑動表面着色器,對UV座標進行時間驅動的位移計算。
性能優化
- 紋理複用:使用小塊紋理通過重複平鋪實現大範圍覆蓋,減少內存佔用。
- 簡化幾何體:對於背景物體,可用帶紋理的簡單幾何體替代高模,結合Billboard技術保持視覺一致性。
具體使用示例
創建火焰粒子材質:
- 新建材質並選擇Shader路徑:
Universal Render Pipeline > Particles > 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創建動態雨滴效果,包含紋理採樣和法線擾動功能,需配合粒子系統使用
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)