Cesium官方教程8-- 幾何體和外觀效果

原文地址: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-- 幾何體和外觀效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章