
开发说明
Cesium 自定义材质最难理解的并不是模板,而是 Property、uniforms 和 GLSL source 三者如何传值。把这个关系理顺以后,流动线、水波纹以及扫描圆的结构几乎一致。
MaterialProperty 的职责
类中保存可响应变化的参数,getType 返回材质名,getValue 在每次渲染时把最新值交给 uniforms。definitionChanged 则让 Cesium 知道参数发生了变化。
export class FlowLineMaterialProperty {
_definitionChanged = new Event()
constructor(options = {}) {
this.color = options.color ?? Color.WHITE
this.speed = options.speed ?? 1
this.repeat = options.repeat ?? new Cartesian2(1, 1)
}
getType() { return "FlowLine" }
getValue(time, result = {}) {
result.color = Property.getValueOrClonedDefault(this._color, time, Color.WHITE)
result.speed = Property.getValueOrDefault(this._speed, time, 1)
result.repeat = Property.getValueOrDefault(this._repeat, time, new Cartesian2(1, 1))
return result
}
}
注册材质
uniforms 的名字必须与 getValue 返回值以及 source 内使用的变量一致。真正决定视觉效果的是 source,其余代码主要负责把参数安全地送进去。
Material._materialCache.addMaterial("FlowLine", {
fabric: {
type: "FlowLine",
uniforms: { color: Color.WHITE, speed: 1, repeat: new Cartesian2(1, 1) },
source: "czm_material czm_getMaterial(czm_materialInput input) { /* GLSL */ }",
},
translucent: true,
})
容易踩坑的地方
材质名重复会覆盖缓存;uniform 名称拼错不会给出友好错误;高频创建 Property 会制造额外垃圾回收。推荐在模块初始化时只注册一次材质,业务侧只创建 Property 实例。