/**
 * @description 下雪天气模拟特效
 * @param {CesiumMapType} viewer - 地图对象
 * @options: 下雪效果配置
 * @options.snowSize: 雪花大小
 * @options.snowSpeed: 雪花落下速度
 */
class SnowEffect {
    snowSize;
    snowSpeed;
    viewer;
    snowStage;
    constructor(viewer, options) {
        if (!viewer)
            throw new Error('no viewer object!');
        options = options || {};
        this.snowSize = Cesium.defaultValue(options.snowSize, 0.02); //最好小于0.02
        this.snowSpeed = Cesium.defaultValue(options.snowSpeed, 60.0);
        this.viewer = viewer;
        this.init();
    }
    init() {
        this.snowStage = new Cesium.PostProcessStage({
            name: 'czm_snow',
            fragmentShader: this.snow(),
            uniforms: {
                snowSize: () => {
                    return this.snowSize;
                },
                snowSpeed: () => {
                    return 100 - this.snowSpeed;
                }
            }
        });
        this.snowStage.enabled = false;
        this.viewer.scene.postProcessStages.add(this.snowStage);
    }
    destroy() {
        if (!this.viewer || !this.snowStage)
            return;
        this.viewer.scene.postProcessStages.remove(this.snowStage);
        this.snowStage.destroy();
    }
    show(visible) {
        this.snowStage.enabled = visible;
    }
    snow() {
        return `
      uniform sampler2D colorTexture;
      varying vec2 v_textureCoordinates;
      uniform float snowSpeed;
      uniform float snowSize;
      float snow(vec2 uv,float scale)
      {
          float time=czm_frameNumber/snowSpeed;
          float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;
          uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;
          uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;
          p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);
          k=smoothstep(0.,k,sin(f.x+f.y)*snowSize);
          return k*w;
      }
      void main(void){
          vec2 resolution=czm_viewport.zw;
          vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
          vec3 finalColor=vec3(0);
          //float c=smoothstep(1.,0.3,clamp(uv.y*.3+.8,0.,.75));
          float c=0.;
          c+=snow(uv,30.)*.0;
          c+=snow(uv,20.)*.0;
          c+=snow(uv,15.)*.0;
          c+=snow(uv,10.);
          c+=snow(uv,8.);
          c+=snow(uv,6.);
          c+=snow(uv,5.);
          finalColor=(vec3(c));
          gl_FragColor=mix(texture2D(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);
        }
      `;
    }
}
/**
 * @description 下雨天气模拟特效
 * @param {CesiumMapType} viewer - 地图对象
 * @options: 下雨效果配置
 * @options.tiltAngle: 雨滴倾斜角度
 * @options.snowSize: 雨滴大小
 * @options.snowSpeed: 雨滴落下速度
 */
class RainEffect {
    tiltAngle;
    rainSize;
    rainSpeed;
    viewer;
    rainStage;
    constructor(viewer, options) {
        if (!viewer)
            throw new Error('no viewer object!');
        options = options || {};
        //倾斜角度，负数向右，正数向左
        this.tiltAngle = Cesium.defaultValue(options.tiltAngle, -0.0);
        this.rainSize = Cesium.defaultValue(options.rainSize, 0.3);
        this.rainSpeed = Cesium.defaultValue(options.rainSpeed, 60.0);
        this.viewer = viewer;
        this.init();
    }
    init() {
        this.rainStage = new Cesium.PostProcessStage({
            name: 'czm_rain',
            fragmentShader: this.rain(),
            uniforms: {
                tiltAngle: () => {
                    return this.tiltAngle;
                },
                rainSize: () => {
                    return this.rainSize;
                },
                rainSpeed: () => {
                    return 100 - this.rainSpeed;
                }
            }
        });
        this.rainStage.enabled = false;
        this.viewer.scene.postProcessStages.add(this.rainStage);
    }
    destroy() {
        if (!this.viewer || !this.rainStage)
            return;
        this.viewer.scene.postProcessStages.remove(this.rainStage);
        this.rainStage.destroy();
    }
    show(visible) {
        this.rainStage.enabled = visible;
    }
    rain() {
        return `
      uniform sampler2D colorTexture;
      varying vec2 v_textureCoordinates;
      uniform float tiltAngle;
      uniform float rainSize;
      uniform float rainSpeed;
      float hash(float x) {
          return fract(sin(x * 133.3) * 13.13);
      }
      void main(void) {
          float time = czm_frameNumber / rainSpeed;
          vec2 resolution = czm_viewport.zw;
          vec2 uv = (gl_FragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y);
          vec3 c = vec3(.6, .7, .8);
          float a = tiltAngle;
          float si = sin(a), co = cos(a);
          uv *= mat2(co, -si, si, co);
          uv *= length(uv + vec2(0, 4.9)) * rainSize + 1.;
          float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);
          float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;
          c *= v * b;
          gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c, 1), .5);
      }
    `;
    }
}
/**
 * @description 雾天气模拟特效
 * @param {CesiumMapType} viewer - 地图对象
 * @options: 雾效果配置
 * @options.fogVisibility: 雾的可见度
 * @options.fogColor: 雾的颜色
 */
class FogEffect {
    visibility;
    color;
    viewer;
    fogState;
    constructor(viewer, options) {
        if (!viewer)
            throw new Error('no viewer object!');
        options = options || {};
        this.visibility = Cesium.defaultValue(options.fogVisibility, 1.0);
        this.color = Cesium.defaultValue(options.fogColor, '#8c8c8c');
        this.viewer = viewer;
        this.init();
    }
    init() {
        this.fogState = new Cesium.PostProcessStage({
            name: 'czm_fog',
            fragmentShader: this.fog(),
            uniforms: {
                visibility: () => {
                    return this.visibility;
                },
                fogColor: () => {
                    return Cesium.Color.fromCssColorString(this.color);
                }
            }
        });
        this.fogState.enabled = false;
        this.viewer.scene.postProcessStages.add(this.fogState);
    }
    destroy() {
        if (!this.viewer || !this.fogState)
            return;
        this.viewer.scene.postProcessStages.remove(this.fogState);
        this.fogState.destroy();
    }
    show(visible) {
        this.fogState.enabled = visible;
    }
    fog() {
        return `uniform sampler2D colorTexture;
       uniform sampler2D depthTexture;
       uniform float visibility;
       uniform vec4 fogColor;
       varying vec2 v_textureCoordinates; 
       void main(void) 
       { 
          vec4 origcolor = texture2D(colorTexture, v_textureCoordinates); 
          float depth = czm_readDepth(depthTexture, v_textureCoordinates); 
          vec4 depthcolor = texture2D(depthTexture, v_textureCoordinates); 
          float f = visibility * (depthcolor.r - 0.3) / 0.2;
          if (f < 0.0) f = 0.0;
          else if (f > 0.9) f = 0.9;
          gl_FragColor = mix(origcolor, fogColor, f); 
       }`;
    }
}
export default {
    SnowEffect,
    RainEffect,
    FogEffect
};
