cesium材质学习笔记

346 阅读3分钟

自定义材质的两种方式

new Cesium.Material

  • 独立实例:使用new Cesium.Material每次都会创建一个新的材质实例,即使材质的定义和参数与之前创建的一样。这会导致更多的内存占用,特别是当场景中有许多材质实例且它们可以复用时。
  • 灵活性:直接实例化提供了更高的灵活性,因为你可以直接控制材质实例的生命周期,而不受缓存管理的影响。这在你需要对材质实例进行特定操作或管理其生命周期时很有用。
  • 直接控制:创建独立的实例允许你直接修改实例的属性,而不会影响到可能存在的其他相同配置的材质实例。
// 自定义材质
 let aper = new Cesium.MaterialAppearance({
    faceForward: true,
    material: new Cesium.Material({
      fabric: {
        uniforms: {
          uTime: 0,
          uWaterColor: new Cesium.Color(0.0, 0.0, 1.0, 0.5),
          uLineColor: new Cesium.Color(0.0, 1.0, 1.0, 0.5),
          uImage: "",
        },
        source: `
          float random(float x) {
             return fract(sin(x) * 10000.);
         }

          float noise(vec2 p) {
              return random(p.x + p.y * 10000.);
          }

          vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
          vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
          vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
          vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

          float smoothNoise(vec2 p) {
              vec2 interp = smoothstep(0., 1., fract(p));
              float s = mix(noise(sw(p)), noise(se(p)), interp.x);
              float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
              return mix(s, n, interp.y);
          }

          float fractalNoise(vec2 p) {
              float x = 0.;
              x += smoothNoise(p      );
              x += smoothNoise(p * 2. ) / 2.;
              x += smoothNoise(p * 4. ) / 4.;
              x += smoothNoise(p * 8. ) / 8.;
              x += smoothNoise(p * 16.) / 16.;
              return x / (3. + 1./2. + 1./4. + 1./8. + 1./16.);
          }

          float movingNoise(vec2 p) {
              float x = fractalNoise(p +0.5* uTime);
              float y = fractalNoise(p -0.5* uTime);
              return fractalNoise(p + vec2(x, y));
          }

          float nestedNoise(vec2 p) {
              float x = movingNoise(p);
              float y = movingNoise(p + 100.);
              return movingNoise(p + vec2(x, y));
          }
           vec4 czm_getMaterial(vec2 vUv)
           {
            vec2 uv = vUv;
            uv = vUv * 2.0 - 1.0;
            
            float n = nestedNoise(uv * 6.);
            vec4 newColor = vec4(mix(uWaterColor.rgb, uLineColor.rgb, n), 0.5);
            return newColor;
           }
        `,
      },
    }),
    translucent: true,
    vertexShaderSource: `
        attribute vec3 position3DHigh;
        attribute vec3 position3DLow;
        attribute float batchId;
        attribute vec2 st;
        attribute vec3 normal;
        varying vec2 v_st;
        varying vec3 v_positionEC;
        varying vec3 v_normalEC;
        void main() {
            v_st = st;
            vec4 p = czm_computePosition();
            v_positionEC = (czm_modelViewRelativeToEye * p).xyz;      // position in eye coordinates
            v_normalEC = czm_normal * normal;                         // normal in eye coordinates
            gl_Position = czm_modelViewProjectionRelativeToEye * p;
        }
                    `,
    fragmentShaderSource: `
      varying vec2 v_st;
      varying vec3 v_positionEC;
      varying vec3 v_normalEC;
      void main()  {
        vec3 positionToEyeEC = -v_positionEC;
        vec3 normalEC = normalize(v_normalEC);
        czm_materialInput materialInput;
        materialInput.normalEC = normalEC;
        materialInput.positionToEyeEC = positionToEyeEC;
        materialInput.st = v_st;
        vec4 color = czm_getMaterial(v_st);
        gl_FragColor = color;
      }
                `,
  });

Cesium.Material._materialCache.addMaterial

  • 资源管理:此方法会将新材质添加到Cesium内部维护的材质缓存中。这意味着如果你尝试添加一个已经存在于缓存中的材质(基于相同的定义和参数),它不会创建新的实例,而是返回缓存中已有的材质实例。这种方式有助于减少内存消耗,避免相同材质的重复创建。
  • 重复利用:通过缓存,可以确保多个具有相同属性的材质实例共享相同的底层资源,这对于性能优化尤其重要,尤其是在大量使用相同材质的场景中。
  • 访问方式:通常情况下,直接通过Cesium.Material._materialCache.getMaterial(materialId)来获取缓存中的材质,其中materialId是材质定义的唯一标识符。
class waterMaterial {
    constructor() {
        Cesium.Material._materialCache.addMaterial('waterMaterial', {
            fabric: {
                type:'waterMaterial',
                uniforms: {
                    uTime: 0,
                    uWaterColor: new Cesium.Color(0.0, 0.0, 1.0, 0.5),
                    uLineColor: new Cesium.Color(0.0, 1.0, 1.0, 0.5),
                    uImage: "",
                },
                source: `
                czm_material czm_getMaterial(czm_materialInput materialInput)
                {
                    czm_material material = czm_getDefaultMaterial(materialInput);
                    vec2 st = materialInput.st;
                    // czm_frameNumber得到当前屏幕的刷新率
                    float animation = czm_frameNumber/60.0;
                    // vec4 colorImage = texture2D(image, vec2(fract(st.s - animation), st.t));
                    // material.alpha = colorImage.a * color.a;
                    // material.diffuse = (colorImage.rgb+color.rgb)/2.0;
                    material.diffuse =vec3(1.0,0.0,0.0);
                    return material;
                }
                `,
            },
            translucent: function (material) {
                return true;
            },
        })
    }
    getType() {
        return 'waterMaterial'
    }
    getValue(time, result) {
        return result
    }
}