【從UnityURP開始探索遊戲渲染】專欄-直達
技術定義與核心作用
ColorLookup是基於LUT(Lookup Table)技術的顏色映射系統,通過預定義的256x16像素條狀PNG紋理實現全局色彩替換。其核心價值在於:
- 風格統一:批量修改場景色彩,避免逐物體調整
- 影視級調色:支持專業調色軟件生成的.cube格式轉換
- 性能優化:相比實時計算的顏色調整,LUT採樣消耗固定性能
發展歷程
- 影視起源(2000年代):LUT最初用於跨設備色彩管理
- 引擎引入(2010-2016):Unity 5.x開始實驗性支持.cube格式
- URP整合(2019+):成為URP標準後處理棧組件,優化移動端支持
實現技術細節
- 紋理映射機制:將原始RGB值作為UV座標採樣LUT紋理
- 管線集成:通過ColorGradingLutPass在渲染管線早期生成LUT
- 混合控制:使用Contribution參數進行線性插值混合
Unity URP中的ColorLookup(顏色查找表)是一種基於LUT(Look-Up Table)技術的後處理效果,其核心原理是通過預定義的紋理映射表對屏幕像素顏色進行非線性轉換,實現全局色調調整。
LUT技術基礎
- 數據結構:LUT通常為256x16或1024x32尺寸的紋理,每個Tile(32x32)對應一個顏色映射區塊。x軸表示R通道值(0-1均勻離散為32級),y軸表示G通道值,而不同Tile的排列順序對應B通道值的離散化。
- 映射邏輯:輸入顏色RGB值被分解為(R,G)座標和B通道索引,通過三次紋理採樣(或插值計算)輸出目標顏色。例如,B通道決定使用第幾個Tile,(R,G)定位該Tile內的具體像素。
URP中的實現機制
- Volume組件集成:ColorLookup作為VolumeComponent子類,通過
TextureParameter綁定LUT紋理。在渲染管線中,PostProcessPass的Execute方法會檢測並應用激活的ColorLookup效果。 -
Shader處理流程:
- 顏色空間轉換:輸入顏色從sRGB轉為線性空間。
- LUT採樣:根據輸入RGB計算紋理座標,採樣LUT獲取映射後顏色。
- 強度混合:通過
Contribution參數控制原色與LUT色的混合比例。
代碼示例與解析
以下為簡化版Shader代碼,展示LUT的核心採樣邏輯:
hlsl
float3 ApplyColorLookup(float3 inputColor, Texture2D lutTexture, float contribution) {
// 計算B通道對應的Tile索引和偏移量
float blueOffset = inputColor.b * 31.0;
int tileIndex = floor(blueOffset);
float lerpFactor = frac(blueOffset);
// 計算(R,G)在Tile內的UV座標
float2 uv = float2(
inputColor.r * (31.0 / 32.0) + (0.5 / 32.0),
inputColor.g * (31.0 / 32.0) + (0.5 / 32.0) + (tileIndex / 32.0)
);
// 採樣相鄰Tile並插值
float3 color1 = lutTexture.Sample(samplerLinearClamp, uv).rgb;
float3 color2 = lutTexture.Sample(samplerLinearClamp, uv + float2(0, 1.0/32.0)).rgb;
float3 mappedColor = lerp(color1, color2, lerpFactor);
// 混合原始顏色與LUT結果
return lerp(inputColor, mappedColor, contribution);
}
關鍵點説明:
- Tile索引計算:B通道值乘以31(1024x32 LUT)確定起始Tile位置。
- 邊緣處理:UV座標添加0.5/32.0偏移避免採樣到相鄰Tile。
- 性能優化:實際URP源碼會結合
Blit命令和全屏三角形渲染,減少紋理採樣次數。
應用場景與限制
- 風格化調色:通過冷色調/暖色調LUT快速統一畫面風格。
- 性能考量:1024x32 LUT比256x16精度更高,但會增加帶寬消耗,移動端建議使用壓縮格式(如ASTC)。
- 動態切換:可通過腳本修改
Volume.profile中的TextureParameter實現運行時LUT切換
完整實現示例
-
ColorLookupController.cs
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; [RequireComponent(typeof(Volume))] public class ColorLookupController : MonoBehaviour { [Header("LUT配置")] [Tooltip("256x16 PNG格式LUT紋理")] public Texture2D lookupTexture; [Range(0, 1), Tooltip("LUT混合強度")] public float intensity = 0.8f; private ColorLookup _colorLookup; void OnEnable() { var volume = GetComponent<Volume>(); if (!volume.profile.TryGet(out _colorLookup)) { _colorLookup = volume.profile.Add<ColorLookup>(); } UpdateParameters(); } void Update() { if (_colorLookup.texture.value != lookupTexture || !Mathf.Approximately(_colorLookup.contribution.value, intensity)) { UpdateParameters(); } } void UpdateParameters() { _colorLookup.texture.Override(lookupTexture); _colorLookup.contribution.Override(intensity); } }
參數詳解與用例
| 參數 | 類型 | 作用 | 典型用例 |
|---|---|---|---|
| texture | Texture2D | LUT紋理(需關閉sRGB) | 賽博朋克風格紫紅色調 |
| contribution | float [0-1] | 效果強度 | 0.5實現半色調效果 |
| mode | enum | 處理模式 | Dual模式用於AB測試 |
工作流程最佳實踐
-
紋理準備:
- 使用Photoshop創建中性灰LUT基底
- 通過調整圖層修改色彩風格
- 導出256x16 PNG(關閉壓縮)
-
Unity設置:
- 紋理導入設置:
- sRGB: Off
- Compression: None
- Wrap Mode: Clamp
-
動態切換:
csharp // 運行時切換LUT public void ApplyLUT(Texture2D newLUT) { lookupTexture = newLUT; UpdateParameters(); }
性能優化建議
- 移動端使用512x32紋理平衡質量與性能
- 結合URP的SRP Batcher減少Draw Calls
- 避免每幀修改Contribution參數
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)