1. 程式人生 > >Cesium官方教程8-- 幾何體和外觀效果

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

部分 替換 著色器 this 矩形區域 mar 網格 fabri 並且

原文地址:https://cesiumjs.org/tutorials/Geometry-and-Appearances/
幾何體和外觀效果(Geometry and Appearances)
這篇教程會教大家學習Primitive API中支持的幾何體和外觀效果。這篇教程並不是面向Cesium的普通用戶,主要討論Cesium的高級知識,包括自定義三角網(mesh),形狀(shape),體(volume)以及他們的外觀。如果你是初學者,建議先學下這篇教程。
Cesium可以使用Entity創建不同的幾何體,比如多邊形和橢圓等。比如把下面代碼拷貝到 Sandcastle 的Hello World 就能創建一個帶條紋狀材質的矩形:
技術分享圖片
技術分享圖片
條紋矩形
這篇教程裏,我們深入到圖元內部,使用 Geometry類和 Appearance 類來創建效果。幾何體定義了圖元的結構,比如三角網、線、點等。外觀(appearance)定義了圖片的著色效果,包含完整的頂點(vertex)和片段(fragment)著色器(shader)以及著色器狀態。
Cesium支持下列幾何體:
技術分享圖片
Box Geometry
BoxGeometry
技術分享圖片
Box Outline Geometry
BoxOutlineGeometryA box
技術分享圖片
Circle Geometry
CircleGeometry
技術分享圖片
Circle Outline Geometry

CircleOutlineGeometry

技術分享圖片
Corridor Geometry
CorridorGeometry
技術分享圖片
Corridor Outline Geometry
CorridorOutlineGeometry 以米為單位的折線 和 一個擠壓高度
技術分享圖片
Cylinder Geometry
CylinderGeometry
技術分享圖片
Cylinder Outline Geometry
CylinderOutlineGeometry圓柱, 椎體,半椎體
技術分享圖片
Ellipse Geometry
EllipseGeometry
技術分享圖片
Ellipse Outline Geometry
EllipseOutlineGeometry橢圓或者垂直擠壓的橢圓
技術分享圖片
Ellipsoid Geometry
EllipsoidGeometry
技術分享圖片
Ellipsoid Outline Geometry
EllipsoidOutlineGeometry橢球體
技術分享圖片
Extent Geometry
RectangleGeometry
技術分享圖片
Extent Outline Geometry
RectangleOutlineGeometry矩形或者垂直擠壓矩形
技術分享圖片
Polygon Geometry
PolygonGeometry
技術分享圖片
Polygon Outline Geometry
PolygonOutlineGeometry多邊形,支持帶洞以及垂直擠壓
技術分享圖片
Polyline Geometry
PolylineGeometry
技術分享圖片
Polyline Outline Geometry
SimplePolylineGeometry像素寬度定義的折線段
技術分享圖片
Volume Geometry
PolylineVolumeGeometry
技術分享圖片
Volume Outline Geometry
PolylineVolumeOutlineGeometry一個二維圖形沿著折線的延伸體。
技術分享圖片
Sphere Geometry
SphereGeometry
技術分享圖片\
Sphere outline Geometry
SphereOutlineGeometry球體
技術分享圖片
all Geometry
WallGeometry
技術分享圖片
Wall Outline Geometry
WallOutlineGeometry垂直於地表的墻面
技術分享圖片
幾何體全家福

使用幾何體和外觀的優勢:

性能 - 尤其是繪制大量靜態圖元(比如整個美國的郵政編碼區域多邊形),使用幾何體可以把他們組合成一個單一的幾何體,這樣會減少cpu的開銷,並且充分利用GPU的能力。組合幾何體可以在web worker中完成,不會影響用戶界面的響應。
靈活性 - 圖元由幾何體和外觀構成。不過他們可以單獨修改。新建的幾何體可以兼容多種不同的外觀,反之亦然。

底層訪問 - 外觀提供了近乎最底層的渲染訪問,但是又不需要直接擔心渲染 Renderer 的細節技術 。外觀使下面的技術簡單了很多:

編寫完整的頂點和片段著色器GLSL代碼。
使用用戶自定義的渲染狀態。

當然也有一些缺點:

使用幾何體和外觀需要寫更多的代碼,並且需要對圖形知識有深刻的理解。Entity是應用層的抽象;而幾何體和外觀更像是一個傳統3D引擎的級別。
對於靜態數據,幾何體合並非常有效,但是對於動態數據不適合。
使用幾何體和外觀來重新編寫示例代碼:
技術分享圖片
沒有用矩形的entity,我們使用了普通的 Primitive, 它裏面連接和幾何體和外觀。現在先忽略 Geometry和 a GeometryInstance 的區別,只需知道instance是geometry的容器。
創建矩形幾何體 RectangleGeometry的時候,這個矩形區域的三角網會貼合地球曲率。
技術分享圖片
網格效果

因為我們預先知道這個幾何體是在球面上,所以直接使用 EllipsoidSurfaceAppearance。這樣做也能節省內存 ,支持所有的材質,因為幾何體是在橢球體上方的固定高度(譯者註:個人理解是說頂點可以只需要二維坐標,高度值可以當作uniform傳進去)。
幾何體合並
當使用一個圖元去繪制多個靜態幾何體的時候,會有些效率提升。比如我們畫兩個矩形:
技術分享圖片
技術分享圖片
兩個矩形

