泛光(Bloom)是一种常用的后期处理特效,游戏中更是随处可见,这里直接上我们的效果图。
Cesium内置的bloom后期处理,是对全屏进行处理,还不能只针对选中的特定对象添加泛光效果,通过修改shader代码也可以实现。不过今天我们不做改进,而是引进three.js的UnrealBloomPass,在Cesium中实现一个新的泛光效果。
从UnrealBloomPass这个名字看,大概是说从Unreal Engine那里学来的吧,另外也是在名称上区别于辉光特效BloomPass,可以说UnrealBloomPass就是增强的辉光特效。感兴趣的可以看看UE4关于泛光的文档页面。UE4关于泛光的文档页面
实现流程
泛光效果的技术并不复杂,大体分为三个步骤:
计算亮度,获得亮度纹理;
高斯模糊,对亮度纹理的根据不同分辨率和高斯核进行模糊处理,得到多个模糊纹理;
合并纹理,将模糊纹理按照不同权重叠加到原始场景。
由于上一篇《Cesium实现更实用的3D描边效果》已经详细介绍了Cesium后期处理技术并给出了基本示例,本文就只对Shader代码进行简单的注解,不贴出JavaScript部分的代码了。
计算亮度
亮度(Luminosity)的概念和计算方法可以参考维基百科。
下面针对Cesium进行修改后的片元着色器(fragmentShader)代码:
计算亮度的核心代码就是这两行:
CZM_SELECTED_FEATURE是由Cesium自动定义的命令,指示当前后期处理节点是否设置selected属性,和czm_selected一起用于判断是否为选中对象。
这一步的效果图如下:
luminosityThreshold和smoothWidth两个参数可以对亮度计算结果进行微调。
高斯模糊
接下来我们需要对亮度纹理进行多次处理,得到不同平滑程度和尺寸的模糊纹理。每次处理的流程如下:
设置高斯核半径KERNEL_RADIUS;
降低目标纹理分辨率(用纹理缩放倍数表示);
对亮度纹理进行纵向、横向两次高斯模糊处理。
高斯模糊的原理网上有很多优秀文章可以学习,感兴趣可以自行搜索,兴许对这部分Shader代码会有更加深刻的理解。
下面这段代码实现一个方向的高斯模糊:
KERNEL_RADIUS是高斯核半径,单位是像素,在创建Cesium.PostProcessStage时在添加。
本文实现的效果总的进行了5次模糊处理,高斯核半径分别为:3, 5, 7, 9, 11;纹理缩放倍数分别为:1,0.5,0.25,0.125,0.0625。
合并纹理
最后我们将五次模糊处理的结果,按不同权重和颜色进行叠加,并预留一些参数供应用时按需进行调整。