屏幕后处理效果系列之常见后处理效果篇
1.1 前言
在系列第一篇中,我们学习了用于图像模糊的相关算法,在探究这些算法效率高低的同时,深入理解了这些算法的核心思想,这些思想将会被应用于许多后处理效果中。接下来,我们将学习一些常见的屏幕后处理效果的实现方式。
1.2 基础知识
Bloom(Glow)特效是游戏中应用最普遍的一种屏幕后处理特效。表现为高光物体带有泛光效果,使画面的光影表现更加优秀。Bloom通常会搭配HDR和ToneMapping来得到更好的效果。
首先我们需要简单了解一下什么是HDR和ToneMapping。电子设备可以显示的亮度范围有限,对于RGB三个通道,每个通道8bit,由此以来可以显示(2^8)^3=16777216种颜色,这个范围被称为低动态范围(Low-Dynamic Range)。这个范围是一个经验亮度范围,在这个范围内不会对人眼产生伤害,而超出这个范围的颜色空间被称为高动态范围(High-Dynamic Range)。现实生活中的亮度是没有范围限制的,想要表达更多的亮度,RGB每个通道需要扩充到12位乃至更多。运算完成后,在进行输出时需要通过ToneMapping将HDR空间中的颜色映射到LDR空间中,再在显示器上进行显示。
现实生活中,Bloom产生的原因是人眼晶状体的散射,例如在强光照射的时候,会有看不清的情况发生。于是使用Bloom来表现高光溢出的效果从而模拟这种现象。
关于HDR 、 LDR、ToneMapping的更多知识点可以学习《漫谈HDR和色彩管理》。
通用的Bloom特效的制作方式是将图像高亮的部分通过卷积进行模糊之后再叠加到原图像上。在《屏幕后处理效果系列之图像模糊算法篇》课程中,我们介绍了各种图像模糊的算法,选择使用效率最高的Dual Blur的方式进行模糊处理。
1.3 Unity实现
首先设定阈值,采样图片,对于图片中超过阈值的像素被判定为高亮部分。高亮部分,保留颜色,其余部分归0,存储在一张RT中。
BloomMaterial.SetFloat("_Threhold", threshold); BloomMaterial.SetFloat("_Intensity", intensity); RenderTexture HighLighrRT=RenderTexture.GetTemporary(src.descriptor); Graphics.Blit(src, HighLighrRT, BloomMaterial, 0);
Boom.shader: Pass { CGPROGRAM #pragma vertex vert_img #pragma fragment frag fixed4 frag(v2f_img input) : SV_Target { float4 color = tex2D(_MainTex, input.uv); return max(color - _Threhold, 0) * _Intensity; } ENDCG }
接着,将得到的高亮部分进行模糊处理后叠加在原图上:
Pass { CGPROGRAM #pragma vertex vert_img #pragma fragment frag sampler2D _CompositeTex; float4 _CompositeColor; fixed4 frag(v2f_img input) : SV_Target { float4 mainColor = tex2D(_MainTex,input.uv); float4 compositeColor = tex2D(_CompositeTex, input.uv); return saturate(mainColor + compositeColor); } ENDCG }
得到效果如图:
原图如下:
类似地,模仿实现“光剑”效果:
1.4 小结
Bloom效果可以说是游戏中使用最为普遍的屏幕后处理特效了,实现也较为简单。从此我们可以学习到通过模糊处理产生可以使颜色自然平滑地晕开,通过颜色叠加可以使亮度提升。
影响Bloom效果性能最大的因素是进行模糊处理的开销。参考《屏幕后处理效果系列之图像模糊算法篇》的内容,建议选择Dual Blur算法进行处理。
完整课程可戳此查看《屏幕后处理效果系列之常见后处理效果篇》。