Cesium 系列3- SceneWeather添加雨雪天气场景

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

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

Cesium 系列3- SceneWeather添加雨雪天气场景_第1张图片

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

其他解决方案网址:网址

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

实现方法:

方法一:

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

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

Cesium 系列3- SceneWeather添加雨雪天气场景_第2张图片

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

snow.html




    
    
    
    
    Tools-29postProcess-Snow
      -->
	
	
	 
    


    

其中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 _;
    }
)();

下雨的例子:



	
		
		
		
		
		Tools-29postProcess-Snow
		
		
		
		
		
	
	
		

整合在一起的例子如下:

Cesium 系列3- SceneWeather添加雨雪天气场景_第3张图片

部分代码:

移除雨雪方法:

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专栏)