原文地址:https://cesiumjs.org/tutorials/Geometry-and-Appearances/
几何体和外观效果(Geometry and Appearances)
这篇教程会教大家学习Primitive API中支持的几何体和外观效果。这篇教程并不是面向Cesium的普通用户,主要讨论Cesium的高级知识,包括自定义三角网(mesh),形状(shape),体(volume)以及他们的外观。如果你是初学者,建议先学下这篇教程。
Cesium可以使用Entity创建不同的几何体,比如多边形和椭圆等。比如把下面代码拷贝到 Sandcastle 的Hello World 就能创建一个带条纹状材质的矩形:
Cesium官方教程8-- 几何体和外观效果
Cesium官方教程8-- 几何体和外观效果
条纹矩形
这篇教程里,我们深入到图元内部,使用 Geometry类和 Appearance 类来创建效果。几何体定义了图元的结构,比如三角网、线、点等。外观(appearance)定义了图片的着色效果,包含完整的顶点(vertex)和片段(fragment)着色器(shader)以及着色器状态。
Cesium支持下列几何体:
Cesium官方教程8-- 几何体和外观效果
Box Geometry
BoxGeometry
Cesium官方教程8-- 几何体和外观效果
Box Outline Geometry
BoxOutlineGeometryA box
Cesium官方教程8-- 几何体和外观效果
Circle Geometry
CircleGeometry
Cesium官方教程8-- 几何体和外观效果
Circle Outline Geometry
CircleOutlineGeometry
Cesium官方教程8-- 几何体和外观效果
Corridor Geometry
CorridorGeometry
Cesium官方教程8-- 几何体和外观效果
Corridor Outline Geometry
CorridorOutlineGeometry 以米为单位的折线 和 一个挤压高度
Cesium官方教程8-- 几何体和外观效果
Cylinder Geometry
CylinderGeometry
Cesium官方教程8-- 几何体和外观效果
Cylinder Outline Geometry
CylinderOutlineGeometry圆柱, 椎体,半椎体
Cesium官方教程8-- 几何体和外观效果
Ellipse Geometry
EllipseGeometry
Cesium官方教程8-- 几何体和外观效果
Ellipse Outline Geometry
EllipseOutlineGeometry椭圆或者垂直挤压的椭圆
Cesium官方教程8-- 几何体和外观效果
Ellipsoid Geometry
EllipsoidGeometry
Cesium官方教程8-- 几何体和外观效果
Ellipsoid Outline Geometry
EllipsoidOutlineGeometry椭球体
Cesium官方教程8-- 几何体和外观效果
Extent Geometry
RectangleGeometry
Cesium官方教程8-- 几何体和外观效果
Extent Outline Geometry
RectangleOutlineGeometry矩形或者垂直挤压矩形
Cesium官方教程8-- 几何体和外观效果
Polygon Geometry
PolygonGeometry
Cesium官方教程8-- 几何体和外观效果
Polygon Outline Geometry
PolygonOutlineGeometry多边形,支持带洞以及垂直挤压
Cesium官方教程8-- 几何体和外观效果
Polyline Geometry
PolylineGeometry
Cesium官方教程8-- 几何体和外观效果
Polyline Outline Geometry
SimplePolylineGeometry像素宽度定义的折线段
Cesium官方教程8-- 几何体和外观效果
Volume Geometry
PolylineVolumeGeometry
Cesium官方教程8-- 几何体和外观效果
Volume Outline Geometry
PolylineVolumeOutlineGeometry一个二维图形沿着折线的延伸体。
Cesium官方教程8-- 几何体和外观效果
Sphere Geometry
SphereGeometry
Cesium官方教程8-- 几何体和外观效果\
Sphere outline Geometry
SphereOutlineGeometry球体
Cesium官方教程8-- 几何体和外观效果
all Geometry
WallGeometry
Cesium官方教程8-- 几何体和外观效果
Wall Outline Geometry
WallOutlineGeometry垂直于地表的墙面
Cesium官方教程8-- 几何体和外观效果
几何体全家福
使用几何体和外观的优势:
性能 - 尤其是绘制大量静态图元(比如整个美国的邮政编码区域多边形),使用几何体可以把他们组合成一个单一的几何体,这样会减少cpu的开销,并且充分利用GPU的能力。组合几何体可以在web worker中完成,不会影响用户界面的响应。
灵活性 - 图元由几何体和外观构成。不过他们可以单独修改。新建的几何体可以兼容多种不同的外观,反之亦然。
底层访问 - 外观提供了近乎最底层的渲染访问,但是又不需要直接担心渲染 Renderer 的细节技术 。外观使下面的技术简单了很多:
编写完整的顶点和片段着色器GLSL代码。
使用用户自定义的渲染状态。
当然也有一些缺点:
使用几何体和外观需要写更多的代码,并且需要对图形知识有深刻的理解。Entity是应用层的抽象;而几何体和外观更像是一个传统3D引擎的级别。
对于静态数据,几何体合并非常有效,但是对于动态数据不适合。
使用几何体和外观来重新编写示例代码:
Cesium官方教程8-- 几何体和外观效果
没有用矩形的entity,我们使用了普通的 Primitive, 它里面连接和几何体和外观。现在先忽略 Geometry和 a GeometryInstance 的区别,只需知道instance是geometry的容器。
创建矩形几何体 RectangleGeometry的时候,这个矩形区域的三角网会贴合地球曲率。
Cesium官方教程8-- 几何体和外观效果
网格效果
因为我们预先知道这个几何体是在球面上,所以直接使用 EllipsoidSurfaceAppearance。这样做也能节省内存 ,支持所有的材质,因为几何体是在椭球体上方的固定高度(译者注:个人理解是说顶点可以只需要二维坐标,高度值可以当作uniform传进去)。
几何体合并
当使用一个图元去绘制多个静态几何体的时候,会有些效率提升。比如我们画两个矩形:
Cesium官方教程8-- 几何体和外观效果
Cesium官方教程8-- 几何体和外观效果
两个矩形
创建了另一个矩形的instance,然后把两个instance都添加到一个图元里,使用同一个外观去绘制。 一些外观允许为每个instance设置不同的属性(attribute)。比如,使用 PerInstanceColorAppearance 对每个instance着不同颜色。
Cesium官方教程8-- 几何体和外观效果
Cesium官方教程8-- 几何体和外观效果
不同颜色的矩形
每个intance有一个Color 属性。图元里创建一个PerInstanceColorAppearance,它知道使用每个instance的color属性去着色。
几何体合并允许Cesium高效的渲染大量几何体。下面示例绘制了2592个不同颜色的矩形。优化之后,渲染非常块。
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
var instances = [];
for (var lon = -180.0; lon < 180.0; lon += 5.0) {
for (var lat = -85.0; lat < 85.0; lat += 5.0) {
instances.push(new Cesium.GeometryInstance({
geometry : new Cesium.RectangleGeometry({
rectangle : Cesium.Rectangle.fromDegrees(lon, lat, lon + 5.0, lat + 5.0),
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({alpha : 0.5}))
}
}));
}
}
scene.primitives.add(new Cesium.Primitive({
geometryInstances : instances,
appearance : new Cesium.PerInstanceColorAppearance()
}));
Cesium官方教程8-- 几何体和外观效果
几何体合并
拾取
当instance合并之后,仍然支持独立访问。通常,我们会设置一个id属性, Scene.pick函数里通过它来判定哪个instance被拾取。这个id 可以任何js类型:字符串,数字,带属性的对象等等。
下面的示例创建一个带id 的instance,当它被点击的时候控制台会输出一个消息。
Cesium官方教程8-- 几何体和外观效果
使用id 而不是用instance对象本身去判定,主要是为了避免在创建图元之后,我们的图元甚至我们的项目对所有的instance对象 以及 它的几何体 一直被引用无法释放内存。因为几何体一般包含了一个比较大的数组,这种方式就可以帮我们节省大量内存。
几何体intances
目前为止,我们创建的每个几何体instance都只包含一个几何体。此外,instance竟然用来把同一个几何体放置在场景的不同位置,包括不同大小和方向。由于多个instance可以引用同一个几何体( Geometry),而每个instance可以有不同的偏移矩阵(modelMatrix)。这样,我们就只需要计算一次几何体(计算顶点等)而多次使用它。
Cesium官方教程8-- 几何体和外观效果
几何体 instance
下面的代码创建了一个EllipsoidGeometry 和 两个instance. 每个instance 引用了相同的椭球几何体,但是使用 modelMatrix放到不同位置,这里效果是一个叠在另一个之上。
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
var ellipsoidGeometry = new Cesium.EllipsoidGeometry({
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
radii : new Cesium.Cartesian3(300000.0, 200000.0, 150000.0)
});
var cyanEllipsoidInstance = new Cesium.GeometryInstance({
geometry : ellipsoidGeometry,
modelMatrix : Cesium.Matrix4.multiplyByTranslation(
Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)),
new Cesium.Cartesian3(0.0, 0.0, 150000.0),
new Cesium.Matrix4()
),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.CYAN)
}
});
var orangeEllipsoidInstance = new Cesium.GeometryInstance({
geometry : ellipsoidGeometry,
modelMatrix : Cesium.Matrix4.multiplyByTranslation(
Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)),
new Cesium.Cartesian3(0.0, 0.0, 450000.0),
new Cesium.Matrix4()
),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.ORANGE)
}
});
scene.primitives.add(new Cesium.Primitive({
geometryInstances : [cyanEllipsoidInstance, orangeEllipsoidInstance],
appearance : new Cesium.PerInstanceColorAppearance({
translucent : false,
closed : true
})
}));
Cesium官方教程8-- 几何体和外观效果
椭球体instances
更新每个instance的属性
即便是已经添加到图元里,每个instance的一些属性也可以修改,包括:
Color : ColorGeometryInstanceAttribute 决定了几何体颜色。不过图元应该设置一个 PerInstanceColorAppearance外观。
Show :布尔变量决定instance是否可见,对任意instance都有效。
下面代码演示如何修改几何体instance的颜色:
This example shows how to change the color of the geometry instance:
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
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))
},
id: 'circle'
});
var primitive = new Cesium.Primitive({
geometryInstances : circleInstance,
appearance : new Cesium.PerInstanceColorAppearance({
translucent : false,
closed : true
})
});
scene.primitives.add(primitive);
setInterval(function() {
var attributes = primitive.getGeometryInstanceAttributes('circle');
attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.fromRandom({alpha : 1.0}));
},2000);
几何体的属性需要通过 primitive.getGeometryInstanceAttributes来获取到。attributes 里的值可以直接修改。这里,我们每2秒钟设置'circle'这个几何体随机颜色。
外观(Appearances)
几何体定义了结构。图元的另一个关键属性是appearance,决定图元的着色,也就说每个像素是如何上色的。一个图元可以有若干个几何体instance,但是只能有一个appearance属性。根据appearance类型不同,一个appearance可能有一个 material 属性,材质属性决定了大体的着色( the bulk of the shading)。
Cesium官方教程8-- 几何体和外观效果
Appearances
Cesium 包含下述外观类型:
Cesium官方教程8-- 几何体和外观效果
MaterialAppearance
MaterialAppearance 所有几何体都使用同一个外观,支持使用 materials 去定义着色效果.
Cesium官方教程8-- 几何体和外观效果
EllipsoidSurface
EllipsoidSurface MaterialAppearance 的简化版本,假定几何体都和地球椭球体平行,就像多边形一样。使用这个可以在计算大量顶点属性的时候节省内存
Cesium官方教程8-- 几何体和外观效果
PerInstanceColorAppearance
PerInstanceColorAppearance 每个instance使用不同的颜色去着色。
Cesium官方教程8-- 几何体和外观效果
PolylineMaterialAppearance
PolylineMaterialAppearance 支持在折线上设置材质。
Cesium官方教程8-- 几何体和外观效果
PolylineColorAppearance
PolylineColorAppearance支持折线在每个顶点或者每一段设置颜色。
外观完整的定义了顶点和片段着色器代码,在GPU中图元渲染的时候使用。除非要自定义外观,否则我们很少使用它们。外观也定义了完整的渲染你状态,它控制了图元渲染时候的GPU状态。我们可以使用高级的属性来定义渲染状态,比如 闭合closed 和 半透明translucent,外观会把他们转换为真正的底层状态,比如:
Cesium官方教程8-- 几何体和外观效果
一旦我们的外观创建了,我们不能修改它的renderState属性,但是我们能修改它的材质 material。当然,我们可以整个替换图元的appearance属性。
大部分外观包含 flat 和faceForward 属性, 这个直接控制了GLSL的着色效果。
flat - 纯色着色,不考虑光照效果。
faceForward - 当有光照的的时候,当视图正对它的时候反转法向量,避免墙体的背面是黑色的。
flat : true | faceForward : false | faceForward : true |
Cesium官方教程8-- 几何体和外观效果
flat:true
Cesium官方教程8-- 几何体和外观效果
faceForward : false
Cesium官方教程8-- 几何体和外观效果
faceForward : true
几何体和外观的匹配性
我们发现不是所有的外观都能作用在任意几何体上。比如EllipsoidSurfaceAppearance 不能用在WallGeometry 上,因为墙永远垂直地表,而不是平行地表。
隐含之意,一个外观能和一个几何体匹配,需要顶点格式匹配,也就是说几何体必须包含外观需要的顶点格式数据。创建一个几何体的时候,可以指定一个 VertexFormat 参数。
有时候为了简化问题,但是接受一点点浪费和效率低,可以计算一个几何体的所有顶点属性格式,这样就能和所有外观兼容(忽略per-instance属性)
Cesium官方教程8-- 几何体和外观效果
不兼容
如果使用EllipsoidSurfaceAppearance,比如我们只创建了顶点的位置属性,那么就会崩溃(get away)。
Cesium官方教程8-- 几何体和外观效果
通常,我们怎么知道某种外观需要哪种顶点格式?大部分外观都有一个 vertexFormat 属性, 甚至一个 VERTEX_FORMAT静态常量。
Cesium官方教程8-- 几何体和外观效果
同样,几何体的 vertexFormat 属性也决定了几何体是否可以合并。如果要合并,可以几何体类型不同,但是必须保证顶点格式一致。
相关资源
用户手册:
所有几何体
所有外观
图元Primitive
几何体instanceGeometryInstance
想了解材质的更多内容,请访问Fabric。
想了解这块的开发计划,请访问: Geometry and Appearances Roadmap.Cesium官方教程8-- 几何体和外观效果
Cesium官方教程8-- 几何体和外观效果
©著作权归作者所有:来自51CTO博客作者cesium实验的原创作品,如需转载,请注明出处,否则将追究法律责任
共同学习,写下你的评论
评论加载中...
作者其他优质文章