在使用 Cesium 进行三维可视化开发时,我们经常会接触到 Entity
和 Primitive
两套 API。很多初学者会疑惑:为什么 Cesium 会存在两套体系?Primitive
到底是什么?为什么有时候性能调优需要转向 Primitive
层?
本文将深入介绍 Primitive 的概念、原理、与 Entity 的关系、典型应用场景,以及如何利用 Primitive 提升性能。
- Entity vs Primitive:两套 API 的区别
在 Cesium 中,有两种核心的绘制方式:
-
Entity API
- 面向开发者的高级抽象
- 开发成本低,上手快
- 内置了时间动态性(如
SampledPositionProperty
) - 常用于数据可视化、快速开发场景
-
Primitive API
- 面向底层渲染引擎的抽象
- 更贴近 WebGL,对 GPU 渲染效率更高
- 缺乏高级封装,需要更多手动管理
- 常用于海量数据、性能敏感的场景
可以简单理解:Entity 就是 Vue/React 这样的高级框架,而 Primitive 更像是直接操作 DOM/Canvas。
- Primitive 的本质 在 Cesium 中,Primitive 表示可被渲染的图元(几何体 + 外观) 。
其核心由三部分组成:
-
Geometry:几何数据(顶点、索引)
- 例如
BoxGeometry
,PolygonGeometry
,PolylineGeometry
- 例如
-
Appearance:外观着色(shader)
- 例如
MaterialAppearance
,PerInstanceColorAppearance
- 例如
-
Primitive:将几何体与外观组合,最终交给 GPU 渲染
代码示意:
js
const instance = new Cesium.GeometryInstance({
geometry: Cesium.BoxGeometry.fromDimensions({
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL,
dimensions: new Cesium.Cartesian3(100000.0, 100000.0, 100000.0),
}),
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1000)
),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED),
}
});
const primitive = new Cesium.Primitive({
geometryInstances: instance,
appearance: new Cesium.PerInstanceColorAppearance({
closed: true
}),
});
viewer.scene.primitives.add(primitive);
在这段代码中:
-
GeometryInstance
定义了几何体及其位置 -
Appearance
定义了材质、着色方式 -
Primitive
把二者组合,交给 GPU 渲染
- 为什么选择 Primitive?
3.1 性能优势
-
Entity 在内部会转换成 Primitive
-
当数据量非常大(比如百万点云、上万条线)时,Entity 的封装开销会显著
-
直接使用 Primitive,可以减少中间层,提高渲染效率
3.2 灵活性
-
你可以完全掌控 Geometry 和 Shader
-
能实现自定义渲染效果,比如特殊着色器、批量实例化
3.3 内存控制
-
Entity 自动管理内存,但不够精细
-
Primitive 可以手动 add/remove,便于大规模数据流式加载
- Primitive 的典型应用场景
-
海量点/线/面渲染
- 如轨迹线、道路网、点云数据
- Entity 可能导致卡顿,而 Primitive 能批量实例化
-
高性能可视化
- 例如实时监控场景,需要快速更新数据
-
自定义着色
- 需要编写 GLSL shader,实现特殊材质或动态效果
- Primitive 与 GroundPrimitive
除了常规的 Primitive
,Cesium 还提供了 GroundPrimitive
,它可以让几何体直接贴地。
示例:
js
const rectangle = new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(110.0, 20.0, 120.0, 30.0),
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
});
const instance = new Cesium.GeometryInstance({
geometry: rectangle,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE.withAlpha(0.5)),
}
});
const groundPrimitive = new Cesium.GroundPrimitive({
geometryInstances: instance
});
viewer.scene.primitives.add(groundPrimitive);
- 性能优化建议
-
批量实例化 :尽量用
GeometryInstance[]
一次性传入多个对象 -
减少动态更新 :Primitive 一旦创建就固定,频繁更新建议使用
PrimitiveCollection
重新构建 -
分块加载:对于海量数据,分区分层加载,避免一次性渲染过多
-
合理选择 Appearance:避免使用复杂的 Shader,尽量利用 GPU 批处理
- 总结
-
Entity 简单易用,适合快速开发
-
Primitive 性能更优,适合海量数据和自定义渲染
-
掌握 Primitive,是进阶 Cesium 开发不可或缺的一步
如果你开发的属于是大型三维可视化项目的话,建议在理解 Entity 的同时,逐步过渡到 Primitive 的使用,渲染性能可能会更好。