【从UnityURP开始探索游戏渲染】专栏-直达
泛光效果概述与发展历史
泛光(Bloom)是一种后处理效果,用于模拟真实世界中明亮光源或高反射表面产生的光晕现象。在Unity中,泛光效果经历了以下发展历程:
内置渲染管线时期:
- 早期Unity版本中,泛光作为标准图像效果(Image Effects)的一部分,通过屏幕空间处理实现。
LWRP时期:
- Unity推出轻量级渲染管线(Lightweight Render Pipeline)后,泛光效果被重新设计以适应移动*台,性能得到优化。
URP时期:
- 2019.3版本后,LWRP更名为URP(Universal Render Pipeline),泛光效果成为URP后处理堆栈的核心组件之一,支持更广泛的*台和更高质量的渲染。
泛光实现原理
泛光效果的技术实现主要分为以下几个步骤:
亮度提取→模糊处理→最终合成→(色调映射 Tonemapping)
亮度提取
- 首先从渲染图像中提取出高于特定亮度阈值的区域。这通常通过阈值比较和高通滤波实现。
模糊处理
- 对提取的亮区进行多次降采样和模糊处理(通常使用高斯模糊或Kawase模糊),创建光晕扩散效果。
合成阶段
- 将模糊后的亮区与原图像按特定强度混合,产生最终的泛光效果。
色调映射
- 在HDR渲染管线中,泛光通常与色调映射(Tonemapping)协同工作,确保在高动态范围下效果自然。
URP中的泛光实现优化了传统方法,采用更高效的模糊算法和GPU加速处理,使其在移动设备上也能良好运行。
URP中泛光的具体实现
URP通过可编程渲染管线(SRP)架构实现泛光效果,主要特点包括:
- 单Pass前向渲染:URP使用单Pass处理所有光源,相比内置管线的多Pass更高效。
- SRP Batcher支持:通过批处理优化减少Draw Call,提高泛光等后处理效果的渲染效率。
- 模块化设计:泛光作为后处理堆栈中的一个独立模块,可以灵活启用或禁用。
- 跨*台兼容:URP泛光针对不同硬件*台进行了优化,确保在各种设备上都能获得良好效果。
亮度提取 URP具体实现
亮度提取是泛光效果的第一步,目的是从渲染图像中分离出需要产生光晕的高亮区域。URP采用以下技术实现:
-
亮度计算:通过公式
0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b
计算像素亮度,其中绿色通道权重最高,符合人眼对绿色更敏感的特性。 -
阈值处理:使用
_BloomThreshold
参数控制哪些像素参与泛光效果,只有亮度超过此阈值的像素才会被保。 -
软过渡处理:为避免硬边缘,URP采用软过渡公式:
hlsl half softness = clamp(brightness - _BloomThreshold + ThresholdKnee, 0.0, 2.0 * ThresholdKnee); softness = (softness * softness) / (4.0 * ThresholdKnee + 1e-4); half multiplier = max(brightness - _BloomThreshold, softness) / max(brightness, 1e-4); color *= multiplier;
- 这种处理方式使得亮度在阈值附*有*滑过渡,避免出现明显分界线
模糊处理 URP具体实现
模糊处理是泛光效果的核心,URP采用优化的多级高斯模糊实现:
-
降采样链:首先创建一系列降采样纹理,每级分辨率减半,形成图像金字塔。例如从全分辨率开始,依次生成1/2、1/4、1/8等分辨率的纹理。
-
双Pass模糊:对每级纹理执行水*和垂直两个方向的模糊处理:
- 水*模糊Pass:采样当前像素左右相邻像素,按高斯权重混合
- 垂直模糊Pass:采样当前像素上下相邻像素,按高斯权重混合这种分离式模糊大幅减少了采样次数,从O(n²)降到O(2n)。
-
模糊权重:URP使用优化的5-tap高斯核,权重分配如下:
hlsl color += 0.4026 * tex2D(_MainTex, i.uv);// 中心像素 color += 0.2442 * tex2D(_MainTex, i.uv01.xy);// 相邻像素 color += 0.2442 * tex2D(_MainTex, i.uv01.zw);// 相邻像素 color += 0.0545 * tex2D(_MainTex, i.uv23.xy);// 远距离像素 color += 0.0545 * tex2D(_MainTex, i.uv23.zw);// 远距离像素
- 这种权重分配在保证质量的同时最大化性能
合成阶段 URP具体实现
模糊后的亮区需要与原图像混合产生最终效果:
-
上采样混合:从最低分辨率纹理开始,逐级上采样并与上一级结果混合,形成*滑的光晕渐变。
-
最终合成:使用公式:
hlsl fixed4 resColor = mainColor + _BloomIntensity * blurColor * _BloomColor;
其中
_BloomIntensity
控制泛光强度,_BloomColor
可为泛光添加色调。 -
散射控制:通过
_Scatter
参数调节光晕的扩散范围,值越大光晕范围越广
如何与色调映射协同工作
在HDR渲染中,泛光效果需要与色调映射(Tonemapping)协同工作才能产生最佳效果:
- HDR处理流程:URP首先在HDR空间完成泛光计算,最后应用色调映射将结果转换到显示器的LDR范围。
- ACES色调映射:URP默认使用ACES(学院色彩编码系统)色调映射,它能:
- 保留高光细节,避免过曝
- 提供电影级的色彩响应
- 与泛光效果自然融合。
- 中性模式:对于需要精确色彩控制的项目,可使用中性色调映射模式,它对色相和饱和度影响最小,适合作为复杂色彩处理的起点。
- 动态范围压缩:色调映射将HDR场景的宽动态范围压缩到显示设备能表现的范围内,同时保持泛光效果的自然过渡
Unity URP中使用泛光的完整示例
以下是在Unity URP项目中设置和使用泛光效果的完整步骤:
确保项目使用URP:
- 通过Package Manager安装Universal RP包
- 创建URP Asset并分配给Graphics和Quality设置
启用后处理效果:
- 在URP Asset中勾选"Post-processing"选项
- 为摄像机添加"Volume"组件
配置泛光效果:
- 创建新的Volume Profile或在现有Profile中添加"Bloom"效果
- 调整泛光参数(阈值、强度、散射等)
参数详解:
-
Threshold:控制哪些像素会参与泛光计算(亮度阈值)
-
Intensity:泛光效果的总体强度
-
Scatter:控制光晕的扩散程度
-
Tint:为泛光效果添加颜色色调
-
High Quality Filtering:启用更高质量的过滤模式
-
BloomExample.cs
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal;public class BloomController : MonoBehaviour {private Volume volume;private Bloom bloom;void Start(){// 获取Volume组件volume = GetComponent<Volume>();// 尝试获取Bloom效果if(volume.profile.TryGet(out bloom)){// 初始化泛光参数bloom.threshold.Override(1.0f);bloom.intensity.Override(1.5f);bloom.scatter.Override(0.7f);}}// 动态调整泛光强度public void SetBloomIntensity(float intensity){if(bloom != null){bloom.intensity.Override(intensity);}} }
性能优化建议
移动*台优化:
- 降低泛光迭代次数
- 使用较低的渲染分辨率
- 限制泛光影响范围
质量与性能*衡:
- 根据目标*台调整泛光质量设置
- 在低端设备上考虑禁用或简化泛光效果
结合其他效果:
- 泛光常与色调映射、色彩校正等效果配合使用
- 注意效果叠加的性能消耗
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)