作用
核心功能
动态范围压缩:将HDR光照数据(如阳光直射与阴影的极端亮度差)映射到0-1的LDR范围,避免高光过曝或暗部细节丢失。
视觉优化:通过非线性曲线调整亮度和对比度,模拟人眼对光照的非线性感知,增强画面电影感或自然感。
典型应用:HDR渲染、Bloom特效配合、影视化色彩分级。
与Gamma校正的区别
Gamma校正是简单的幂律变换,而色调映射涉及全局/局部的动态范围适配策略,如ACES算法会改变色相和饱和度以实现电影级效果。
发展历史
早期算法:如Reinhard算子(全局映射),通过对数压缩保留整体氛围,但局部对比度不足。
进阶算法:ACES(学院色彩编码系统)成为行业标准,提供更自然的亮部压缩和色彩空间转换。
现代优化:Unity URP/HDRP引入Custom模式,支持用户自定义曲线参数(如Toe/Shoulder强度),平衡性能与效果。
原理
色调映射(Tonemapping)是将高动态范围(HDR)图像转换为标准动态范围(SDR)显示的核心技术,其底层原理主要涉及非线性压缩和感知优化。以下是详细解释:
HDR到LDR的转换需求
在HDR渲染中,光照强度可能远超显示器能表现的0-1范围(如阳光亮度可达6.5单位),直接显示会导致亮部细节丢失为纯白。色调映射通过以下方式解决:
动态范围压缩:将HDR的高亮度值(如>1.0)非线性压缩到LDR的0-1范围,避免简单截断导致的亮部细节丢失。
感知适配:模拟人眼对亮度的非线性响应(如韦伯-费希纳定律),在暗部保留更多细节。
核心算法原理
ACES曲线(常用电影级算法)
公式:通过有理分式实现高光柔和压缩,同时增强中间调对比度。
$f(x)=\frac {x(2.51x+0.03)}{x(2.43x+0.59)+0.14}$
示例效果:输入亮度6.5会被映射到约0.95,而0.5亮度映射到0.45,既保留高光层次又避免整体发灰。
Neutral模式(中性映射)
采用对数变换:最小化色相偏移,适合需要后续色彩分级的场景。
$f(x)=\frac {log(x+1)}{log(X_{max}+1)}$
自定义曲线参数
Toe/Shoulder控制:
Toe Strength调整暗部过渡(0.5时暗部细节更明显)
Shoulder Angle控制高光压缩斜率(值越大高光保留越多)(具体参数见下表)
参数 作用 典型值
Gamma 整体伽马校正 2.2
Toe Length 暗部动态范围占比 0.3-0.5
Shoulder Strength 高光过渡硬度 0.5-0.8
URP实现示例
在URP中通过Volume组件添加Tonemapping覆盖,关键代码如下:
csharp
// 通过Volume API动态修改参数
var volume = GetComponent<Volume>();
if (volume.profile.TryGet(out Tonemapping tone)) {
tone.mode.value = TonemappingMode.ACES;
tone.shoulderStrength.value = 0.7f;
}
此代码将模式设为ACES并调整高光过渡强度。
视觉对比实验
测试场景中:
无Tonemapping时,阳光区域(亮度5.0)显示为全白;
启用ACES后,同一区域呈现为淡黄色并保留云层纹理。
该技术本质是基于人眼感知特性的动态范围重映射,通过非线性函数平衡物理准确性与视觉舒适度。
Unity URP实现流程
启用Tonemapping
需通过Volume框架添加后处理覆盖:
创建或选择已有Volume GameObject。
在Inspector中点击 Add Override > Post-processing > Tonemapping。
参数详解
参数 说明 用例
Mode 映射算法类型 ACES适合电影感,Neutral保留原始色彩
Toe Strength 暗部过渡强度 值越高,阴影对比度越强(Custom模式有效)
Shoulder Length 高光动态范围 控制亮部细节保留程度
Lookup Texture 自定义LUT纹理 实现风格化调色(如赛博朋克色调)
完整示例代码
以下为URP中自定义Tonemapping的Shader实现示例:
代码说明:
Shader实现ACES算法,通过曝光参数(_Exposure)控制亮度映射。
Volume脚本提供运行时参数调整,集成到URP后处理堆栈。
TonemappingEffect.shader
Shader "PostProcessing/Tonemapping"
{
Properties {...}
SubShader
{
Pass
{
// ACES近似算法核心
float3 ACESTonemap(float3 color)
{
float a = 2.51, b = 0.03, c = 2.43, d = 0.59, e = 0.14;
return saturate((color*(a*color+b))/(color*(c*color+d)+e));
}
fixed4 frag(v2f i) : SV_Target
{
float4 src = tex2D(_MainTex, i.uv);
float3 tonemapped = ACESTonemap(src.rgb * _Exposure);
return float4(tonemapped, src.a);
}
}
}
}
TonemappingVolume.cs
using UnityEngine.Rendering;
public class TonemappingVolume : VolumeComponent
{
public TonemappingModeParameter mode = new TonemappingModeParameter(TonemappingMode.ACES);
public FloatParameter exposure = new FloatParameter(1.0f);
}
实际用例建议
开放世界游戏:使用ACES模式增强日落时的高光自然过渡。
移动端优化:改用Neutral模式减少计算开销,或简化ACES算法(如拟合矩阵)。
艺术风格化:结合Lookup Texture实现像素风或复古胶片效果。
通过调整参数组合(如Toe Length+Shoulder Angle),可精细控制画面动态范围分布