Cesium材质——Material

发布于:2025-02-11 ⋅ 阅读:(82) ⋅ 点赞:(0)

简介:

Cesium.Material对象的目的,就是生成一段名称为czm_getMaterial的函数(示例代码如下),

这个czm_getMaterial函数,是shader代码,会被放到片元着色器中使用。

czm_material czm_getMaterial(czm_materialInput materialInput)
{
    ...省略代码...
    return material;
}

Cesium.Material主要被MaterialProperty、Appearace这2个对象使用

1、创建自定义Material对象

创建一个自定义的material对象,主要是掌握fabric的结构就可以

fabric官方参考:

https://github.com/CesiumGS/cesium/wiki/Fabric

let materialPolylineFlow = new Cesium.Material({
  fabric: {
    type: "PolylineFlow",//自定义type类型
    uniforms: {
      color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
      speed: 4,
      percent: 0.1,
      gradient: 0.4,
    },
    source: fs,//自定义的着色器,也就是定义czm_getMaterial函数的地方
  },
  translucent: function (material) {
    return true;
  },
});

2、Material的复用

上述代码定义了一个type(类型)名为“PolylineFlow”的Material实例对象。

里面包含4个uniform变量、一段自定义的shader代码、还有控制透明度的函数

问题:如果我想复用这个material对象,该怎么做?

比如,我想声明一个一模一样的material效果,只是color为蓝色Cesium.Color.BLUE

我该怎么做?

方案1:复制上述所有代码

只是修改color的值

let materialPolylineFlowBlue = new Cesium.Material({
  fabric: {
    //type: "PolylineFlowBlue",//不能和上面的PolylineFlow同名(也可以不写这个值)
    uniforms: {
      color: new Cesium.Color(0.0, 0.0, 1.0, 1.0),//只是这里的值变了,其他都没变
      speed: 4,
      percent: 0.1,
      gradient: 0.4,
    },
    source: fs,
  },
  translucent: function (material) {
    return true;
  },
});

这个可行,就是重复代码太多

方案2:封装一个工具类

解决重复代码,第1个想到的就是自己封装一个类,把公共代码集中到一块

class util{
  
 static getMaterialByType(strTypeName,options){
    if(strTypeName=="PolylineFlow"){
      let {color=new Cesium.Color(1.0, 0.0, 0.0, 1.0),
           speed=4,
           percent=0.1,
           gradient=0.4
          }=options;
      //——————下述代码和之前基本一致——————
      let material = new Cesium.Material({
        fabric: {
          //type: "PolylineFlowBlue",//没必要再传入这个参数了
          uniforms: {
            color: color,
            speed: speed,
            percent: percent,
            gradient: gradient,
          },
          source: fs,
        },
        translucent: function (material) {
          return true;
        },
      });
      //——————上述代码和之前基本一致——————
    }else if(strTypeName=="otherType"){
      //其他类型的Material
    }
  }
}

这个也可行!

获取一个蓝色的Material,代码如下

let materialBlue=util.getMaterialByType("PolylineFlow",{
  color:Cesium.Color.BLUE
})
方案3:Cesium自己的方案

通过Cesium.Material._materialCache.addMaterial来注册一个type类型的Material

Cesium.Material.PolylineFlowType = "PolylineFlow";
Cesium.Material._materialCache.addMaterial(
  Cesium.Material.PolylineFlowType,
  {
    fabric: {
      type: Cesium.Material.PolylineFlowType,
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
        speed: 4,
        percent: 0.1,
        gradient: 0.4,
      },
      source: fs,
    },
    translucent: function (material) {
      return true;
    },
  },
);

之后,如果要复用这个PolylineFlow类型的Material

Cesium提供了2中方法

方法1:
let materialByNew = new Cesium.Material({
  fabric: {
    type: "PolylineFlow",
    uniforms: {
      color: new Cesium.Color(0.0, 0.0, 1.0, 1.0),
    },
  },
});

不推荐使用这个,假如type传入一个“非注册过”的material类型

不会报错,反而会进行“不完全注册”!

“不完全注册”是指

new Cesium.Material()的源码中,

虽然执行了Cesium.Material._materialCache.addMaterial()方法

但是,并不能复用!(可能是Cesium的bug)

方法2:
let materialByFrom = Cesium.Material.fromType("PolylineFlow", {
  color: new Cesium.Color(0.0, 1.0, 0.0, 1.0),
});

推荐使用这个,因为它就是一个纯粹的复用

fromType()的第1个参数,是要复用的material的type名称

如果传入的type值,不在materialCache中,则直接报错。


网站公告

今日签到

点亮在社区的每一天
去签到