【從UnityURP開始探索遊戲渲染】專欄-直達
色調映射(Tonemapping)是Unity URP後處理中的關鍵技術,用於將高動態範圍(HDR)圖像適配到標準動態範圍(SDR)顯示設備,解決亮度範圍超出顯示器能力導致的細節丟失問題。以下是綜合解析:
作用
核心功能
- 動態範圍壓縮:將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),可精細控制畫面動態範圍分佈
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)