最近项目中要实现一个根据天气状况自动添加雨雪天气场景的功能,先看官网demo,发现已经有示例Particle System Weaher

cesium中显示雪的效果时雪的颗粒度比较大,而且切换视角后就有些问题了

网上查过,有其他解决方案,果断放弃这种实现方法,具体如下:

其他解决方案网址:网址

思路:利用postProcessStages接口实现全屏效果,利用postProcessStages在片元着色器中拿到v_textureCoordinates,然后自己添加雨雪效果,相当于在镜头前添加粒子效果,与场景位置视角无关,解决了上述的问题。

实现方法:

方法一:

和博客介绍一致是将shader代码放在Source/Shaders/PostProcessStages文件夹下,修改ceisum源码中的PostProcessStageLibray类,将雨雪效果内嵌到cesium源码中,这个需要自己重新编译ceisum,修改源码,

方法二:直接利用PostProcessStage对象实现动态创建,不需要修改源码

如API所述,可修改fragmentShader属性,修改着色器即可,示例和代码如下

snow.html

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="utf-8" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="initial-scale=1, maximum-scale=1"><title>Tools-29postProcess-Snow</title><script src="1-2ImageryProvider-WebExtend.js"></script>  --><script src="https://cesiumjs.org/releases/1.50/Build/Cesium/Cesium.js"></script><link href="https://cesiumjs.org/releases/1.50/Build/Cesium/Widgets/widgets.css" rel="stylesheet"><script src="./js/1-2ImageryProvider-WebExtend.js"></script> <style>html, body, #cesiumContainer {width: 100%;height: 100%;margin: 0;padding: 0;overflow: hidden;}</style>
</head>
<body><div id="cesiumContainer" class="fullSize"></div><div id="creditContainer" style="display: none;"></div><script>var GoogleMap = ImageryProviderWebExtendTool.createGoogleMapsByUrl(Cesium, { url: "http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}" });var viewer = new Cesium.Viewer('cesiumContainer', {imageryProvider: GoogleMap,contextOptions: {webgl: {alpha: true,depth: false,stencil: true,antialias: true,premultipliedAlpha: true,preserveDrawingBuffer: true,  failIfMajorPerformanceCaveat: true},allowTextureFilterAnisotropic: true},creditContainer: "creditContainer",selectionIndicator: false,animation: false,   baseLayerPicker: false,  geocoder: false,  timeline: false,  sceneModePicker: true,  navigationHelpButton: false,  infoBox: false,   fullscreenButton: true});var lat = 42.006;var lon = 128.055;//取消双击事件viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);//设置homebutton的位置Cesium.Camera.DEFAULT_VIEW_RECTANGLE =Cesium.Rectangle.fromDegrees(lon - 1, lat - 1, lon + 1, lat + 1);//Rectangle(west, south, east, north)//设置初始位置viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(lon, lat, 300000)});//定义下雪场景 着色器function FS_Snow() {return "uniform sampler2D colorTexture;\n\varying vec2 v_textureCoordinates;\n\
\n\float snow(vec2 uv,float scale)\n\{\n\float time = czm_frameNumber / 60.0;\n\float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n\uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n\uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n\p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n\k=smoothstep(0.,k,sin(f.x+f.y)*0.01);\n\return k*w;\n\}\n\
\n\void main(void){\n\vec2 resolution = czm_viewport.zw;\n\vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\vec3 finalColor=vec3(0);\n\float c = 0.0;\n\c+=snow(uv,30.)*.0;\n\c+=snow(uv,20.)*.0;\n\c+=snow(uv,15.)*.0;\n\c+=snow(uv,10.);\n\c+=snow(uv,8.);\n\c+=snow(uv,6.);\n\c+=snow(uv,5.);\n\finalColor=(vec3(c)); \n\gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5); \n\
\n\}\n\
";}var collection = viewer.scene.postProcessStages;var fs_snow = FS_Snow();var snow = new Cesium.PostProcessStage({name: 'czm_snow',fragmentShader: fs_snow});collection.add(snow);viewer.scene.skyAtmosphere.hueShift = -0.8;viewer.scene.skyAtmosphere.saturationShift = -0.7;viewer.scene.skyAtmosphere.brightnessShift = -0.33;viewer.scene.fog.density = 0.001;viewer.scene.fog.minimumBrightness = 0.8;</script>
</body>
</html>