創建了另一個矩形的instance,然後把兩個instance都添加到一個圖元裏,使用同一個外觀去繪制。 一些外觀允許為每個instance設置不同的屬性(attribute)。比如,使用 PerInstanceColorAppearance 對每個instance著不同顏色。
技術分享圖片
技術分享圖片
不同顏色的矩形

每個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()
}));
技術分享圖片
幾何體合並

拾取
當instance合並之後,仍然支持獨立訪問。通常,我們會設置一個id屬性, Scene.pick函數裏通過它來判定哪個instance被拾取。這個id 可以任何js類型:字符串,數字,帶屬性的對象等等。
下面的示例創建一個帶id 的instance,當它被點擊的時候控制臺會輸出一個消息。
技術分享圖片
使用id 而不是用instance對象本身去判定,主要是為了避免在創建圖元之後,我們的圖元甚至我們的項目對所有的instance對象 以及 它的幾何體 一直被引用無法釋放內存。因為幾何體一般包含了一個比較大的數組,這種方式就可以幫我們節省大量內存。
幾何體intances
目前為止,我們創建的每個幾何體instance都只包含一個幾何體。此外,instance竟然用來把同一個幾何體放置在場景的不同位置,包括不同大小和方向。由於多個instance可以引用同一個幾何體( Geometry),而每個instance可以有不同的偏移矩陣(modelMatrix)。這樣,我們就只需要計算一次幾何體(計算頂點等)而多次使用它。
技術分享圖片
幾何體 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
})
}));
技術分享圖片
橢球體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)。
技術分享圖片
Appearances
Cesium 包含下述外觀類型:
技術分享圖片
MaterialAppearance
MaterialAppearance 所有幾何體都使用同一個外觀,支持使用 materials 去定義著色效果.
技術分享圖片
EllipsoidSurface
EllipsoidSurface MaterialAppearance 的簡化版本,假定幾何體都和地球橢球體平行,就像多邊形一樣。使用這個可以在計算大量頂點屬性的時候節省內存
技術分享圖片
PerInstanceColorAppearance
PerInstanceColorAppearance 每個instance使用不同的顏色去著色。
技術分享圖片
PolylineMaterialAppearance
PolylineMaterialAppearance 支持在折線上設置材質。
技術分享圖片
PolylineColorAppearance

PolylineColorAppearance支持折線在每個頂點或者每一段設置顏色。
外觀完整的定義了頂點和片段著色器代碼,在GPU中圖元渲染的時候使用。除非要自定義外觀,否則我們很少使用它們。外觀也定義了完整的渲染你狀態,它控制了圖元渲染時候的GPU狀態。我們可以使用高級的屬性來定義渲染狀態,比如 閉合closed 和 半透明translucent,外觀會把他們轉換為真正的底層狀態,比如:
技術分享圖片
一旦我們的外觀創建了,我們不能修改它的renderState屬性,但是我們能修改它的材質 material。當然,我們可以整個替換圖元的appearance屬性。
大部分外觀包含 flat 和faceForward 屬性, 這個直接控制了GLSL的著色效果。

flat - 純色著色,不考慮光照效果。

faceForward - 當有光照的的時候,當視圖正對它的時候反轉法向量,避免墻體的背面是黑色的。
flat : true | faceForward : false | faceForward : true |
技術分享圖片
flat:true
技術分享圖片
faceForward : false
技術分享圖片
faceForward : true
幾何體和外觀的匹配性
我們發現不是所有的外觀都能作用在任意幾何體上。比如EllipsoidSurfaceAppearance 不能用在WallGeometry 上,因為墻永遠垂直地表,而不是平行地表。
隱含之意,一個外觀能和一個幾何體匹配,需要頂點格式匹配,也就是說幾何體必須包含外觀需要的頂點格式數據。創建一個幾何體的時候,可以指定一個 VertexFormat 參數。
有時候為了簡化問題,但是接受一點點浪費和效率低,可以計算一個幾何體的所有頂點屬性格式,這樣就能和所有外觀兼容(忽略per-instance屬性)
技術分享圖片
不兼容
如果使用EllipsoidSurfaceAppearance,比如我們只創建了頂點的位置屬性,那麽就會崩潰(get away)。
技術分享圖片
通常,我們怎麽知道某種外觀需要哪種頂點格式?大部分外觀都有一個 vertexFormat 屬性, 甚至一個 VERTEX_FORMAT靜態常量。
技術分享圖片
同樣,幾何體的 vertexFormat 屬性也決定了幾何體是否可以合並。如果要合並,可以幾何體類型不同,但是必須保證頂點格式一致。
相關資源
用戶手冊:

所有幾何體
所有外觀
圖元Primitive
幾何體instanceGeometryInstance

想了解材質的更多內容,請訪問Fabric。
想了解這塊的開發計劃,請訪問: Geometry and Appearances Roadmap.技術分享圖片

技術分享圖片

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