zoukankan      html  css  js  c++  java
  • Cesium应用篇--添加雨雪天气

      作为一个三维地球,在场景中来点雨雪效果,貌似可以增加一点真实感。Cesium官网Demo中有天气系统的实例,用的是Cesium中的粒子系统做的。效果如下图所示,粒子系统的本质是向场景中添加了很多物体,用BillBoard技术展现。这种实现方式有一个麻烦的地方就是当视角变化(拉近、拉远、平移、旋转)时,粒子就会变化,甚至会消失,影响体验。考虑用shader的方式直接模拟雨雪效果,恰好发现了Catzpaw大神写的模拟雨雪的shader,果断增添到Cesium中。

      1. 添加GLSL代码

      Catzpaw大神写的模拟雨雪的效果如下,那我们要做的就是将这个效果和地球场景融合。这就用到之前博客中介绍的后期处理过程,只需要添加一个PostProcessStage创建雪的效果,添加一个PostProcessState创建雨的效果即可。

      

      首先在Source/Shaders/PostProcessStages文件夹下新建Snow.glsl文件和Rain.glsl文件,glsl文件中存放雨雪效果的片元着色器代码。代码分别如下:

     1 uniform sampler2D colorTexture; //输入的场景渲染照片
     2 varying vec2 v_textureCoordinates;
     3 
     4 float snow(vec2 uv,float scale)
     5 {
     6     float time = czm_frameNumber / 60.0;
     7     float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;
     8     uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;
     9     uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;
    10     p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);
    11     k=smoothstep(0.,k,sin(f.x+f.y)*0.01);
    12     return k*w;
    13 }
    14 
    15 void main(void){
    16     vec2 resolution = czm_viewport.zw;
    17     vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
    18     vec3 finalColor=vec3(0);
    19     //float c=smoothstep(1.,0.3,clamp(uv.y*.3+.8,0.,.75));
    20     float c = 0.0;
    21     c+=snow(uv,30.)*.0;
    22     c+=snow(uv,20.)*.0;
    23     c+=snow(uv,15.)*.0;
    24     c+=snow(uv,10.);
    25     c+=snow(uv,8.);
    26     c+=snow(uv,6.);
    27     c+=snow(uv,5.);
    28     finalColor=(vec3(c)); //屏幕上雪的颜色
    29     gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5);  //将雪和三维场景融合
    30 
    31 }
     1 uniform sampler2D colorTexture;//输入的场景渲染照片
     2 varying vec2 v_textureCoordinates;
     3 
     4 float hash(float x){
     5     return fract(sin(x*133.3)*13.13);
     6 }
     7 
     8 void main(void){
     9 
    10     float time = czm_frameNumber / 60.0;
    11     vec2 resolution = czm_viewport.zw;
    12 
    13     vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
    14     vec3 c=vec3(.6,.7,.8);
    15 
    16     float a=-.4;
    17     float si=sin(a),co=cos(a);
    18     uv*=mat2(co,-si,si,co);
    19     uv*=length(uv+vec2(0,4.9))*.3+1.;
    20 
    21     float v=1.-sin(hash(floor(uv.x*100.))*2.);
    22     float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;
    23     c*=v*b; //屏幕上雨的颜色
    24 
    25     gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5); //将雨和三维场景融合
    26 }

       生成雨和雪的glsl代码很神奇,就是单纯的数学计算,意识到学好数学还是很重要的,再次向大神膜拜,哈哈。

      2. 创建PostProcessStage

      在上一步写完glsl代码后,接下来就是创建PostProcessStage对象。通过在PostProcessStageLibray类中添加两个函数,就可以创建出需要的PostProcessStage对象。代码如下:

     1 PostProcessStageLibrary.createSnowStage = function() {
     2         var snow = new PostProcessStage({
     3             name : 'czm_snow',
     4             fragmentShader : Snow
     5         });
     6         return snow;
     7     }
     8 
     9     PostProcessStageLibrary.createRainStage = function() {
    10         var snow = new PostProcessStage({
    11             name : 'czm_rain',
    12             fragmentShader : Rain
    13         });
    14         return snow;
    15     }

       3. 外部调用

       在准备好以上内容后,就可以直接在html页面中调用。为了达到更加逼真的效果,还需要更改一下大气参数。代码和效果如下:

    1 var collection = viewer.scene.postProcessStages;
    2 var snow = Cesium.PostProcessStageLibrary.createSnowStage();
    3 collection.add(snow);
    4 scene.skyAtmosphere.hueShift = -0.8;
    5 scene.skyAtmosphere.saturationShift = -0.7;
    6 scene.skyAtmosphere.brightnessShift = -0.33;
    7 
    8 scene.fog.density = 0.001;
    9 scene.fog.minimumBrightness = 0.8;

     

      4. 总结

      通过Shader这种方式模拟雨雪可以不受视点位置的影响,相当于是一个全屏的后处理,当然在效果模拟上还有可以增强的地方。本文描写的步骤可以作为大家在Cesium上添加后期处理效果步骤的一个参考。

    PS:Cesium交流可以扫码加群,期待你的加入!!!

  • 相关阅读:
    171 01 Android 零基础入门 03 Java常用工具类02 Java包装类 01 包装类简介 01 Java包装类内容简介
    170 01 Android 零基础入门 03 Java常用工具类01 Java异常 08 Java异常总结 01 异常总结
    169 01 Android 零基础入门 03 Java常用工具类01 Java异常 07 异常链 01 异常链简介
    168 01 Android 零基础入门 03 Java常用工具类01 Java异常 06 自定义异常 01 自定义异常类
    167 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 02 使用throw抛出异常对象
    166 01 Android 零基础入门 03 Java常用工具类01 Java异常 05 使用throw和throws实现异常处理 01 使用throws声明异常类型
    165 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 05 return关键字在异常处理中的使用
    DevExpress WPF v20.2版本亮点放送:全新升级的PDF Viewer
    界面控件DevExpress使用教程:Dashboard – 自定义导出
    DevExpress WinForms帮助文档:表单控件
  • 原文地址:https://www.cnblogs.com/webgl-angela/p/9846990.html
Copyright © 2011-2022 走看看