const viewer = new Cesium.Viewer('cesiumContainer')

let xMin = 115.894604,
  yMin = 39.516896,
  xMax = 117.431959,
  yMax = 40.630521
let rect = new Cesium.Rectangle(
  Cesium.Math.toRadians(xMin),
  Cesium.Math.toRadians(yMin),
  Cesium.Math.toRadians(xMax),
  Cesium.Math.toRadians(yMax)
)

const rectangle = new Cesium.RectangleGeometry({
  rectangle: rect,
  height: 10000.0,
})
const geometry = Cesium.RectangleGeometry.createGeometry(rectangle)
viewer.scene.primitives.add(
  new Cesium.Primitive({
    asynchronous: false,
    geometryInstances: new Cesium.GeometryInstance({
      geometry: geometry,
    }),
    appearance: new Cesium.MaterialAppearance({
      material: new Cesium.Material({
        fabric: {
          uniforms: {
            image: './texture.png',
          },
        },
      }),
      fragmentShaderSource: ` 
            in vec3 v_positionEC;//顶点 相机（眼睛）坐标系 
            in vec3 v_normalEC;//顶点法线 相机（眼睛）坐标系 
            in vec2 v_st;//纹理坐标 uv
            /**
            This tab contains all the necessary noise functions required to model a cloud shape.
            */

            // Hash by David_Hoskins
            #define UI0 1597334673U
            #define UI1 3812015801U
            #define UI2 uvec2(UI0, UI1)
            #define UI3 uvec3(UI0, UI1, 2798796415U)
            #define UIF (1.0 / float(0xffffffffU))

            vec3 hash33(vec3 p)
            {
                uvec3 q = uvec3(ivec3(p)) * UI3;
                q = (q.x ^ q.y ^ q.z)*UI3;
                return -1. + 2. * vec3(q) * UIF;
            }

            float remap(float x, float a, float b, float c, float d)
            {
                return (((x - a) / (b - a)) * (d - c)) + c;
            }

            // Gradient noise by iq (modified to be tileable)
            float gradientNoise(vec3 x, float freq)
            {
                // grid
                vec3 p = floor(x);
                vec3 w = fract(x);

                // quintic interpolant
                vec3 u = w * w * w * (w * (w * 6. - 15.) + 10.);

                // gradients
                vec3 ga = hash33(mod(p + vec3(0., 0., 0.), freq));
                vec3 gb = hash33(mod(p + vec3(1., 0., 0.), freq));
                vec3 gc = hash33(mod(p + vec3(0., 1., 0.), freq));
                vec3 gd = hash33(mod(p + vec3(1., 1., 0.), freq));
                vec3 ge = hash33(mod(p + vec3(0., 0., 1.), freq));
                vec3 gf = hash33(mod(p + vec3(1., 0., 1.), freq));
                vec3 gg = hash33(mod(p + vec3(0., 1., 1.), freq));
                vec3 gh = hash33(mod(p + vec3(1., 1., 1.), freq));

                // projections
                float va = dot(ga, w - vec3(0., 0., 0.));
                float vb = dot(gb, w - vec3(1., 0., 0.));
                float vc = dot(gc, w - vec3(0., 1., 0.));
                float vd = dot(gd, w - vec3(1., 1., 0.));
                float ve = dot(ge, w - vec3(0., 0., 1.));
                float vf = dot(gf, w - vec3(1., 0., 1.));
                float vg = dot(gg, w - vec3(0., 1., 1.));
                float vh = dot(gh, w - vec3(1., 1., 1.));

                // interpolation
                return va + 
                       u.x * (vb - va) + 
                       u.y * (vc - va) + 
                       u.z * (ve - va) + 
                       u.x * u.y * (va - vb - vc + vd) + 
                       u.y * u.z * (va - vc - ve + vg) + 
                       u.z * u.x * (va - vb - ve + vf) + 
                       u.x * u.y * u.z * (-va + vb + vc - vd + ve - vf - vg + vh);
            }

            // Tileable 3D worley noise
            float worleyNoise(vec3 uv, float freq)
            {    
                vec3 id = floor(uv);
                vec3 p = fract(uv);

                float minDist = 10000.;
                for (float x = -1.; x <= 1.; ++x)
                {
                    for(float y = -1.; y <= 1.; ++y)
                    {
                        for(float z = -1.; z <= 1.; ++z)
                        {
                            vec3 offset = vec3(x, y, z);
                            vec3 h = hash33(mod(id + offset, vec3(freq))) * .5 + .5;
                            h += offset;
                            vec3 d = p - h;
                               minDist = min(minDist, dot(d, d));
                        }
                    }
                }

                // inverted worley noise
                return 1. - minDist;
            }

            // Fbm for Perlin noise based on iq's blog
            float perlinfbm(vec3 p, float freq, int octaves)
            {
                float G = exp2(-.85);
                float amp = 1.;
                float noise = 0.;
                for (int i = 0; i < octaves; ++i)
                {
                    noise += amp * gradientNoise(p * freq, freq);
                    freq *= 2.;
                    amp *= G;
                }

                return noise;
            }

            // Tileable Worley fbm inspired by Andrew Schneider's Real-Time Volumetric Cloudscapes
            // chapter in GPU Pro 7.
            float worleyFbm(vec3 p, float freq)
            {
                return worleyNoise(p*freq, freq) * .625 +
                         worleyNoise(p*freq*2., freq*2.) * .25 +
                         worleyNoise(p*freq*4., freq*4.) * .125;
            }

            void main(  )
            {
                vec2 uv =  v_st;
                float iTime=czm_frameNumber/100.;
                uv -= .02 * iTime;
                vec2 m = vec2(0.5);

                vec4 col = vec4(0.);

                float slices = 128.; // number of layers of the 3d texture
                float freq = 4.;

                float pfbm= mix(1., perlinfbm(vec3(uv, floor(m.y*slices)/slices), 4., 7), .5);
                pfbm = abs(pfbm * 2. - 1.); // billowy perlin noise

                col.g += worleyFbm(vec3(uv, floor(m.y*slices)/slices), freq);
                col.b += worleyFbm(vec3(uv, floor(m.y*slices)/slices), freq*2.);
                col.a += worleyFbm(vec3(uv, floor(m.y*slices)/slices), freq*4.);
                col.r += remap(pfbm, 0., 1., col.g, 1.); // perlin-worley 

                float perlinWorley =  col.r;

                // worley fbms with different frequencies
                vec3 worley = col.yzw;
                float wfbm = worley.x * .625 +
                             worley.y * .125 +
                             worley.z * .25; 

                // cloud shape modeled after the GPU Pro 7 chapter
                float cloud = remap(perlinWorley, wfbm - 1., 1., 0., 1.);
                cloud = remap(cloud, .65, 1., 0., 1.); // fake cloud coverage

                vec3 col_ = vec3(0.); 
                col_ += cloud;  

                out_FragColor = vec4(col_,col.r); }`,
    }),
  })
)