其中1-2ImageryProvider-WebExtend.js如下:

var ImageryProviderWebExtendTool = (function () {function _() { }_.createGoogleMapsByUrl = function (Cesium, options) {options = Cesium.defaultValue(options, {});var templateUrl = Cesium.defaultValue(options.url, 'http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}');var trailingSlashRegex = /\/$/;var defaultCredit = new Cesium.Credit('Google Maps');var tilingScheme = new Cesium.WebMercatorTilingScheme({ ellipsoid: options.ellipsoid });var tileWidth = 256;var tileHeight = 256;var minimumLevel = Cesium.defaultValue(options.minimumLevel, 0);var maximumLevel = Cesium.defaultValue(options.minimumLevel, 17);var rectangle = Cesium.defaultValue(options.rectangle, tilingScheme.rectangle);// Check the number of tiles at the minimum level.  If it's more than four,// throw an exception, because starting at the higher minimum// level will cause too many tiles to be downloaded and rendered.var swTile = tilingScheme.positionToTileXY(Cesium.Rectangle.southwest(rectangle), minimumLevel);var neTile = tilingScheme.positionToTileXY(Cesium.Rectangle.northeast(rectangle), minimumLevel);var tileCount = (Math.abs(neTile.x - swTile.x) + 1) * (Math.abs(neTile.y - swTile.y) + 1);//>>includeStart('debug', pragmas.debug);if (tileCount > 4) {throw new Cesium.DeveloperError('The rectangle and minimumLevel indicate that there are ' + tileCount + ' tiles at the minimum level. Imagery providers with more than four tiles at the minimum level are not supported.');}//>>includeEnd('debug');var credit = Cesium.defaultValue(options.credit, defaultCredit);if (typeof credit === 'string') {credit = new Cesium.Credit(credit);}return new Cesium.UrlTemplateImageryProvider({url: templateUrl,proxy: options.proxy,credit: credit,tilingScheme: tilingScheme,tileWidth: tileWidth,tileHeight: tileHeight,minimumLevel: minimumLevel,maximumLevel: maximumLevel,rectangle: rectangle});}return _;}
)();

下雨的例子:

<!DOCTYPE html>
<html><head lang="en"><meta charset="utf-8" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="initial-scale=1, maximum-scale=1"><title>Tools-29postProcess-Snow</title><!-- <script src="../../Cesium1.48/Cesium/Cesium.js"></script>--><script src="https://cesiumjs.org/releases/1.50/Build/Cesium/Cesium.js"></script><link href="https://cesiumjs.org/releases/1.50/Build/Cesium/Widgets/widgets.css" rel="stylesheet"><script src="./js/1-2ImageryProvider-WebExtend.js"></script><style>/*  @import url(../../Cesium1.48/Cesium/Widgets/widgets.css); */html,body,#cesiumContainer {width: 100%;height: 100%;margin: 0;padding: 0;overflow: hidden;}</style></head><body><div id="cesiumContainer" class="fullSize"></div><div id="creditContainer" style="display: none;"></div><script>var GoogleMap = ImageryProviderWebExtendTool.createGoogleMapsByUrl(Cesium, {url: "http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}"});var viewer = new Cesium.Viewer('cesiumContainer', {imageryProvider: GoogleMap,contextOptions: {webgl: {alpha: true,depth: false,stencil: true,antialias: true,premultipliedAlpha: true,preserveDrawingBuffer: true,failIfMajorPerformanceCaveat: true},allowTextureFilterAnisotropic: true},creditContainer: "creditContainer",selectionIndicator: false,animation: false,baseLayerPicker: false,geocoder: false,timeline: false,sceneModePicker: true,navigationHelpButton: false,infoBox: false,fullscreenButton: true});var lat = 42.006;var lon = 128.055;//取消双击事件viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);//设置homebutton的位置Cesium.Camera.DEFAULT_VIEW_RECTANGLE =Cesium.Rectangle.fromDegrees(lon - 1, lat - 1, lon + 1, lat + 1); //Rectangle(west, south, east, north)//设置初始位置viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(lon, lat, 300000)});//定义下雨场景 着色器function FS_Rain() {return "uniform sampler2D colorTexture;\n\varying vec2 v_textureCoordinates;\n\\n\float hash(float x){\n\return fract(sin(x*133.3)*13.13);\n\}\n\\n\void main(void){\n\\n\float time = czm_frameNumber / 60.0;\n\vec2 resolution = czm_viewport.zw;\n\\n\vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\vec3 c=vec3(.6,.7,.8);\n\\n\float a=-.4;\n\float si=sin(a),co=cos(a);\n\uv*=mat2(co,-si,si,co);\n\uv*=length(uv+vec2(0,4.9))*.3+1.;\n\\n\float v=1.-sin(hash(floor(uv.x*100.))*2.);\n\float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;\n\c*=v*b; \n\\n\gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5);  \n\}\n\
";}var collection = viewer.scene.postProcessStages;var fs_rain = FS_Rain();var snow = new Cesium.PostProcessStage({name: 'czm_rain',fragmentShader: fs_rain});collection.add(snow);viewer.scene.skyAtmosphere.hueShift = -0.8;viewer.scene.skyAtmosphere.saturationShift = -0.7;viewer.scene.skyAtmosphere.brightnessShift = -0.33;viewer.scene.fog.density = 0.001;viewer.scene.fog.minimumBrightness = 0.8;</script></body>
</html>

整合在一起的例子如下:

部分代码:

移除雨雪方法:

function removeStage() {
lastStage && viewer.scene.postProcessStages.remove(lastStage), lastStage = null
}

添加雨方法

function showRain() {removeStage();var e = new Cesium.PostProcessStage({name: "czm_rain",fragmentShader: getRainShader()});viewer.scene.postProcessStages.add(e), lastStage = e
}function getRainShader() {
return "uniform sampler2D colorTexture;\n    varying vec2 v_textureCoordinates;\n                    \n     float hash(float x){\n    return fract(sin(x*133.3)*13.13);\n    }\n                 \n     void main(void){\n    \n float time = czm_frameNumber / 120.0;\n                    vec2 resolution = czm_viewport.zw;\n                    \n                    vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n                    vec3 c=vec3(.6,.7,.8);\n                    \n                    float a=-.4;\n                    float si=sin(a),co=cos(a);\n                    uv*=mat2(co,-si,si,co);\n                    uv*=length(uv+vec2(0,4.9))*.3+1.;\n                    \n                    float v=1.-sin(hash(floor(uv.x*100.))*2.);\n                    float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;\n                    c*=v*b; \n                    \n                    gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5);  \n                    }\n                    "
}

添加雪方法

function showSnow() {removeStage();var e = new Cesium.PostProcessStage({name: "czm_snow",fragmentShader: getSnowShader()});viewer.scene.postProcessStages.add(e), lastStage = e
}
function getSnowShader() {return "uniform sampler2D colorTexture;\n  varying vec2 v_textureCoordinates;\n                    \n                     float snow(vec2 uv,float scale)\n  {\n                           float time = czm_frameNumber / 60.0;\n                          float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n                            uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n                            uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n                            p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n                            k=smoothstep(0.,k,sin(f.x+f.y)*0.01);\n                       return k*w;\n                        }\n     \n
void main(void){\n   vec2 resolution = czm_viewport.zw;\n                 vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n                            vec3 finalColor=vec3(0);\n                         float c = 0.0;\n   c+=snow(uv,30.)*.0;\n                            c+=snow(uv,20.)*.0;\n c+=snow(uv,15.)*.0;\n  c+=snow(uv,10.);\n                            c+=snow(uv,8.);\n   c+=snow(uv,6.);\n c+=snow(uv,5.);\n                            finalColor=(vec3(c)); \n                          gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5); \n                    \n                        }\n                    "
}

注:自cesium1.46版本起才有PostProcessStage接口,之前的版本没有,如果想使用最好将cesium版本升级

关注

如果有问题,请在下方评论

想获得更多的学习知识请关注微信公众号:西北码农或扫下方二维码


Cesium 系列3- SceneWeather添加雨雪天气场景相关推荐

  1. Cesium-通过Shader添加雨雪天气效果

    前言 实验效果 代码 自定义GLSL代码 外部调用 总结 参考链接 前言 作为一个三维地球,在场景中来点雨雪效果,貌似可以增加一点真实感.Cesium 官网 Demo 中有天气系统的实例,用的是 Ce ...

  2. [unreal4入门系列之八] 使用VS编译UE4编辑器并添加物体到场景中

    接下来,我们将会创建一个放置我们的游戏角色的基本场景. 编译UE4编辑器 1) 现在,我们创建一个空白的UE4项目来开始.首先点击桌面的Epic Games Launcher,打开启动器,点击左上角的 ...

  3. 基于粒子(Points)模拟雨雪天气效果

    目录 功能描述 最终效果 准备工作 实现原理 参数配置 核心代码 功能描述 在基于THREE.js的场景中,实现雨雪天气效果,可设置下雨.雪的范围.位置.量级以及下落速度. 最终效果 雪 雨 准备工作 ...

  4. 微信小程序 | canvas为你的天气预报添加雨雪效果

    在 Canvas 开发中,经常会提到粒子系统,使用粒子系统可以模拟出火.雾.云.雪等抽象视觉效果.它是HTML5新增的为页面添加多样化效果的绝佳实践. 正巧最近做的一个天气类微信小程序紧接尾声,寻思着 ...

  5. 第六章 Cesium学习入门之添加Geojson数据(dataSource)

    从0开始的Cesium 第一章 Cesium学习入门之搭建Vite+Vue3+Cesium开发环境 第二章 Cesium学习入门之搭建Cesium界面预览和小控件隐藏 第三章 Cesium学习入门之地 ...

  6. canvas为你的天气预报添加雨雪效果 | 微信小程序

    关注 前端瓶子君,回复"交流" 加入我们一起学习,天天进步 来源:行舟客 https://yunxiaomeng.blog.csdn.net/article/details/110 ...

  7. 鬼影、雨雪天气点云噪声处理

    雨雪天气点云噪声处理 在雨雪天气中,点云噪声可能来自以下几个方面: 雨滴.雪花等降水物体对激光雷达的反射造成的干扰: 湿度.温度等气象因素对激光雷达的影响: 环境中的遮挡物或反射体造成的多次反射或回波 ...

  8. cesium实现向卫星添加传感器并跟随卫星移动

    cesium实现向卫星添加传感器并跟随卫星移动 import * as Cesium from 'cesium' import "./CesiumSensors.js";/* es ...

  9. creator 跳跃弧线_(转)CocosCreator零基础制作游戏《极限跳跃》四、添加游戏主场景控制脚本...

    CocosCreator零基础制作游戏<极限跳跃>四.添加游戏主场景控制脚本 前面简单的实现了主界面的UI设置,现在我们开始制作游戏的控制脚本. 在资源管理器的Script文件夹中,点击右 ...

最新文章

  1. Android CheckBox 点击的时候没有效果
  2. 你还不了解基于session的授权认证吗?
  3. 算法导论 第六章 堆排序 习题6.5-8 k路合并排序
  4. 在DataGridView中添加行号
  5. 跳板机连接数据库_跳板数据科学职业生涯回顾
  6. AI 线上峰会 | 人工智能技术解析与实战
  7. Hadoop发行版的比较与选择
  8. 【Java】hashCode和identityHashCode的区别
  9. 统计文件中以某个字母开头的单词的数目
  10. 分区挂载,mount,blkid
  11. PHP undefined index的几种解决方法
  12. 《现代操作系统》知识点整理
  13. 1、pr的基本操作流程学习
  14. 集合问题 : 容斥原理
  15. 职场人如何制定学习计划?
  16. Go字符串拼接方式深入比较
  17. vs2015 openssl-1.0.2j编译
  18. 百面机器学习 之 逻辑回归
  19. 唯一插件化Replugin源码及原理深度剖析--插件的安装、加载原理
  20. 一个应届毕业生的七次 悲惨 求职经历

热门文章

  1. 用python可以做哪些有趣的事_可以用 Python 来干些什么有趣的事?
  2. 读取风云4号卫星FullMask_Grid.raw文件
  3. ADBFastboot常用命令
  4. 罗兰贝格:自动驾驶出租车(Robotaxi)商业化前景展望(附下载)
  5. php 同学录设计与实现,同学录系统的设计与实现
  6. 微软认证考试70-461 Work with Data 数据处理 --27%比重--(5.5)
  7. 互联网时代的IP技术
  8. Avast与360安全卫士的冲突
  9. codeforces 729 C
  10. Appium元素定位方法