Primitive
primitive主要由两部分组成:Geometry
(几何结构) 和 Appearance
(着色,包括GLSL顶点着色器、片段着色器和渲染状态)
面向图形开发人员的底层 API,暴露最小限度的抽象,更多使用图形学术语,具有更大的灵活性。
图元(Primitive)代表场景中的几何体。 几何可以来自单个
GeometryInstance
,也可以来自实例数组,即 geometry 来自不同的几何类型。图元将 geometry 实例与描述完整着色的 appearance 相结合,包括 Material 和 RenderState。 粗略地说,geometry 实例定义了结构和位置,appearance 定义了视觉特征。 解耦 geometry 和 appearance,允许我们混合和匹配它们中的大部分,并相互独立地添加新的 geometry 或 appearance 。将多个实例组合成一个原语称为批处理,可显着提高静态数据的性能。 实例可以单独挑选,
Scene#pick
返回它们的GeometryInstance#id
。使用PerInstanceColorAppearance
设定实例的外观,每个实例可以具有唯一的颜色。
Geometry
可以在 web worker 或主线程上创建和批处理。
其具有以下优势:
- 性能:绘制大量 Primitive 时,可以将其合并为单个
Geometry
,减轻 CPU 负担,更好使用 GPU。 - 灵活:
Geometry
和Appearance
解耦,两者可独立修改。
我们可以通过Primitive API来操控几何图形及其外观,绘制各种形状。
var instance = new Cesium.GeometryInstance({
geometry : new Cesium.EllipseGeometry({
center : Cesium.Cartesian3.fromDegrees(-100.0, 20.0),
semiMinorAxis : 500000.0,
semiMajorAxis : 1000000.0,
rotation : Cesium.Math.PI_OVER_FOUR,
vertexFormat : Cesium.VertexFormat.POSITION_AND_ST
}),
id : 'object returned when this instance is picked and to get/set per-instance attributes'
});
scene.primitives.add(new Cesium.Primitive({
geometryInstances : instance,
appearance : new Cesium.EllipsoidSurfaceAppearance({
material : Cesium.Material.fromType('Checkerboard')
})
}));
Geometry
在Cesium中,支持以下几种Geometry几何图形
几何图形 | 说明 |
---|---|
BoxGeometry | 立方体 |
BoxOutlineGeometry | 仅有轮廓的立方体,只有外部线条的的盒子 |
CircleGeometry | 圆形或者拉伸的圆形,圆圈或挤压圆 |
CircleOutlineGeometry | 只有轮廓的圆形 |
CorridorGeometry | 走廊:沿着地表的多段线 (垂直于表面的折线),且具有一定的宽度,可以拉伸到一定的高度 |
CorridorOutlineGeometry | 只有轮廓的走廊 |
CylinderGeometry | 圆柱、圆锥或者截断的圆锥 |
CylinderOutlineGeometry | 只有轮廓的圆柱、圆锥或者截断的圆锥 |
EllipseGeometry | 椭圆或者拉伸的椭圆 |
EllipseOutlineGeometry | 只有轮廓的椭圆或者拉伸的椭圆 |
EllipsoidGeometry | 椭球体 |
EllipsoidOutlineGeometry | 只有轮廓的椭球体 |
RectangleGeometry | 矩形或者拉伸的矩形 |
RectangleOutlineGeometry | 只有轮廓的矩形或者拉伸的矩形 |
PolygonGeometry | 多边形,可以具有空洞或者拉伸一定的高度 |
PolygonOutlineGeometry | 只有轮廓的多边形 |
PolylineGeometry | 多段线,可以具有一定的宽度 |
SimplePolylineGeometry | 简单的多段线 |
PolylineVolumeGeometry | 多段线柱体 |
PolylineVolumeOutlineGeometry | 只有轮廓的多段线柱体 |
SphereGeometry | 球体 |
SphereOutlineGeometry | 只有轮廓的球体 |
WallGeometry | 墙 |
WallOutlineGeometry | 只有轮廓的墙 |
Geometry Instances - 几何图形实例
在前边的示例代码中,我们已经用到了它,它相当于 Geometry 的容器,而多个 Instance 可以公用一个 Geomotry 并利用GeometryInstance.modelMatrix
提供多种属性信息。
var geometry = Cesium.BoxGeometry.fromDimensions({
vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL,
dimensions : new Cesium.Cartesian3(1000000.0, 1000000.0, 500000.0)
});
var instanceBottom = new Cesium.GeometryInstance({
geometry : geometry,
modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)
},
id : 'bottom'
});
var instanceTop = new Cesium.GeometryInstance({
geometry : geometry,
modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 3000000.0), new Cesium.Matrix4()),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)
},
id : 'top'
});
Combing Geometries - 合并几何图形
我们可以合并多个 Instance 为一个 Primitive,提高我们的性能。
var instances = [Instance1, Instance2, Instance3, ……];
scene.primitives.add( new Cesium.Primitive( {
geometryInstances : instances, //合并
//某些外观允许每个几何图形实例分别指定某个属性,例如:
appearance : new Cesium.PerInstanceColorAppearance({translucent : false,closed : true})
} ) );
更新单个 Instance 属性
在添加到 Primitive 后,我们仍然可以通过 Id 获取指定 Instance 并修改其属性。
var circleInstance = new Cesium.GeometryInstance( {
geometry : new Cesium.CircleGeometry( {
center : Cesium.Cartesian3.fromDegrees( -95.0, 43.0 ),
radius : 250000.0,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
} ),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor( new Cesium.Color( 1.0, 0.0, 0.0, 0.5 ) ),
show : new Cesium.ShowGeometryInstanceAttribute( true ) //显示或者隐藏
},
id : 'circle'
} );
var primitive = new Cesium.Primitive( {
geometryInstances : circleInstance,
appearance : new Cesium.PerInstanceColorAppearance( {
translucent : false,
closed : true
} )
} );
scene.primitives.add( primitive );
var attributes = primitive.getGeometryInstanceAttributes( 'circle' );//获取某个实例的属性集
attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue( Cesium.Color.fromRandom( {
alpha : 1.0
} ) );
Appearance
Cesium 支持以下列出的 Appearance
外观 | 描述 |
---|---|
MaterialAppearance | 支持各种 Geometry 类型的外观,支持使用材质来定义着色。支持材料描述阴影。 |
EllipsoidSurfaceAppearance | MaterialAppearance 的一个版本。假设几何图形与地表是平行的,并且依此来进行顶点属性(vertex attributes)的计算。和 Material Appearance 一样,就像一个多边形,并且使用这个假设来通过程序上计算许多顶点属性来节省内存。 |
PerInstanceColorAppearance | 让每个实例使用自定义的颜色来着色,使用每个实例的颜色来遮蔽每个实例。 |
PolylineMaterialAppearance | 支持使用材质来着色多段线。支持材料遮蔽 Polyline。 |
PolylineColorAppearance | 使用每顶点或者每片段(per-vertex or per-segment )的颜色来着色多段线—使用每顶点或每段着色来遮蔽折线 |
Appearance 定义了需要在 GPU 上执行的 GLSL 着色器,这部分一般只有在自定义外观时需要修改。
render state
用来在绘制 Primitive 的时候控制 GPU 状态,一旦外观被创建,render state
就不能再改变了,但是我们可以修改其材质。
//下面的外观可用于定义一个Viewer不可进入的不透明盒子
var appearance = new Cesium.PerInstanceColorAppearance( {
translucent : false,
closed : true
} );
//下面的代码效果同上
var translucent = new Cesium.PerInstanceColorAppearance( {
renderState : {
depthTest : {
enabled : true
},
cull : {
enabled : true,
face : Cesium.CullFace.BACK
}
}
} );
Primitive 与 Entity 对比
看过上边对 Primitive 相关接口的用法,我们会有这样的疑惑:entity 调用方便,封装完美,为什么还要使用 Primitive?区别就是加载的效率问题。Primitve 更接近 webGL 的底层,没有 entity 一样的附加属性,加载时效率会更高。