SuperMap iClient3D for WebGL教程 Primitive
WuYK
在Webgl中,实体对象主要由两大类组成,一类是Entity对象,还有一类就是Primitive对象。那么有同学就要问,他们有啥区别呢?
先说说Primitive,Primitive是面向图形开发人员的底层API,该API暴露最小限度的抽象,使用图形学术语,具有很大的灵活性,性能很高,需要具有图形学编程的知识。再说说Entity,Entity为高级别的数据驱动的API,称为“Entity API”。该API使用一致性设计的、高级别的对象来管理一组相关性的可视化对象,其底层使用Primitive API。
一句话概括,Primitive是Entity的起源,当需要同时展示很多几何体时,则用Primitive的渲染效率远远大于Entity。
Webgl如何加载Primitive
下面是Primitive的加载代码:
var instance = new Cesium.GeometryInstance({
geometry: new Cesium.CircleGeometry({
center : Cesium.Cartesian3.fromDegrees( -95.0, 43.0 ),
radius : 250000.0,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
});
viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: instance,
appearance: new Cesium.EllipsoidSurfaceAppearance({
material:Cesium.Material.fromType('Stripe')
})
}));
从上面代码我们可以看出,Primitive主要是由两大类组成,即geometry(几何体)和appearance(外观)。下面分开介绍这两部分。
一.Geometry
看下原版英文介绍
A geometry representation with attributes forming vertices and optional index data defining primitives. Geometries and an Appearance, which describes the shading, can be assigned to a Primitive for visualization. A Primitive can be created from many heterogeneous - in many cases - geometries for performance.
翻译大概是。。 表示具有顶点属性和定义图元的可选取索引数据的几何图形,可以将描述阴影的几何图形和外观分配给图元以进行可视化。 可以从许多不同的(在许多情况下)几何形状创建高性能基元。
说的那么复杂,其实就是几何体的基类,衍生了很多其他几何体,目前Cesium支持的几何体如下所示:
我们看到开篇介绍的添加Primitive的代码
眼见的小伙伴已经看到了,这个参数带有s,意思就是可以添加一个数组对象。开篇已经提到过了,Primitive加载多个几何体时,性能远远高于Entity,就是在这里体现的。
下面的代码就是简单的应用:
可以给所有几何对象赋予相同的appearance(后面会讲到)
var instance = new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(105.20, 30.55, 106.20, 31.55),
vertexFormat:Cesium.EllipsoidSurfaceAppearance.VERTEXT_FORMAT
})
});
var instance1 = new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(107.20, 30.55, 108.20, 31.55),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEXT_FORMAT
})
});
viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [instance, instance1],
appearance: new Cesium.EllipsoidSurfaceAppearance({
material:Cesium.Material.fromType('Stripe')
})
}));
通过这样一个数组对象添加图元,可以极大提升性能,那么有同学又要问,我想单独给每个几何对象设置颜色怎么办,只需要在appearance这里写上一句
new Cesium.PerInstanceColorAppearance() 就行了,如下所示:
var instance = new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(105.20, 30.55, 106.20, 31.55),
vertexFormat:Cesium.EllipsoidSurfaceAppearance.VERTEXT_FORMAT
}),
attributes: {
color:Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE)
}
});
var instance1 = new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(107.20, 30.55, 108.20, 31.55),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEXT_FORMAT
}),
attributes: {
color:Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
}
});
var primitives= viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [instance, instance1],
appearance: new Cesium.PerInstanceColorAppearance()
}));
当整个geometryInstances添加过后,它就作为一个primitive加载到场景里面,不是多个对象 可以利用代码scene.primitives.get(0);获取这个集合primitive。
但是,我们怎么才能单独获取其中的对象呢,这时候就需要用到我们的scene.pick方法。我们可以单独在添加这些几何对象的时候给他们赋予一个id,然后通过scene.pick.id来判断,如果id一致,那么这个对象已经被获取到了。
二.Appearances
一看到这个单词,小伙伴们就已经猜到这个类的作用,即定义几何对象的外观,目前Cesium支持的外观如下:
这里主要介绍常用的一种常用的MaterialAppearance
主要的参数:
1.flat:扁平化着色,不考虑光线的作用
2.faceForward:布尔值,控制光照效果
3.material:即使用的材质对象
(1)使用颜色材质
primitives= viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [instance, instance1],
appearance: new Cesium.MaterialAppearance({
material : Cesium.Material.fromType('Color', {
color : Cesium.Color.BLUE
})
})
}));
(2)使用贴图材质
primitives= viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [instance, instance1],
appearance: new Cesium.MaterialAppearance({
material : Cesium.Material.fromType('Image', {
image : '医院.jpg'
})
})
}));
(3)使用棋盘材质
primitives= viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [instance, instance1],
appearance: new Cesium.MaterialAppearance({
material : Cesium.Material.fromType('Checkerboard', {
lightColor : Cesium.Color.RED,
darkColor:Cesium.Color.BLUE
})
})
}));
当我们定义了一个外观后,外观是没办法改变的,但是材质对象可以替换
例如,我们要把第一个颜色材质改成红色
可以通过以下代码修改
var primitive=scene.primitives.get(0);
primitive.appearance.material=new Cesium.Material.fromType('Color', {
color : Cesium.Color.RED
});
还有一些需要注意的 不是所有外观和所有几何图形可以搭配使用,例如EllipsoidSurfaceAppearance与WallGeometry就不能搭配,原因是后者是垂直于地表的。
还有之前所提起的合并geometry,必须所有geometry具有匹配的vertexFormat,才能被合并到一个Primitive中。