为实现三维模型的更炫、更酷、更美观,Cesium在1.46的版本中新增了场景的后期处理(Post Processing)功能,包括模型描边、黑白图、明亮度调整、夜市效果、环境光遮蔽,也包括雷达扫描、原型扩散等一些特效。今天我们来学习一下场景后期处理的基础知识和实现流程。

场景后期处理流程

场景的后期处理这个词比较陌生,但说起照片的PS大家都很熟悉,这两个过程非常类似。日常生活中我们拍摄完照片之后,发现太亮或太暗,又或者是皮肤不够白、脸上痘痘明显,我们可以调整亮度、修复一下嫩白的脸蛋,经过几波操作之后,得到了一张我们非常满意的照片。

我们可以把照片的修复过程简单理解成场景的后期处理过程,修图的过程就比喻成对三维场景中初始渲染的效果进行再处理,比如添加物体描边、明暗度调整、夜市效果等,最终把综合之后的效果在场景中渲染出来。Cesium中的场景后期处理的大概流程如下图所示:

下面结合Cesium本身的PostProcess类,详细的说明一下处理流程:
第一步:通过PostProcessStageLibrary创建一个或者多个后处理效果对象,得到多个PostProcessStage或PostProcessStageComposite;
第二步:将他们加入到PostProcessStageCollection对象中,并设置PostProcessStage或PostProcessStageComposite一些参数,如uniforms;
第三步:PostProcessStageCollection对象就会按照加入的顺序进行屏幕后期处理,在所有的效果都处理完毕后,最后绘制到屏幕上。
当然也可以省略第一步,直接利用PostProcessStageCollection实例化对象中已有的处理效果去实现,如ambientOcclusion、bloom、fxaa。

场景后期处理相关类

上述提到了PostProcess类,基本上涉及到4个类文件,具体每个类的作用又是什么呢?我们来说明一下。
(1)PostProcessStage
对应于某个具体的后期处理效果,它的输入为场景渲染图或者上一个后期处理的结果图,输出结果是一张处理后的图片。

// Simple stage to change the colorvar
fs ='uniform sampler2D colorTexture;\n' +'varying vec2 v_textureCoordinates;\n' +'uniform float scale;\n' +'uniform vec3 offset;\n' +'void main() {\n' +'    vec4 color = texture2D(colorTexture, v_textureCoordinates);\n' +'    gl_FragColor = vec4(color.rgb * scale + offset, 1.0);\n' +'}\n';
scene.postProcessStages.add(new Cesium.PostProcessStage({fragmentShader : fs,uniforms : {scale : 1.1,offset : function() {return new Cesium.Cartesian3(0.1, 0.2, 0.3);}}}));

fragmentShader:片源着色器代码字符串,它是GLSL代码语言,需要成对配置顶点着色器和片元着色器。
uniforms:片源着色器代码字符串中需要在前端传入的变量。
(2)PostProcessStageComposite
一个集合对象,按顺序存储了不同的场景处理对象,存储类型为PostProcessStage或者PostProcessStageComposite的元素,并存储在stages属性中。

// Example 1: separable blur filter
// The input to blurXDirection is the texture rendered to by the scene or the output of the previous stage.
// The input to blurYDirection is the texture rendered to by blurXDirection.
scene.postProcessStages.add(new Cesium.PostProcessStageComposite({stages : [blurXDirection, blurYDirection]}));

(3)PostProcessStageLibrary
负责创建具体的后期处理效果,提供了一些创建常用场景特效的方法,包括createBlackAndWhiteStage-黑色和白色渐变渲染、createBlurStage-高斯模、createBrightnessStage-纹理饱和、createDepthOfFieldStage-景深效果等,创建返回的结果是PostProcessStageComposite或者PostProcessStage类型。相对来说比较简单,直接调用即可。

var stages = viewer.scene.postProcessStages;var silhouette = stages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage());

(4)PostProcessStageCollection
是一个集合类型的类,负责管理和维护放到集合中的PostProcessStage或PostProcessStageComposite类型对象,实例化对象可通过viewer.scene.postProcessStages直接获取,提供了一些常用的方法,如add、contains、destroy、remove等。
但需要注意的是,该集合中也设定了三个ambientOcclusion、bloom、fxaa效果,如果此类中的环境光遮挡-ambientOcclusion或发光效果-bloom被启用,它们将在所有其他阶段之前执行,优先级最高;如果近似抗锯齿-fxaa被启用,它将在所有其他阶段之后执行,优先级最低。

场景后期处理效果

