Unity Shader學習:貼花(Decal)_貼圖

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 DistanceStart 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處理