【從UnityURP開始探索遊戲渲染】專欄-直達
基本概念與作用
Shadows, Midtones, Highlights 是 Unity URP 後處理系統中用於顏色分級的重要效果,它允許開發者分別控制畫面中的陰影、中間色調和高光部分的顏色調整。這種精細控制的優勢在於:
- 陰影調整:可以單獨改變畫面暗部的色調和亮度,常用於營造特定氛圍或修正陰影顏色.
- 中間色調控制:調整畫面中等亮度區域,這是大多數視覺信息所在的區域.
- 高光處理:專門處理畫面最亮部分,可以增強或減弱高光效果
發展歷史
這一效果源於專業影視調色技術,Unity 在 2018 年左右引入後處理堆棧(Post Processing Stack)時首次包含了類似功能,後來在 URP/HDRP 中進一步優化。相比早期的 Lift, Gamma, Gain 調整方式,Shadows, Midtones, Highlights 提供了更精確的色調範圍定義能力。
實現原理與技術細節
在 URP 中,該效果通過體積框架(Volume Framework)實現,使用屏幕空間計算和色調映射技術來分離和調整不同亮度區。核心算法包括:
- 亮度分離:基於像素亮度值將畫面分為三個區域
- 色調映射:對每個區域應用獨立的顏色變換
- 平滑過渡:確保區域間過渡自然,避免明顯邊界
底層原理
Shadows, Midtones, Highlights 效果基於亮度分離和區域特定顏色變換技術實現。其核心處理流程包括:
-
亮度分析階段:通過計算像素的亮度值(Luminance),將畫面分為三個區域:
- Shadows:亮度低於Shadow Limit閾值的區域
- Highlights:亮度高於Highlight Limit閾值的區域
- Midtones:介於兩者之間的區域
-
色調映射階段:對每個區域應用獨立的顏色變換矩陣,包括:
- 色相/飽和度調整
- 亮度/對比度調整
- 顏色偏移(Offset)
- 混合階段:使用平滑過渡函數(通常為Sigmoid或線性插值)混合三個區域的調整結果,避免明顯的邊界效應
技術實現細節
在URP中,該效果通過RenderPass實現,主要處理步驟包括:
- 屏幕空間處理:在像素着色器中計算每個像素的亮度值
- 區域分類:使用閾值比較確定像素所屬區域
- 顏色變換:根據區域應用不同的顏色校正矩陣
- ACES色調映射:可選地與ACES色調映射管線集成,增強影視級效果
示例實現
以下是一個簡化的Shader代碼示例,展示核心處理邏輯:
代碼説明:
- 亮度計算使用標準RGB轉亮度公式
- 使用smoothstep函數實現區域間的平滑過渡
- 三個區域的顏色調整獨立進行後混合
- 閾值參數(_ShadowLimits/_HighlightLimits)控制區域範圍
-
ShadowsMidtonesHighlights.shader
Shader "Hidden/Universal Render Pipeline/ShadowsMidtonesHighlights" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _Shadows ("Shadows", Color) = (1,1,1,1) _Midtones ("Midtones", Color) = (1,1,1,1) _Highlights ("Highlights", Color) = (1,1,1,1) _ShadowLimits ("Shadow Limits", Vector) = (0.0, 0.3, 0, 0) _HighlightLimits ("Highlight Limits", Vector) = (0.55, 1.0, 0, 0) } SubShader { Pass { HLSLPROGRAM #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); float4 _Shadows; float4 _Midtones; float4 _Highlights; float2 _ShadowLimits; float2 _HighlightLimits; float Luminance(float3 color) { return dot(color, float3(0.2126, 0.7152, 0.0722)); } float4 Frag(Varyings input) : SV_Target { float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv); float lum = Luminance(color.rgb); // 計算各區域權重 float shadowWeight = smoothstep(_ShadowLimits.x, _ShadowLimits.y, lum); float highlightWeight = smoothstep(_HighlightLimits.x, _HighlightLimits.y, lum); float midtoneWeight = 1.0 - shadowWeight - highlightWeight; // 應用區域特定調整 float3 shadowColor = color.rgb * _Shadows.rgb; float3 midtoneColor = color.rgb * _Midtones.rgb; float3 highlightColor = color.rgb * _Highlights.rgb; // 混合結果 color.rgb = shadowColor * shadowWeight + midtoneColor * midtoneWeight + highlightColor * highlightWeight; return color; } ENDHLSL } } }
實際應用原理
在URP管線中,該效果通過Volume框架集成到後處理堆棧中。當相機啓用後處理時,URP會:
- 創建臨時渲染紋理存儲中間結果
- 執行多個RenderPass完成各種後處理效果
- 將Shadows, Midtones, Highlights作為其中一個Pass插入管線
- 最終結果輸出到相機目標紋理
這種設計使得效果可以與其他後處理(如Tonemapping、Bloom等)無縫配合,共同構成完整的顏色分級管線
完整實現流程
以下是在 Unity URP 中實現 Shadows, Midtones, Highlights 效果的完整步驟:
-
確保項目使用URP管線
- 在Graphics Settings中選擇URP Asset
-
創建後處理體積
- 在Hierarchy中右鍵 -> Volume -> Global Volume
-
創建Profile
- 在Global Volume組件的Profile字段點擊New
-
添加效果
- 在Profile中添加Override: Add Override -> Post-processing -> Shadows Midtones Highlights
-
啓用相機後處理
- 選中主相機 -> Rendering -> Post Processing勾選
參數詳解與用例
核心參數
-
Shadows:
- 功能:控制畫面暗部色調和亮度
- 實際用例:將陰影調為冷藍色營造寒冷氛圍
-
參數:
- 色環:選擇陰影色調
- 滑塊:調整陰影亮度(左暗右亮)
-
Midtones:
- 功能:調整畫面中間亮度區域
- 實際用例:增強中間色調飽和度使畫面更生動
-
參數:
- 色環:選擇中間色調
- 滑塊:調整中間調亮度
-
Highlights:
- 功能:控制畫面最亮部分
- 實際用例:將高光調為暖黃色模擬陽光效果
-
參數:
- 色環:選擇高光色調
- 滑塊:調整高光亮度
高級參數
-
Shadow Limits:
- 功能:定義陰影範圍的開始和結束點
- 實際用例:精細控制哪些像素被視為陰影
-
Highlight Limits:
- 功能:定義高光範圍的開始和結束點
- 實際用例:避免過亮區域被錯誤分類
性能優化建議
-
該效果屬於低開銷後處理,但仍建議:
- 避免過度使用複雜調整
- 在移動平台簡化參數調整
- 使用局部體積(Local Volume)而非全局應用
-
與類似效果對比:
- Lift Gamma Gain:更簡單但控制精度較低
- Color Grading:更全面但開銷略高
實際應用示例
恐怖遊戲場景設置
- 將Shadows調為深綠色增強詭異感
- Midtones略微降低飽和度營造壓抑感
- Highlights保持中性避免分散注意力
陽光明媚的户外場景
- Shadows使用淡藍色模擬天空反射
- Midtones增強飽和度使色彩鮮豔
- Highlights使用暖黃色強化陽光效果
通過這種分級控制,開發者可以精確塑造遊戲視覺風格,而無需修改原始材質或光照設置
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)