Unity URP中的Decal(貼花)系統是一種用於將材質投射到場景幾何體表面的技術,主要用於實現血跡、彈孔、塗鴉等動態表面裝飾效果。以下是詳細解析: 核心功能與用途 動態投影:通過Decal
【從UnityURP開始探索遊戲渲染】專欄-直達
Unity URP中的Decal(貼花)系統是一種用於將材質投射到場景幾何體表面的技術,主要用於實現血跡、彈孔、塗鴉等動態表面裝飾效果。以下是詳細解析:
核心功能與用途
- 動態投影:通過Decal Projector組件將材質動態投射到任意表面,包括曲面和複雜幾何體
- 光照交互:支持與場景光照系統交互,可模擬陰影、高光等物理效果
- 典型應用場景:
- 遊戲中的彈孔、血跡、塗鴉
- 環境細節增強(如牆面裂縫、污漬)
- 技能範圍指示器(如Dota2的地面標記)
技術演進
|
版本階段
|
實現方式
|
特性差異
|
|
傳統實現
|
基於面片Mesh
|
僅支持平面投影,無法適應複雜曲面
|
|
URP早期
|
Projector組件
|
存在深度衝突(Z-fighting)問題,性能開銷大
|
|
URP 12+
|
Decal Renderer Feature
|
支持PBR材質,與SRP深度集成,性能優化
|
原理
Unity URP中的Decal系統通過深度緩衝重建世界座標和材質投影技術實現動態貼花效果,其核心原理可分為以下技術層級:
底層渲染流程
- 深度圖採樣
Decal Renderer Feature在渲染管線中插入自定義Pass,通過_CameraDepthTexture獲取像素深度值,結合攝像機參數重建世界座標。關鍵公式:
worldPos = _CameraToWorld矩陣 × (屏幕UV + 深度值 × 視錐向量)
- 投影體積裁剪
使用Decal Projector定義的立方體邊界(Size參數)進行空間裁剪,通過射線與AABB碰撞檢測判斷像素是否在投影範圍內。超出範圍的像素會被剔除。 - 材質混合
採用延遲渲染路徑的GBuffer修改策略,通過Blend指令將Decal的Albedo/Normal/Metallic等屬性與場景材質混合,支持PBR光照交互。
關鍵代碼實現示例
以下為簡化版Shader核心邏輯:
hlsl
// 深度重建世界座標
float3 ReconstructWorldPos(float2 uv, float depth) {
float4 clipPos = float4(uv * 2 - 1, depth, 1);
float4 worldPos = mul(_ClipToWorld, clipPos);
return worldPos.xyz / worldPos.w;
}
// 投影體積判斷
bool IsInDecalVolume(float3 worldPos, float3 decalPos, float3 size) {
float3 localPos = mul(_WorldToDecal, float4(worldPos, 1)).xyz;
return all(abs(localPos) < 0.5);
}
技術演進對比
|
版本
|
技術方案
|
缺陷
|
改進點
|
|
傳統實現
|
基於Mesh面片投影
|
無法適應曲面
|
-
|
|
URP 10
|
屏幕空間深度採樣
|
透明物體不支持
|
減少Z-fighting
|
|
URP 12+
|
GBuffer混合+體積裁剪
|
性能開銷較高
|
支持PBR和動態光照
|
性能優化要點
- 層級剔除:通過
Decal Layer分類控制不同Decal的渲染層級 - 距離淡出:
Draw Distance和Start Fade參數動態減少遠處Decal計算 - 批處理:相同材質的Decal Projector會自動合併繪製調用
典型問題解決方案
- 透明物體支持:需自定義Shader重寫
AlphaTest邏輯 - 曲面變形:增加
Normal Smoothing參數修正法線插值 - 移動端適配:降低深度圖精度或使用
Depth Prepass策略
完整實現流程
- 創建URP Asset:
- 菜單欄 Edit > Project Settings > Graphics
- 指定URP Pipeline Asset
- 添加Decal Renderer Feature:
- 在URP Renderer Data中添加Decal Renderer Feature
- 設置Priority控制渲染順序
- 創建Decal材質:
- Shader選擇"Universal Render Pipeline/Decal"
- 配置Albedo、Normal等貼圖通道
- 放置Decal Projector:
- 創建空GameObject
- 添加Decal Projector組件
- 關聯步驟創建的材質
關鍵參數詳解
|
參數
|
類型
|
作用
|
典型值
|
|
Size |
Vector3
|
控制投影體積尺寸
|
(2,2,2)
|
|
Fade Factor |
Float [0-1]
|
邊緣漸變強度
|
0.8
|
|
Draw Distance |
Float
|
渲染距離閾值
|
20
|
|
Start Fade |
Float
|
開始淡出的距離
|
15
|
|
Angle Fade |
Vector2
|
基於表面角度的淡出
|
(0.5,0.8)
|
|
Affects Transparent |
Bool
|
是否影響透明表面
|
False
|
案例:彈孔效果
- 材質準備:
- 使用8K掃描的彈孔貼圖(Quixel Megascans)
- 法線貼圖增強立體感
- 動態生成:
csharp
void CreateBulletHole(Vector3 hitPoint, Vector3 normal) {
var decal = new GameObject("BulletHole");
var projector = decal.AddComponent<DecalProjector>();
projector.material = bulletHoleMaterial;
decal.transform.position = hitPoint + normal * 0.1f;
decal.transform.rotation = Quaternion.LookRotation(-normal);
}
- 性能優化:
- 使用對象池管理Decal實例
- 設置合理的Draw Distance避免過度渲染
注意事項
- 深度衝突:適當調整Projector的Offset參數(建議0.05-0.1)
- 移動平台:需測試ES3.0設備兼容性,必要時降低貼圖分辨率
- 透明表面:默認不支持透明物體接收Decal,需特殊Shader處理