【从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开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,)
浙公网安备 33010602011771号