【URP】Unity[后处理]颜色查询ColorLookup

【从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纹理。在渲染管线中,PostProcessPassExecute方法会检测并应用激活的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开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

posted @ 2025-11-04 11:11  SmalBox  阅读(53)  评论(0)    收藏  举报