Cesium高级-1、下雨特效

  • Post author:
  • Post category:其他


Cesium中,提供了粒子效果,也能够实现下雨效果。但我个人觉得整体效果不是很满意:

1、粒子是局部的,如果覆盖范围过小,相机移动后,下雨效果就会移出屏幕。

2、下雨效果不是很明显(可能是我的参数设置的不是很准确)

偶然阅读了其他大佬的文章,发现用后处理特效可以实现很好的下雨效果。直接粘代码:

export function setRainEffect(viewer:Cesium.Viewer){
  const fs = `//【内置变量】颜色纹理,用于在片元着色器中访问各个像素的颜色
              uniform sampler2D colorTexture;
              //【内置变量】纹理坐标,是从顶点着色器中传递下来的。
              varying vec2 v_textureCoordinates;
                
              float hash(float x){
                //取小数部分
                return fract(sin(x*23.3)*13.13);
              }
                
              void main(){
                  //将当前帧数转换为以秒为单位的时间
                  //在Cesium中,czm_frameNumber是一个递增整数值
                  //且一秒钟内,平均会渲染大约60帧,因此除以60可以得到近似的秒数
                  float time = czm_frameNumber / 60.0;
                  
                  //窗口分辨率
                  vec2 resolution = czm_viewport.zw;
                  //转换为uv坐标(-1,1)
                  //gl_FragCoord.xy 表示当前片段的屏幕坐标(或窗口坐标)的X和Y分量。
                  //resolution.xy 表示屏幕或窗口的宽度和高度
                  //gl_FragCoord.xy * 2.0 - resolution.xy 将屏幕坐标扩大两倍,然后减去屏幕的宽度和高度。这样处理可以将坐标原点移至屏幕中心。
                  vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
                  
                  //雨颜色值(153,178,204),并做归一化处理(除以255)
                  vec3 c=vec3(0.6,0.7,0.8);
                  //定义雨滴的倾角0.4弧度,转为角度约为23度
                  float a=0.4;
                  float si=sin(a),co=cos(a);
                  //将纹理坐标uv角度a旋转
                  uv*=mat2(co,-si,si,co);
                  //将纹理坐标进行缩放变换(变形)
                  uv*=length(uv+vec2(0,4.9))*0.3+1.0;
                  
                  //加入时间time,基础雨滴颜色,及变换后的uv坐标和一系列随机值运算
                  //得到每一个像素的雨滴颜色
                  float v=1.0-sin(hash(floor(uv.x*100.0))*2.0);
                  float b=clamp(abs(sin(20.0*time*v+uv.y*(5.0/(2.0+v))))-0.95,0.0,1.0)*20.;
                  c*=v*b;
                  //将雨与场景颜色混合
                  //texture2D(colorTexture, v_textureCoordinates)是获取场景原始颜色值
                  gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c, 1),0.4);
              }
                `;

  viewer.scene.postProcessStages.add(new PostProcessStage({
    name:'rainEffect',
    fragmentShader:fs,
  }))
}

因为我也是小白,所以对每一句代码都做了注释说明。

但对于形成雨滴的关键算法,还是没有太懂是什么原理。还希望看到的大佬能够指点迷津。



版权声明:本文为lying_19原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。