Cesium为我们提供了一些默认的示例效果,但基本上可分为如下三类:
(1)利用PostProcessStageCollection集合类提供的三个效果
包括ambientOcclusion环境光遮挡、bloom发光效果、fxaa近似抗锯齿,我们挑选前两个为例进行说明。

  • ambientOcclusion环境光遮挡
function updatePostProcess() {const ambientOcclusion =viewer.scene.postProcessStages.ambientOcclusion;ambientOcclusion.enabled =Boolean(viewModel.show) || Boolean(viewModel.ambientOcclusionOnly);ambientOcclusion.uniforms.ambientOcclusionOnly = Boolean(viewModel.ambientOcclusionOnly);ambientOcclusion.uniforms.intensity = Number(viewModel.intensity);ambientOcclusion.uniforms.bias = Number(viewModel.bias);ambientOcclusion.uniforms.lengthCap = Number(viewModel.lengthCap);ambientOcclusion.uniforms.stepSize = Number(viewModel.stepSize);ambientOcclusion.uniforms.blurStepSize = Number(viewModel.blurStepSize);
}

没有开启AO效果如上图一,开启AO效果如上图二,单纯的AO图如上图三

  • bloom发光效果
function updatePostProcess() {const bloom = viewer.scene.postProcessStages.bloom;bloom.enabled = Boolean(viewModel.show);bloom.uniforms.glowOnly = Boolean(viewModel.glowOnly);bloom.uniforms.contrast = Number(viewModel.contrast);bloom.uniforms.brightness = Number(viewModel.brightness);bloom.uniforms.delta = Number(viewModel.delta);bloom.uniforms.sigma = Number(viewModel.sigma);bloom.uniforms.stepSize = Number(viewModel.stepSize);
}

(2)直接调用PostProcessStageLibrary中提供的方法去渲染场景特效
Cesium在场景处理库中默认为我们提供了如下8个效果,其实也是非常简单的,直接调用即可。

下面是一个切换动画小人效果的简单示例:

const stages = viewer.scene.postProcessStages;
const silhouette = stages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage()
);
const blackAndWhite = stages.add(Cesium.PostProcessStageLibrary.createBlackAndWhiteStage()
);
const brightness = stages.add(Cesium.PostProcessStageLibrary.createBrightnessStage()
);
const nightVision = stages.add(Cesium.PostProcessStageLibrary.createNightVisionStage()
);function updatePostProcess() {silhouette.enabled = Boolean(viewModel.silhouette);silhouette.uniforms.color = Cesium.Color.YELLOW;blackAndWhite.enabled = Boolean(viewModel.blackAndWhiteShow);blackAndWhite.uniforms.gradations = Number(viewModel.blackAndWhiteGradations);brightness.enabled = Boolean(viewModel.brightnessShow);brightness.uniforms.brightness = Number(viewModel.brightnessValue);nightVision.enabled = Boolean(viewModel.nightVisionShow);
}

(3)编写自定义Shader实现场景特效
要想实现自定义Shader,不仅需要开发者了解顶点着色器和片元着色器,openGL,还需要会编写GLSL(GL Shading Language)语言,通过自定义Shader可以表达更多的场景特效。关于GLSL编程语法,这里就不多赘述了,感兴趣的可以查看其官网。下面是一个简单的给动画小人打马赛克的示例:

const fragmentShaderSource = `uniform sampler2D colorTexture; varying vec2 v_textureCoordinates; const int KERNEL_WIDTH = 16; void main(void) { vec2 step = czm_pixelRatio / czm_viewport.zw; vec2 integralPos = v_textureCoordinates - mod(v_textureCoordinates, 8.0 * step); vec3 averageValue = vec3(0.0); for (int i = 0; i < KERNEL_WIDTH; i++) { for (int j = 0; j < KERNEL_WIDTH; j++) { averageValue += texture2D(colorTexture, integralPos + step * vec2(i, j)).rgb; } } averageValue /= float(KERNEL_WIDTH * KERNEL_WIDTH); gl_FragColor = vec4(averageValue, 1.0); }`;
viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({fragmentShader: fragmentShaderSource,})

