[CesiumJS material] (1) circular diffusion

Effect example

Best Practices:
Please add a picture description

Other Effects:
Please add a picture description
Element Description:insert image description here

the code

/*
 * @Date: 2023-07-21 15:15:32
 * @LastEditors: ReBeX  [email protected]
 * @LastEditTime: 2023-07-27 11:13:17
 * @FilePath: \cesium-tyro-blog\src\utils\Material\EllipsoidFadeMaterialProperty.js
 * @Description: 扩散圆材质
 */
import * as Cesium from 'cesium'

export default class EllipsoidFadeMaterialProperty {
    
    
  constructor(options) {
    
    
    this._definitionChanged = new Cesium.Event();
    this._color = undefined;
    this._colorSubscription = undefined;
    this._time = (new Date()).getTime();
    this.color = options.color;
    this.duration = options.duration;
  };

  get isConstant() {
    
    
    return false;
  }

  get definitionChanged() {
    
    
    return this._definitionChanged;
  }

  getType(time) {
    
    
    return Cesium.Material.EllipsoidFadeMaterialType;
  }

  getValue(time, result) {
    
    
    if (!Cesium.defined(result)) {
    
    
      result = {
    
    };
    }

    result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
    result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
    return result;
  }

  equals(other) {
    
    
    return (this === other ||
      (other instanceof EllipsoidFadeMaterialProperty &&
        Property.equals(this._color, other._color))
    )
  }
}

Object.defineProperties(EllipsoidFadeMaterialProperty.prototype, {
    
    
  color: Cesium.createPropertyDescriptor('color'),
})

// Cesium.EllipsoidFadeMaterialProperty = EllipsoidFadeMaterialProperty;
Cesium.Material.EllipsoidFadeMaterialProperty = 'EllipsoidFadeMaterialProperty';
Cesium.Material.EllipsoidFadeMaterialType = 'EllipsoidFadeMaterialType';
Cesium.Material.EllipsoidFadeMaterialSource =
  `
  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 per = fract(time);
    if(dis > per * 0.5){
      material.alpha = 0.0;
      discard;
    }else {
      material.alpha = color.a  * dis / per / 1.0;
    }
    return material;
  }
  `

Cesium.Material._materialCache.addMaterial(Cesium.Material.EllipsoidFadeMaterialType, {
    
    
  fabric: {
    
    
    type: Cesium.Material.EllipsoidFadeMaterialType,
    uniforms: {
    
    
      color: new Cesium.Color(1.0, 0.0, 0.0, 1),
      time: 0
    },
    source: Cesium.Material.EllipsoidFadeMaterialSource
  },
  translucent: function (material) {
    
    
    return true;
  }
})
console.log('成功加载扩散圆材质');


// ? 如何使用
// import EllipsoidFadeMaterialProperty from '@/utils/Material/EllipsoidFadeMaterialProperty.js'

// material: new EllipsoidFadeMaterialProperty({
    
    
//   color: new Cesium.Color(1.0, 1.0, 0.0, 0.8),
//   duration: 3000,
// })

Example

import EllipsoidFadeMaterialProperty from '@/utils/Material/EllipsoidFadeMaterialProperty.js' // 引入这个材质类
import {
    
     viewer } from '@/utils/createCesium.js' // 引入地图对象
import * as Cesium from 'cesium'

const ellipse= viewer.entities.add({
    
    
  position: Cesium.Cartesian3.fromDegrees(50, 50),
  ellipse: {
    
    
    semiMajorAxis: 150000.0, // 长半轴距离
    semiMinorAxis: 150000.0, // 短半轴距离
    
    // ! 重点
    material: new EllipsoidFadeMaterialProperty({
    
    
      color: new Cesium.Color(1.0, 1.0, 0.0, 0.8),
      duration: 3000,
    }),
  }
});
viewer.zoomTo(ellipse);

shader

The core of implementing a custom material is the source attribute of the fabric object. The following is the shader code of this material based on GLSL syntax:

  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 per = fract(time);
    if(dis > per * 0.5){
    
    
      material.alpha = 0.0;
      discard;
    }else {
    
    
      material.alpha = color.a  * dis / per / 1.0;
    }
    return material;
  }

materialInputThe main function of the code is to create a material object according to the input material, then modify the material according to some logic, and finally return the modified material.

Here is an explanation of the code:

  1. czm_getDefaultMaterial(materialInput)Create a default material: Create a default material object by calling a function and assign it to a variable material.
  2. Modify the diffuse color: set to 1.5 times the material.diffusecurrent color value . color.rgbThis changes the diffuse color of the material.
  3. Calculate the distance and scale: materialInput.stGet the texture coordinates by and calculate the distance from the texture coordinates to (0.5, 0.5) dis. Then use the global variable timeto calculate the fractional part of the current time per.
  4. Judgment distance condition: if disis greater than permultiplied by 0.5, enter ifthe statement block. In this statement block, material.alphaset to 0.0, which means full transparency, and use discardthe keyword to discard the current fragment (drawing is invalid). The purpose of this conditional statement is to control transparency and visibility based on distance and current time.
  5. Calculation transparency: If the above distance condition is not met, enter elsethe statement block. In the block, material.alphaset to the result of color.amultiplying disby perdividing by 1.0. Means to dynamically adjust the transparency of the material based on distance, time and color transparency.
  6. ReturnModifiedMaterial: Returns the modifiedMaterial materialas the result of the function.

reference

  1. Cesium custom material Material and some thoughts - czm_material_GhostPaints' Blog - CSDN Blog

Guess you like

Origin blog.csdn.net/ReBeX/article/details/131976206