Cesium的Primitive API 是直接对接WebGL的底层渲染接口,是实现极致性能与高度定制化三维场景的核心工具。与高层的Entity API不同,Primitive需要开发者手动管理顶点数据、材质、变换矩阵等WebGL资源,但其批处理能力、自定义着色器支持和内存可控性使其成为大规模数据渲染、特殊视觉效果开发的首选。以下从核心概念、创建流程、常用类型、高级技巧、交互与优化五大模块详细讲解Primitive API的常用方法与实战场景。
一、Primitive核心概念与定位
1. 本质:WebGL渲染的最小单元
Primitive对应WebGL中的绘制调用(Draw Call),包含三个核心组成部分:
- GeometryInstance:几何数据容器,存储顶点、索引、实例化属性(如每个实例的颜色)
- Appearance:渲染状态容器,定义材质、着色器、深度测试/裁剪等WebGL状态
- Primitive:将GeometryInstance与Appearance绑定,最终提交给WebGL渲染的单元
2. 核心优势
- 极致性能:通过批处理将数千个几何合并为一个WebGL绘制调用,性能比Entity提升5-10倍
- 高度定制:支持自定义GLSL着色器、顶点属性、WebGL扩展
- 内存可控:手动管理资源生命周期,避免Entity自动封装带来的内存开销
- 贴地渲染:支持GroundPrimitive直接贴合地形,无需额外处理
二、Primitive基本创建流程
1. 步骤1:创建GeometryInstance(几何数据)
GeometryInstance是几何数据的载体,可包含单个或多个几何实例,支持实例化属性(如每个实例的颜色)。
常用几何类型
| 几何类型 | 适用场景 | 核心参数 |
|---|---|---|
SphereGeometry |
球体(如传感器、地标) | radius、vertexFormat |
BoxGeometry |
立方体(如建筑、设备) | minimum/maximum(顶点范围) |
CylinderGeometry |
圆柱体(如杆塔、管道) | length、topRadius、bottomRadius |
PolygonGeometry |
多边形(如区域、地块) | polygonHierarchy(顶点数组) |
PointsGeometry |
点集(如点云、轨迹点) | positions(顶点数组) |
PolylineGeometry |
折线(如航线、管线) | positions(顶点数组) |
代码示例:创建单个几何实例
javascript
// 创建球体几何实例
const sphereInstance = new Cesium.GeometryInstance({
geometry: new Cesium.SphereGeometry({
radius: 1000, // 半径(米)
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL // 顶点属性:位置+法线
}),
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.4, 39.9, 5000) // 几何位置
),
id: "sensor-sphere", // 实例ID,用于拾取交互
attributes: {
// 实例化属性:每个实例的颜色
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
}
});
代码示例:批量创建几何实例
javascript
const instances = [];
// 生成1000个随机位置的立方体
for (let i = 0; i < 1000; i++) {
const position = Cesium.Cartesian3.fromDegrees(
116.4 + Math.random() * 0.1,
39.9 + Math.random() * 0.1,
1000 + Math.random() * 500
);
instances.push(new Cesium.GeometryInstance({
geometry: new Cesium.BoxGeometry({
minimum: new Cesium.Cartesian3(-50, -50, -50),
maximum: new Cesium.Cartesian3(50, 50, 50),
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL
}),
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
id: `building-${i}`,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.fromRandom({ alpha: 0.8 })
)
}
}));
}
2. 步骤2:创建Appearance(渲染状态)
Appearance定义了几何的渲染方式,包括材质、着色器、深度测试等WebGL状态。Cesium提供了多种内置Appearance,也支持自定义着色器。
常用内置Appearance类型
| Appearance类型 | 适用场景 | 核心特性 |
|---|---|---|
MaterialAppearance |
通用材质渲染 | 支持Cesium内置材质(如发光、纹理),适合大多数场景 |
PerInstanceColorAppearance |
多实例不同颜色 | 支持每个GeometryInstance使用独立颜色,适合批处理场景 |
EllipsoidSurfaceAppearance |
贴地几何 | 专门用于GroundPrimitive,自动贴合地形曲面 |
PointsMaterialAppearance |
点渲染 | 用于PointsGeometry,支持点大小、颜色配置 |
PolylineMaterialAppearance |
折线渲染 | 用于PolylineGeometry,支持线宽、发光材质 |
代码示例:创建Appearance
javascript
// 1. 通用材质Appearance(支持内置材质)
const materialAppearance = new Cesium.MaterialAppearance({
material: new Cesium.PolylineGlowMaterialProperty({ // 发光材质
glowPower: 0.3,
color: Cesium.Color.BLUE
}),
translucent: true, // 开启半透明
closed: true // 封闭几何(如球体、立方体),优化渲染
});
// 2. 实例化颜色Appearance(批处理场景)
const perInstanceAppearance = new Cesium.PerInstanceColorAppearance({
translucent: false,
closed: true,
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL
});
3. 步骤3:创建Primitive并添加到场景
将GeometryInstance与Appearance绑定为Primitive,最终添加到viewer.scene.primitives中渲染。
代码示例:单个Primitive
javascript
const spherePrimitive = new Cesium.Primitive({
geometryInstances: sphereInstance,
appearance: materialAppearance,
asynchronous: false, // 同步加载(适合小模型,大模型建议异步)
show: true // 是否可见
});
viewer.scene.primitives.add(spherePrimitive);
代码示例:批处理Primitive(核心性能优化)
通过BatchedPrimitive将多个GeometryInstance合并为一个WebGL绘制调用,是大规模数据渲染的关键:
javascript
const batchedPrimitive = new Cesium.BatchedPrimitive({
geometryInstances: instances, // 批量几何实例数组
appearance: perInstanceAppearance,
asynchronous: true // 异步加载,避免阻塞主线程
});
viewer.scene.primitives.add(batchedPrimitive);
三、常用Primitive类型与方法
1. 基础Primitive:通用几何渲染
javascript
// 创建并添加Primitive
const primitive = new Cesium.Primitive({
geometryInstances: instance,
appearance: appearance,
modelMatrix: Cesium.Matrix4.IDENTITY, // 初始变换矩阵(单位矩阵)
cullFace: Cesium.CullFace.BACK, // 背面裁剪,优化性能
depthTest: true // 开启深度测试,避免遮挡错误
});
// 常用方法
primitive.show = false; // 隐藏Primitive
primitive.modelMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(1000, 0, 0)); // 平移1000米
primitive.destroy(); // 释放WebGL资源(必须手动调用,避免内存泄漏)
2. GroundPrimitive:贴地几何渲染
专门用于贴合地形的多边形、折线,无需手动处理地形高度:
javascript
const groundPrimitive = new Cesium.GroundPrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: Cesium.Cartesian3.fromDegreesArray([
116.4, 39.9,
116.401, 39.9,
116.401, 39.901,
116.4, 39.901
]),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GREEN.withAlpha(0.5))
}
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
translucent: true
})
});
viewer.scene.primitives.add(groundPrimitive);
3. PointsPrimitive:大规模点云渲染
优化后的点渲染Primitive,适合点云、轨迹点等大规模点数据:
javascript
const pointsPrimitive = new Cesium.PointsPrimitive({
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
116.4, 39.9, 1000,
116.401, 39.9, 1200,
116.402, 39.9, 1500,
// 支持数千/数万个点
]),
pointSize: 5, // 点大小(像素)
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 1, // 点边框宽度
disableDepthTestDistance: Number.POSITIVE_INFINITY // 始终显示在最上层
});
viewer.scene.primitives.add(pointsPrimitive);
4. PolylinePrimitive:高性能折线渲染
专门用于折线的Primitive,支持批处理和复杂材质:
javascript
const polylinePrimitive = new Cesium.PolylinePrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray([
116.4, 39.9,
116.5, 40.0,
116.6, 39.95
]),
width: 5, // 线宽(像素)
vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT
})
}),
appearance: new Cesium.PolylineMaterialAppearance({
material: new Cesium.PolylineArrowMaterialProperty({ // 箭头材质
color: Cesium.Color.RED
})
})
});
viewer.scene.primitives.add(polylinePrimitive);
四、高级技巧:自定义着色器与变换
1. 自定义GLSL着色器(核心定制能力)
通过Cesium.Material自定义GLSL着色器,实现特殊视觉效果(如动态纹理、热图、伪3D效果)。
代码示例:动态颜色变换着色器
javascript
// 自定义Material,包含动态时间uniform
const customMaterial = new Cesium.Material({
fabric: {
type: 'DynamicColor',
uniforms: {
time: 0.0,
baseColor: Cesium.Color.RED
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
// 随时间动态改变颜色亮度
float t = uniforms.time;
vec3 dynamicColor = uniforms.baseColor.rgb * (sin(t * 2.0) * 0.5 + 0.5);
material.diffuse = dynamicColor;
material.alpha = 0.7;
return material;
}
`
}
});
// 每一帧更新时间uniform
viewer.scene.postRender.addEventListener(() => {
customMaterial.uniforms.time = viewer.clock.currentTime.secondsOfDay;
});
// 应用到Primitive
const primitive = new Cesium.Primitive({
geometryInstances: instance,
appearance: new Cesium.MaterialAppearance({ material: customMaterial })
});
2. 变换矩阵:位置/旋转/缩放控制
通过modelMatrix手动控制Primitive的空间变换,比Entity的position更灵活:
javascript
// 1. 平移:向东偏移1000米
const translationMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(1000, 0, 0));
primitive.modelMatrix = translationMatrix;
// 2. 旋转+缩放:绕Z轴旋转45度,缩放2倍
const rotationMatrix = Cesium.Matrix4.fromRotationZ(Cesium.Math.toRadians(45));
const scaleMatrix = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(2, 2, 2));
primitive.modelMatrix = Cesium.Matrix4.multiply(rotationMatrix, scaleMatrix, new Cesium.Matrix4());
// 3. 组合变换:位置+旋转+缩放
const position = Cesium.Cartesian3.fromDegrees(116.4, 39.9, 1000);
const hpr = new Cesium.HeadingPitchRoll(0, Cesium.Math.toRadians(10), 0); // 俯仰10度
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
const combinedMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
position,
orientation,
new Cesium.Cartesian3(2, 2, 2)
);
primitive.modelMatrix = combinedMatrix;
五、Primitive交互与拾取
Primitive没有Entity的内置事件,需通过viewer.scene.pick手动实现交互:
代码示例:鼠标拾取Primitive实例
javascript
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((event) => {
// 拾取点击位置的Primitive实例
const pickResult = viewer.scene.pick(event.position);
if (Cesium.defined(pickResult) && Cesium.defined(pickResult.id)) {
const instanceId = pickResult.id;
console.log("点击了Primitive实例:", instanceId);
// 实现高亮效果:创建临时Primitive覆盖原实例
const highlightInstance = new Cesium.GeometryInstance({
geometry: pickResult.geometry,
modelMatrix: pickResult.modelMatrix,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW)
}
});
const highlightPrimitive = new Cesium.Primitive({
geometryInstances: highlightInstance,
appearance: new Cesium.PerInstanceColorAppearance()
});
viewer.scene.primitives.add(highlightPrimitive);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
六、资源管理与性能优化
1. 资源释放(关键:避免内存泄漏)
Primitive包含WebGL资源(顶点缓冲、着色器程序),必须手动释放:
javascript
// 方式1:从场景移除并销毁
viewer.scene.primitives.remove(primitive);
primitive.destroy(); // 释放WebGL资源
primitive = null; // 解除引用,帮助垃圾回收
// 方式2:批量销毁所有Primitive
viewer.scene.primitives.removeAll();
viewer.scene.primitives.forEach(p => p.destroy());
2. 性能优化技巧
- 批处理优先 :尽可能使用
BatchedPrimitive合并相同类型的几何,减少WebGL绘制调用 - 异步加载 :大规模数据设置
asynchronous: true,避免阻塞主线程 - 实例化属性 :使用
PerInstanceColorAppearance实现多实例不同样式,避免创建多个Primitive - 裁剪与遮挡 :开启
cullFace: Cesium.CullFace.BACK背面裁剪,减少不必要的渲染 - LOD优化 :为Geometry设置
levelOfDetail,根据相机距离切换不同精度的几何 - 内存控制:避免创建过多未使用的Primitive,及时dispose不再需要的资源
七、Primitive适用场景总结
| 场景 | 选择Primitive的原因 |
|---|---|
| 大规模数据渲染(>10000个几何) | 批处理能力将绘制调用从数千个减少到1个,性能提升数量级 |
| 自定义视觉效果(如热图、动态纹理) | 支持自定义GLSL着色器,实现Entity无法完成的特殊效果 |
| 性能敏感场景(如无人机实时数据可视化) | 内存可控,无Entity的抽象层开销,帧率更稳定 |
| 贴地复杂几何 | GroundPrimitive自动贴合地形,无需手动处理地形高度 |
八、开发注意事项
- WebGL基础要求:使用Primitive需熟悉WebGL的顶点缓冲、着色器、绘制调用等概念
- 资源生命周期 :必须手动调用
destroy()释放WebGL资源,否则会导致内存泄漏 - 异步加载 :大规模数据必须开启
asynchronous: true,避免页面卡顿 - 实例化属性限制 :
PerInstanceColorAppearance仅支持Cesium的Primitive API 是直接对接WebGL的底层渲染接口,是实现极致性能与高度定制化三维场景的核心工具。与高层的Entity API不同,Primitive需要开发者手动管理顶点数据、材质、变换矩阵等WebGL资源,但其批处理能力、自定义着色器支持和内存可控性使其成为大规模数据渲染、特殊视觉效果开发的首选。以下从核心概念、创建流程、常用类型、高级技巧、交互与优化五大模块详细讲解Primitive API的常用方法与实战场景。
一、Primitive核心概念与定位
1. 本质:WebGL渲染的最小单元
Primitive对应WebGL中的绘制调用(Draw Call),包含三个核心组成部分:
- GeometryInstance:几何数据容器,存储顶点、索引、实例化属性(如每个实例的颜色)
- Appearance:渲染状态容器,定义材质、着色器、深度测试/裁剪等WebGL状态
- Primitive:将GeometryInstance与Appearance绑定,最终提交给WebGL渲染的单元
2. 核心优势
- 极致性能:通过批处理将数千个几何合并为一个WebGL绘制调用,性能比Entity提升5-10倍
- 高度定制:支持自定义GLSL着色器、顶点属性、WebGL扩展
- 内存可控:手动管理资源生命周期,避免Entity自动封装带来的内存开销
- 贴地渲染:支持GroundPrimitive直接贴合地形,无需额外处理
二、Primitive基本创建流程
1. 步骤1:创建GeometryInstance(几何数据)
GeometryInstance是几何数据的载体,可包含单个或多个几何实例,支持实例化属性(如每个实例的颜色)。
常用几何类型
| 几何类型 | 适用场景 | 核心参数 |
|---|---|---|
SphereGeometry |
球体(如传感器、地标) | radius、vertexFormat |
BoxGeometry |
立方体(如建筑、设备) | minimum/maximum(顶点范围) |
CylinderGeometry |
圆柱体(如杆塔、管道) | length、topRadius、bottomRadius |
PolygonGeometry |
多边形(如区域、地块) | polygonHierarchy(顶点数组) |
PointsGeometry |
点集(如点云、轨迹点) | positions(顶点数组) |
PolylineGeometry |
折线(如航线、管线) | positions(顶点数组) |
代码示例:创建单个几何实例
javascript
// 创建球体几何实例
const sphereInstance = new Cesium.GeometryInstance({
geometry: new Cesium.SphereGeometry({
radius: 1000, // 半径(米)
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL // 顶点属性:位置+法线
}),
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.4, 39.9, 5000) // 几何位置
),
id: "sensor-sphere", // 实例ID,用于拾取交互
attributes: {
// 实例化属性:每个实例的颜色
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
}
});
代码示例:批量创建几何实例
javascript
const instances = [];
// 生成1000个随机位置的立方体
for (let i = 0; i < 1000; i++) {
const position = Cesium.Cartesian3.fromDegrees(
116.4 + Math.random() * 0.1,
39.9 + Math.random() * 0.1,
1000 + Math.random() * 500
);
instances.push(new Cesium.GeometryInstance({
geometry: new Cesium.BoxGeometry({
minimum: new Cesium.Cartesian3(-50, -50, -50),
maximum: new Cesium.Cartesian3(50, 50, 50),
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL
}),
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
id: `building-${i}`,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
Cesium.Color.fromRandom({ alpha: 0.8 })
)
}
}));
}
2. 步骤2:创建Appearance(渲染状态)
Appearance定义了几何的渲染方式,包括材质、着色器、深度测试等WebGL状态。Cesium提供了多种内置Appearance,也支持自定义着色器。
常用内置Appearance类型
| Appearance类型 | 适用场景 | 核心特性 |
|---|---|---|
MaterialAppearance |
通用材质渲染 | 支持Cesium内置材质(如发光、纹理),适合大多数场景 |
PerInstanceColorAppearance |
多实例不同颜色 | 支持每个GeometryInstance使用独立颜色,适合批处理场景 |
EllipsoidSurfaceAppearance |
贴地几何 | 专门用于GroundPrimitive,自动贴合地形曲面 |
PointsMaterialAppearance |
点渲染 | 用于PointsGeometry,支持点大小、颜色配置 |
PolylineMaterialAppearance |
折线渲染 | 用于PolylineGeometry,支持线宽、发光材质 |
代码示例:创建Appearance
javascript
// 1. 通用材质Appearance(支持内置材质)
const materialAppearance = new Cesium.MaterialAppearance({
material: new Cesium.PolylineGlowMaterialProperty({ // 发光材质
glowPower: 0.3,
color: Cesium.Color.BLUE
}),
translucent: true, // 开启半透明
closed: true // 封闭几何(如球体、立方体),优化渲染
});
// 2. 实例化颜色Appearance(批处理场景)
const perInstanceAppearance = new Cesium.PerInstanceColorAppearance({
translucent: false,
closed: true,
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL
});
3. 步骤3:创建Primitive并添加到场景
将GeometryInstance与Appearance绑定为Primitive,最终添加到viewer.scene.primitives中渲染。
代码示例:单个Primitive
javascript
const spherePrimitive = new Cesium.Primitive({
geometryInstances: sphereInstance,
appearance: materialAppearance,
asynchronous: false, // 同步加载(适合小模型,大模型建议异步)
show: true // 是否可见
});
viewer.scene.primitives.add(spherePrimitive);
代码示例:批处理Primitive(核心性能优化)
通过BatchedPrimitive将多个GeometryInstance合并为一个WebGL绘制调用,是大规模数据渲染的关键:
javascript
const batchedPrimitive = new Cesium.BatchedPrimitive({
geometryInstances: instances, // 批量几何实例数组
appearance: perInstanceAppearance,
asynchronous: true // 异步加载,避免阻塞主线程
});
viewer.scene.primitives.add(batchedPrimitive);
三、常用Primitive类型与方法
1. 基础Primitive:通用几何渲染
javascript
// 创建并添加Primitive
const primitive = new Cesium.Primitive({
geometryInstances: instance,
appearance: appearance,
modelMatrix: Cesium.Matrix4.IDENTITY, // 初始变换矩阵(单位矩阵)
cullFace: Cesium.CullFace.BACK, // 背面裁剪,优化性能
depthTest: true // 开启深度测试,避免遮挡错误
});
// 常用方法
primitive.show = false; // 隐藏Primitive
primitive.modelMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(1000, 0, 0)); // 平移1000米
primitive.destroy(); // 释放WebGL资源(必须手动调用,避免内存泄漏)
2. GroundPrimitive:贴地几何渲染
专门用于贴合地形的多边形、折线,无需手动处理地形高度:
javascript
const groundPrimitive = new Cesium.GroundPrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: Cesium.Cartesian3.fromDegreesArray([
116.4, 39.9,
116.401, 39.9,
116.401, 39.901,
116.4, 39.901
]),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GREEN.withAlpha(0.5))
}
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
translucent: true
})
});
viewer.scene.primitives.add(groundPrimitive);
3. PointsPrimitive:大规模点云渲染
优化后的点渲染Primitive,适合点云、轨迹点等大规模点数据:
javascript
const pointsPrimitive = new Cesium.PointsPrimitive({
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
116.4, 39.9, 1000,
116.401, 39.9, 1200,
116.402, 39.9, 1500,
// 支持数千/数万个点
]),
pointSize: 5, // 点大小(像素)
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 1, // 点边框宽度
disableDepthTestDistance: Number.POSITIVE_INFINITY // 始终显示在最上层
});
viewer.scene.primitives.add(pointsPrimitive);
4. PolylinePrimitive:高性能折线渲染
专门用于折线的Primitive,支持批处理和复杂材质:
javascript
const polylinePrimitive = new Cesium.PolylinePrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray([
116.4, 39.9,
116.5, 40.0,
116.6, 39.95
]),
width: 5, // 线宽(像素)
vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT
})
}),
appearance: new Cesium.PolylineMaterialAppearance({
material: new Cesium.PolylineArrowMaterialProperty({ // 箭头材质
color: Cesium.Color.RED
})
})
});
viewer.scene.primitives.add(polylinePrimitive);
四、高级技巧:自定义着色器与变换
1. 自定义GLSL着色器(核心定制能力)
通过Cesium.Material自定义GLSL着色器,实现特殊视觉效果(如动态纹理、热图、伪3D效果)。
代码示例:动态颜色变换着色器
javascript
// 自定义Material,包含动态时间uniform
const customMaterial = new Cesium.Material({
fabric: {
type: 'DynamicColor',
uniforms: {
time: 0.0,
baseColor: Cesium.Color.RED
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
// 随时间动态改变颜色亮度
float t = uniforms.time;
vec3 dynamicColor = uniforms.baseColor.rgb * (sin(t * 2.0) * 0.5 + 0.5);
material.diffuse = dynamicColor;
material.alpha = 0.7;
return material;
}
`
}
});
// 每一帧更新时间uniform
viewer.scene.postRender.addEventListener(() => {
customMaterial.uniforms.time = viewer.clock.currentTime.secondsOfDay;
});
// 应用到Primitive
const primitive = new Cesium.Primitive({
geometryInstances: instance,
appearance: new Cesium.MaterialAppearance({ material: customMaterial })
});
2. 变换矩阵:位置/旋转/缩放控制
通过modelMatrix手动控制Primitive的空间变换,比Entity的position更灵活:
javascript
// 1. 平移:向东偏移1000米
const translationMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(1000, 0, 0));
primitive.modelMatrix = translationMatrix;
// 2. 旋转+缩放:绕Z轴旋转45度,缩放2倍
const rotationMatrix = Cesium.Matrix4.fromRotationZ(Cesium.Math.toRadians(45));
const scaleMatrix = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(2, 2, 2));
primitive.modelMatrix = Cesium.Matrix4.multiply(rotationMatrix, scaleMatrix, new Cesium.Matrix4());
// 3. 组合变换:位置+旋转+缩放
const position = Cesium.Cartesian3.fromDegrees(116.4, 39.9, 1000);
const hpr = new Cesium.HeadingPitchRoll(0, Cesium.Math.toRadians(10), 0); // 俯仰10度
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
const combinedMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
position,
orientation,
new Cesium.Cartesian3(2, 2, 2)
);
primitive.modelMatrix = combinedMatrix;
五、Primitive交互与拾取
Primitive没有Entity的内置事件,需通过viewer.scene.pick手动实现交互:
代码示例:鼠标拾取Primitive实例
javascript
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((event) => {
// 拾取点击位置的Primitive实例
const pickResult = viewer.scene.pick(event.position);
if (Cesium.defined(pickResult) && Cesium.defined(pickResult.id)) {
const instanceId = pickResult.id;
console.log("点击了Primitive实例:", instanceId);
// 实现高亮效果:创建临时Primitive覆盖原实例
const highlightInstance = new Cesium.GeometryInstance({
geometry: pickResult.geometry,
modelMatrix: pickResult.modelMatrix,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW)
}
});
const highlightPrimitive = new Cesium.Primitive({
geometryInstances: highlightInstance,
appearance: new Cesium.PerInstanceColorAppearance()
});
viewer.scene.primitives.add(highlightPrimitive);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
六、资源管理与性能优化
1. 资源释放(关键:避免内存泄漏)
Primitive包含WebGL资源(顶点缓冲、着色器程序),必须手动释放:
javascript
// 方式1:从场景移除并销毁
viewer.scene.primitives.remove(primitive);
primitive.destroy(); // 释放WebGL资源
primitive = null; // 解除引用,帮助垃圾回收
// 方式2:批量销毁所有Primitive
viewer.scene.primitives.removeAll();
viewer.scene.primitives.forEach(p => p.destroy());
2. 性能优化技巧
- 批处理优先 :尽可能使用
BatchedPrimitive合并相同类型的几何,减少WebGL绘制调用 - 异步加载 :大规模数据设置
asynchronous: true,避免阻塞主线程 - 实例化属性 :使用
PerInstanceColorAppearance实现多实例不同样式,避免创建多个Primitive - 裁剪与遮挡 :开启
cullFace: Cesium.CullFace.BACK背面裁剪,减少不必要的渲染 - LOD优化 :为Geometry设置
levelOfDetail,根据相机距离切换不同精度的几何 - 内存控制:避免创建过多未使用的Primitive,及时dispose不再需要的资源
七、Primitive适用场景总结
| 场景 | 选择Primitive的原因 |
|---|---|
| 大规模数据渲染(>10000个几何) | 批处理能力将绘制调用从数千个减少到1个,性能提升数量级 |
| 自定义视觉效果(如热图、动态纹理) | 支持自定义GLSL着色器,实现Entity无法完成的特殊效果 |
| 性能敏感场景(如无人机实时数据可视化) | 内存可控,无Entity的抽象层开销,帧率更稳定 |
| 贴地复杂几何 | GroundPrimitive自动贴合地形,无需手动处理地形高度 |
八、开发注意事项
- WebGL基础要求:使用Primitive需熟悉WebGL的顶点缓冲、着色器、绘制调用等概念
- 资源生命周期 :必须手动调用
destroy()释放WebGL资源,否则会导致内存泄漏 - 异步加载 :大规模数据必须开启
asynchronous: true,避免页面卡顿 - 实例化属性限制 :
PerInstanceColorAppearance仅支持