cesium特效扩散圆

361 阅读2分钟

前言

今天主要和大家介绍一下cesium中怎么实现一个扩散圆的效果!

基本原理

如果有一个红色的圆形,我们希望在shader里面把这个圆形变成一个从四周向中心透明渐变的圆应该怎么做呢?我们只需要通过"UV"去计算导中心(0.5,0.5)的距离就可以得到。

2.png

1.png

    //伪代码
    float dis = distance(uv, vec2(0.5, 0.5)); 
    color.a = fract(dis); 

如果我希望圆形呈现一个慢慢变大的效果应该怎么做呢?我们只需要判断当dis大于某个阈值的时候透明度为零,否则不变,这个阈值随时间不断从0-1就行。

3.png

4.png //伪代码 //fract函数去time的小数,范围0-1 float per1 = fract(time); float dis = distance(uv, vec2(0.5, 0.5)); //step函数当dis大于per1的时候返回1,小于就返回0, float pass1 = step(per1, dis) == 0.0? color.a * dis / per1: 0.0; color.a = pass1;

5.png

cesium实现

基本的原理就是这样,那接下来就让我们自cesium实现这个效果。

1.先用 primetive 创建一个圆形

    const instance = new Cesium.GeometryInstance({
        geometry: new Cesium.EllipseGeometry({
            center: Cesium.Cartesian3.fromDegrees(118, 23, 0),
            semiMinorAxis: 500,
            semiMajorAxis: 500,
        }),
    });

2.创建一个 MaterialAppearance,更具上面的原理修改 material 的 source,注意下面的代码我优化了一下效果,增加了两道波纹,并且实现了一个渐变消失的过程。

const appearance = new Cesium.MaterialAppearance({
    material: new Cesium.Material({
        fabric: {
            uniforms: {
                color: Cesium.Color.fromCssColorString(color),
                speed: 1,
            },
            source: `
                czm_material czm_getMaterial(czm_materialInput materialInput) { 
                    czm_material material = czm_getDefaultMaterial(materialInput);
                    material.diffuse = 1.5 * color.rgb; 
                    vec2 st = materialInput.st; 
                    float dis = distance(st, vec2(0.5, 0.5)); 
                    //重复三次,每次的时间偏移一点,实现三道扩散
                    float per1 = fract(czm_frameNumber * 0.032 * speed); 
                    float per2 = fract((czm_frameNumber * 0.032 * speed) - 0.3); 
                    float per3 = fract((czm_frameNumber * 0.032 * speed) - 0.6); 
                    float pass1 = step(per1 * 0.3, dis) == 0.0? color.a * dis / per1: 0.0;
                    float pass2 = step(per2 * 0.3, dis) == 0.0? color.a * dis / per2: 0.0;
                    float pass3 = step(per3 * 0.3, dis) == 0.0? color.a * dis / per3: 0.0;
                    //实现每道扩散渐变消失的效果
                    pass1 = pass1* (1.0 - per1) * 2.0;
                    pass2 = pass2* (1.0 - per2) * 2.0;
                    pass3 = pass3* (1.0 - per3) * 2.0;
                    material.alpha = pass1; 
                    return material; 
                }
            `,
        }
    }),
})

3.最终添加场景就行了

 let primitive = viewer.scene.primitives.add(
    new Cesium.Primitive({
        geometryInstances: instance,
        appearance: appearance
    })
);

扩散圆的效果到这里就介绍完毕啦,希望能对大家有所帮助!有问题可以在评论区留言~小编会定时回复大家的问题

7.gif