Cesium开发高级篇 | 05场景后期处理相关推荐

  1. Cesium开发高级篇 | 01空间数据可视化之Primitive

    在基础篇中我们讲过空间数据可视化之Entity实体类,今天我们介绍另外一个比较接近渲染引擎底层的类Primitive,虽然两者都可用于绘制同样的几何图形,但考虑到性能问题,我们更推荐您使用Primit ...

  2. Cesium开发高级篇 | 04粒子系统

    在三维GIS系统中,我们经常会看到一些常见的特效,比如雨雪雾天气.烟火.爆炸.喷泉等,这些都可以通过粒子系统实现,今天我就来带领大家学习一下Cesium中的粒子系统. 1.什么是粒子系统 粒子系统是一 ...

  3. Cesium开发工具篇 | 07回顾总结

    到目前为止,Cesium开发课程的篇幅已经学完四分之三了,大家如果有什么问题可以私信我或者扫描以下二维码进群沟通,若群二维码失效,可扫描最下方的公众号二维码,加我为好友并备注加群.有时会比较忙来不及回 ...

  4. Nginx 模块开发高级篇

    Nginx 模块开发高级篇 变量 综述 在Nginx中同一个请求需要在模块之间数据的传递或者说在配置文件里面使用模块动态的数据一般来说都是使用变量,比如在HTTP模块中导出了host/remote_a ...

  5. Cesium开发基础篇 | 04空间数据可视化之Entity

    前面介绍了Cesium如何加载影像数据.地形数据.以及矢量数据,但是作为一个完整的三维系统,仅仅包括这些数据还是远远不够的.当然,还需要一些其他数据,比如空间可视化数据.三维数据数据等,今天我们先从空 ...

  6. [洪流学堂]Hololens开发高级篇5:空间映射(Spatial mapping)

    本教程基于Unity2017.2及Visual Studio 2017 本教程编写时间:2017年12月16日 本文内容提要 空间映射让holograms了解周围环境,将真实世界和虚拟世界更好地结合在 ...

  7. [洪流学堂]Hololens开发高级篇3:语音(Voice)

    本教程基于Unity2017.2及Visual Studio 2017 本教程编写时间:2017年12月8日 本文内容提要 设计语音命令并针对Hololens语音引擎优化 让用户知道可以用什么语音命令 ...

  8. [洪流学堂]Hololens开发高级篇2:手势(Gesture)

    本教程基于Unity2017.2及Visual Studio 2017 本教程编写时间:2017年12月7日 本文内容提要 当跟踪到用户的手时提供反馈 使用导航手势旋转hologram 当用户的手要离 ...

  9. Cesium开发基础篇 | 02加载地形数据

    Cesium中的地形图层类 前面我们主要学习了cesium内置接口如何操作影像数据,但是在一些应用场景中我们需要操作地形数据,例如模拟逼真的三维场景.与高程相关的一些空间分析和计算等.Cesium提供 ...

最新文章

  1. 设置Fetch快捷键Ctrl+Alt+Shift+1
  2. ASP.NET 2.0实现自带TreeView的客户端连带选择
  3. 4星|《高手》:会讲故事的科学家的经管社科书读书笔记
  4. 目标检测基本概念理解之IoU(交并比)以及Python代码实现
  5. 2014年职称计算机word2003,2014年职称计算机考试Word2003模拟题及答案5
  6. VisualVM安装使用详解
  7. WPF 如何在代码中使用自定义的鼠标资源
  8. java爪哇咖啡语言_“爪哇咖啡JAVACAFE及图”商标注册案例分析
  9. 10-5-展示后台数据
  10. java零碎要点001--深入理解JVM_Java的堆内存_栈内存_以及运行时数据区的作用
  11. TensorFlow新功能「AutoGraph」:将Python转换为计算图
  12. cdq分治(bzoj 1176: [Balkan2007]Mokia bzoj 2683: 简单题)
  13. 将机器人的urdf文件转为Mujoco模型
  14. adb双击POWER键指令
  15. podman 开机自启
  16. 闲鱼卖货,月入1.5w的小众类目分享。
  17. 4.5/4.6 磁盘格式化 4.7/4.8 磁盘挂载 4.9 手动增加swap空间
  18. 哪个工具可以保护计算机免受ESD的影响,可以避免ESD影响的实用解决方案
  19. 智慧家庭产业链及典型企业
  20. python打印国际象棋棋盘_python输出国际象棋棋盘的实例分享

热门文章

  1. 弹性云服务器使用须知
  2. 计算机视觉(二)-matlab之理想低通滤波器,布特沃斯低通、高斯低通,理想高通、布特沃斯高通、高斯高通滤波器
  3. 第7课 微信小程序实现图片搜索器案例:
  4. idea java新建项目详细步骤
  5. 01. Java8-Lambada 表达式
  6. Python Scipy 显著性检验
  7. jquery 入门(jquery是什么/与JavaScript的联系与区别/jquery版本/引包/入口函数)
  8. 全栈AI火力全开,“云智一体”为开发者凿开产业智能通衢
  9. AFNetworking理解:
  10. 【NOIP2016提高A组模拟9.24】天使的分裂