Cesium 1.95 的材质系统是其可视化能力的核心,提供了丰富的材质类型和高度自定义能力。
一、材质基础概念
1. 材质组成要素
颜色/纹理:定义基础外观
光照响应:漫反射、镜面反射等
透明度:alpha通道控制
特殊效果:发光、法线贴图等
2、核心组件
MaterialProperty:材质属性基类
Material:运行时材质实例
Fabric Schema:材质定义规范
Shader Pipeline:着色器处理管线
3、渲染流程
材质定义 → 材质编译 → Uniform绑定 → 着色器生成 → 渲染执行
4、材质类型
基础材质类型
颜色材质 (Color):通过CSS颜色字符串或 Cesium.Color 设置颜色,支持透明度调节。
图像材质 (Image):使用纹理图像(如png)作为表面纹理。
棋盘材质 (Checkerboard)、 斑马线材质 (Stripe)、 网格材质 (Grid):通过预设图案实现纹理效果。
自定义材质
通过 GLSL着色器 编写自定义材质,需定义 Fabric结构体 ,包含type、uniforms(统一值)和source(着色器代码)。例如:
fabric : {
type : 'Color',
uniforms : {
color : 'rgba(255, 255, 255, 0.5)'
}
}
或直接使用 Cesium内置函数 如czm_getMaterial动态计算材质属性。
材质类型(type)
- 标识材质的唯一名称
- 可用于后续材质引用
统一变量(uniforms)
- 定义材质参数,可在运行时修改
- 支持的类型包括:颜色、数字、纹理等
着色器代码(source)
- 使用GLSL编写
- 可以访问Cesium提供的实用函数(czm_*)
- 必须包含材质输出结构
Cesium 1.95 中的新特性
- 改进的材质性能:优化了材质系统的渲染性能
- 增强的纹理支持:更好的纹理压缩和流式加载
- 扩展的uniform类型:支持更多类型的uniform变量
- 调试工具改进:更好的材质调试支持
常用内置函数
- Cesium 提供了许多有用的GLSL函数:
- czm_getDefaultMaterial() - 获取默认材质
- czm_materialInput - 包含材质输入信息(st, normal, position等)
- czm_pixelToTextureCoordinates() - 像素坐标转纹理坐标
- czm_eyeToWindowCoordinates() - 眼空间坐标转窗口坐标
5. 材质应用场景
实体(Entity)外观
通过:ml-search[materialProperty]设置材质(如Color.fromCssColorString)。
3D Tiles样式化
自定义图元(Primitive)
使用:ml-search[Material类]直接修改几何体材质,需定义 Fabric JSON 。
二、使用方式:
1. 创建与应用
应用于实体
const entity = viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([...]),
material: new Cesium.ColorMaterialProperty(Cesium.Color.RED)
}
});
完整实例
const viewer = new Cesium.Viewer("cesiumContainer");
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(116.3, 39.9, 100000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-60),
roll: 0.0,
},
});
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
116.2, 39.8, 116.4, 39.8, 116.4, 40.0, 116.2, 40.0,
]),
material: new Cesium.Color.BLUE.withAlpha(0.7),
height: 0,
extrudedHeight: 10000
},
});
应用于图元
const primitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({...})
}),
appearance: new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
type: 'Color',
uniforms: {
color: Cesium.Color.BLUE
}
}
})
})
});
完整实例
const viewer = new Cesium.Viewer("cesiumContainer");
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(116.3, 39.9, 100000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-60),
roll: 0.0,
},
});
const positions = Cesium.Cartesian3.fromDegreesArray([
117.3,
38.9, // 北京大致位置
118.4,
37.9,
116.4,
36.8,
119.3,
39.8,
115.3,
37.9, // 闭合多边形
]);
// 2. 创建 GeometryInstance
const geometryInstance = new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(positions),
perPositionHeight: false, // 如果为 true,则 positions 中的每个点可以有不同的高度
vertexFormat: Cesium.VertexFormat.POSITION_AND_ST, // 用于纹理等,如果不需要可以简化
}),
});
// 3. 创建 Primitive 并添加到 Viewer 的 PrimitiveCollection 中
const primitive = new Cesium.Primitive({
geometryInstances: geometryInstance,
appearance: new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
type: "Color",
uniforms: {
color: Cesium.Color.BLUE,
},
},
}),
}),
});
viewer.scene.primitives.add(primitive);
2. 动态材质更新
// 使用CallbackProperty实现动态效果
const pulseMaterial = new Cesium.ColorMaterialProperty(
new Cesium.CallbackProperty(function(time) {
const t = Cesium.JulianDate.secondsDifference(time, startTime);
const pulse = 0.5 + 0.5 * Math.sin(t);
return Cesium.Color.RED.withAlpha(pulse);
}, false)
);
// 直接更新uniforms
customMaterial.uniforms.speed = 2.0;
三、内置材质类型详解
1. ColorMaterialProperty (纯色材质)
// 创建红色材质
const redMaterial = new Cesium.ColorMaterialProperty(
Cesium.Color.RED.withAlpha(0.8) // 带80%透明度
);
// 动态变色示例
const dynamicColor = new Cesium.ColorMaterialProperty(
new Cesium.CallbackProperty(function(time) {
return Cesium.Color.fromHsl(
Cesium.JulianDate.secondsDifference(time, startTime) * 0.1 % 1.0,
1.0, 0.5
);
}, false)
);
2. ImageMaterialProperty (图像材质)
const imageMaterial = new Cesium.ImageMaterialProperty({
image: 'textures/brick.jpg', // 图片路径/URL
repeat: new Cesium.Cartesian2(4, 4), // 横向和纵向重复次数
color: Cesium.Color.WHITE.withAlpha(0.9), // 颜色叠加
transparent: true // 启用透明度
});
// 动态切换纹理
imageMaterial.image = new Cesium.CallbackProperty(function(time) {
return time.getSeconds() % 2 === 0 ?
'textures/day.jpg' : 'textures/night.jpg';
}, false);
3. 图案材质组
(1) CheckerboardMaterialProperty (棋盘格)
const checkerboard = new Cesium.CheckerboardMaterialProperty({
evenColor: Cesium.Color.WHITE,
oddColor: Cesium.Color.BLACK,
repeat: new Cesium.Cartesian2(10, 10) // 10x10重复
});
(2) StripeMaterialProperty (条纹)
const stripeMaterial = new Cesium.StripeMaterialProperty({
orientation: Cesium.StripeOrientation.HORIZONTAL, // 或VERTICAL
evenColor: Cesium.Color.BLUE,
oddColor: Cesium.Color.CYAN,
repeat: 16, // 重复次数
orientation: Cesium.StripeOrientation.VERTICAL, // 方向
offset: 0.2 // 偏移量(0-1)
});
(3) GridMaterialProperty (网格)
const gridMaterial = new Cesium.GridMaterialProperty({
color: Cesium.Color.YELLOW,
cellAlpha: 0.1, // 单元格透明度
lineCount: new Cesium.Cartesian2(8, 8), // 行列数
lineThickness: new Cesium.Cartesian2(1.0, 1.0), // 线宽
lineOffset: new Cesium.Cartesian2(0.0, 0.0) // 偏移
});
4. 折线专用材质
(1) PolylineGlowMaterialProperty (发光折线)
const glowLine = new Cesium.PolylineGlowMaterialProperty({
color: Cesium.Color.BLUE,
glowPower: 0.3, // 发光强度(0-1)
taperPower: 0.5 // 锥度效果
});
(2) PolylineOutlineMaterialProperty (轮廓折线)
const outlineLine = new Cesium.PolylineOutlineMaterialProperty({
color: Cesium.Color.GREEN,
outlineWidth: 3, // 轮廓宽度(像素)
outlineColor: Cesium.Color.BLACK
});
(3) PolylineArrowMaterialProperty(折线箭头材质)
new Cesium.PolylineArrowMaterialProperty(Cesium.Color.PURPLE);
(4) PolylineDashMaterialProperty(折线虚线材质)
new Cesium.PolylineDashMaterialProperty({
color: Cesium.Color.CYAN,
dashLength: 16.0, // 虚线长度
dashPattern: 255 // 虚线模式(二进制)
})
四、高级材质技术
在 Cesium 1.95 中,创建自定义材质主要有两种方式:
1. 使用 Fabric 规范
const customMaterial1 = new Cesium.Material({
fabric: {
type: "Water",
uniforms: {
specularMap: "../images/earthspec1k.jpg",
normalMap: Cesium.buildModuleUrl("Assets/Textures/waterNormals.jpg"),
frequency: 10000.0,
animationSpeed: 0.01,
amplitude: 1.0,
},
},
});
const customMaterial2 = new Cesium.Material({
fabric: {
type: "Image",
uniforms: {
image: "/Cesium_Logo_Color.jpg",
},
},
});
2、使用 GLSL 着色器
var material = new Cesium.Material({
fabric: {
type: 'CustomShaderMaterial',
uniforms: {
texture: new Cesium.TextureUniform({
url: 'path/to/texture.jpg'
}),
time: 0.0
},
source: `
uniform sampler2D texture;
uniform float time;
void main() {
// 自定义着色器代码
vec2 st = czm_materialInput.st;
vec4 color = texture2D(texture, st);
gl_FragColor = color * abs(sin(time));
}
`
}
});
3. PBR材质配置
const pbrMaterial = new Cesium.Material({
fabric: {
type: 'PBR',
uniforms: {
baseColorTexture: 'textures/albedo.jpg',
normalTexture: 'textures/normal.jpg',
roughnessTexture: 'textures/roughness.jpg',
metallicTexture: 'textures/metallic.jpg',
ambientOcclusionTexture: 'textures/ao.jpg',
baseColorFactor: [1.0, 1.0, 1.0, 1.0],
metallicFactor: 0.5,
roughnessFactor: 0.3
}
}
});
4. 材质混合
const compositeMaterial = new Cesium.Material({
fabric: {
type: 'Composite',
materials: {
base: { type: 'Color', uniforms: { color: Cesium.Color.BLUE } },
overlay: { type: 'Image', uniforms: { image: 'textures/overlay.png' } }
},
components: {
diffuse: "mix(base.diffuse, overlay.diffuse, overlay.alpha)",
alpha: "base.alpha * overlay.alpha"
}
}
});
五、性能优化技巧
1、纹理优化:
// 使用压缩纹理
viewer.scene.primitives.add(
new Cesium.createTextureAtlas({
images: ['textures/atlas.png'],
context: viewer.scene.context,
pixelFormat: Cesium.PixelFormat.RGBA,
compression: Cesium.TextureCompression.WEBP // 或PVRTC
})
);
2、材质复用:
// 创建材质池
const materialCache = {};
function getMaterial(type, options) {
const key = JSON.stringify([type, options]);
if (!materialCache[key]) {
materialCache[key] = new Cesium[type + 'MaterialProperty'](options);
}
return materialCache[key];
}
3、动态更新策略:
// 使用requestAnimationFrame优化频繁更新
function updateMaterial() {
if (!viewer.scene.isDestroyed()) {
material.uniforms.time = Date.now() * 0.001;
Cesium.requestAnimationFrame(updateMaterial);
}
}
六、常见问题解决方案
1、材质不显示:
- 检查图片路径是否正确
- 验证颜色值是否有效(0-255或0-1范围)
- 确认实体或图元的show属性为true
2、性能问题:
// 诊断材质性能
viewer.scene.debugShowFramesPerSecond = true;
Cesium.Material._materialCache.count; // 查看材质缓存数量
3、移动端适配:
// 根据设备能力降级材质
const useSimpleMaterial = !Cesium.FeatureDetection.supportsWebGL2(viewer.scene.context);
entity.material = useSimpleMaterial ? simpleMaterial : advancedMaterial;
七、最佳实践总结
材质设计原则:
- 重用材质:尽可能重用材质实例而不是频繁创建新实例
- 优化uniform更新:避免每帧更新所有uniform
- 使用内置函数:优先使用Cesium提供的GLSL函数
- 测试性能:复杂材质可能影响性能,需进行性能测试
性能黄金法则:
// 批处理相似材质
const batchTable = new Cesium.BatchTable();
batchTable.addTexture('diffuse', texture1);
batchTable.addTexture('normal', texture2);
// 使用实例化渲染
const instances = new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
},
id: 'instance1'
});
内存管理:
// 及时释放资源
viewer.scene.primitives.remove(primitive);
material.destroy();
texture.destroy();
// 监控内存使用
Cesium.MemoryTracker.getStatistics();
Cesium 1.95的材质系统通过这套完整的工具链,可以构建从简单可视化到影视级渲染的各种效果。掌握这些技术后,您将能够创建出既美观又高性能的3D地理应用。