Cesium官方教程8-- 几何体和外观效果

原文地址: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.

原文地址:http://blog.51cto.com/14117342/2327147

时间: 2024-08-01 20:56:50

Cesium官方教程8-- 几何体和外观效果的相关文章

Cesium官方教程9--粒子系统

原文地址:https://cesiumjs.org/tutorials/Particle-Systems-Tutorial/ 粒子系统介绍这篇教程带你学习Cesium的粒子相关API,比如如何在你的项目里添加烟,火,火花等特效.什么是粒子系统?粒子系统是一种图形学技术,用来模拟复杂的物理效果.粒子系统是由一堆很小的图片组成,看起来就像一些复杂的"含糊不清(fuzzy)"对象,就像火.烟.天气.或者 ×××.这些复杂效果其实是通过控制每一个独立的粒子的初始位置.速度.生命周期等属性来完成

Cesium官方教程13--Cesium和Webpack

原文地址:https://cesiumjs.org/tutorials/cesium-and-webpack/Cesium 和 WebpackWebpack是非常强大非常流行的JavaScript 模块打包工具.它可以让开发人员以一种简单直观的 require 方式去加载各种页面需要的文件,极大的方便了开源人员对代码和资源文件进行结构化设计.当编译的时候,它会跟踪代码依赖性,把所有的模型打包到浏览器可以直接加载的一个或者多个bundles中.在这个教程的前一半,我们创建一个简单的web项目,学会

Cesium官方教程10--高级粒子特效

原文地址:https://cesiumjs.org/tutorials/Particle-Systems-More-Effects-Tutorial/高级粒子系统特效这篇教程学习更多的效果,包括天气和火箭推进器.如果没有学习过粒子系统基础知识,请学习这篇教程 粒子系统介绍 .天气下雪下雨 最开始下雪的教程是来自 追踪圣诞老人项目里的实现.步骤我们即将介绍如何做下雪效果,然后怎么把下雪变为下雨效果.我们将给每个粒子添加雪花图片,然后在updateParticle函数里定义每个粒子的移动属性和其他动

Cesium官方教程12--材质(Fabric)

原文地址:https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric介绍Fabric 是Cesium中基于JSON格式来描述materials的机制.材质描述多边形.折线.椭球等对象的外观特征.材质可以简单的是覆盖一张图片,或者是条纹或者棋盘图案.使用Fabric 和GLSL,可以从零开始写脚本新建材质,也可以从现有的材质中派生.比如潮湿碎裂的砖块可以使用程序生成的纹理.凹凸贴图和反射贴图来组合.对象通过material 属性来支持材质

Cesium官方教程11--建模人员必读

原文地址:https://cesium.com/blog/2014/12/15/gltf-tips-for-artists/这篇文章是Branden Coker, an artist from AGI 写的,他是 AGI 的一个艺术家,做过很多事情,包括 为追踪圣诞老人项目建模.感谢3dben 编写的Blender和3DS Max建模建议.Cesium使用面向web的glTF 格式三维模型,同时提供了一个 dae在线转gltf的工具, 把dae和它纹理拖放到这个工具里,就能获得一个glTF格式的

Cesium官方教程5--地形图层

原文地址:https://cesiumjs.org/tutorials/Terrain-Tutorial/Cesium支持渐进流式加载和渲染全球高精度地形,并且包含海.湖.河等水面效果.相对2D地图,山峰.山谷等其他地形特征的更适宜在这种3D地球中展示.地形数据集是巨大的,通常都是GB或者TB级别.在普通3D引擎中,使用底层图形API去高效实现地形数据的可视化需要做很多事情.幸好,Cesium已经完成了这个体力活,而我们只需要写几行代码.快速开始从一个示例开始吧.打开Sandcastle中的 H

Qt官方教程翻译——Using Qt Quick Designer

附网址:http://qt-project.org/doc/qtcreator-3.1/creator-using-qt-quick-designer.html Using Qt Quick Designer 你可以在Qt Quick Designer可视化编辑器或者代码编辑器中编辑.qml文件. 在工程中双击一个.qml文件可以在代码编辑器中打开它,然后选择设计模式在可视化编辑器中打开它. 使用可视化编辑窗格来管理你的工程: 导航面板(1):以树结构形式显示当前QML文件中的各个项目. 库面板

学习ASP .NET MVC5官方教程总结(七)Edit方法和Edit视图详解

学习ASP .NET MVC5官方教程总结(七)Edit方法和Edit视图详解 在本章中,我们研究生成的Edit方法和视图.但在研究之前,我们先将 release date 弄得好看一点.打开Models\Movie.cs 文件.先添加一个引用: <span style="font-size:14px;">using System.ComponentModel.DataAnnotations;</span> 然后在Movie类中添加以下代码: [Display(

QML官方教程——Using the Qt Quick Particle System

附网址:http://qt-project.org/doc/qt-5/qtquick-effects-particles.html Using the Qt Quick Particle System-- 使用Qt Quick粒子系统 所有粒子系统的类型都可以在QtQuick.Particles模块文档中找到. 注意想要使用粒子模块中的类型,你需要使用下面这个代码进行引入: import QtQuick.Particles 2.0 · The ParticleSystem 粒子系统包含4个主要的