天天看点

Cesium Primitive API 实践:绘制一个三角形

与直接调用官方 API 不同,本例直接使用 Geometry 和 Appearance 类进行构造图形,灵活度较大。 博客园 @四季留歌

目录

1 目的与结果

2 实现原理坐标系统选择

3 踩坑点

3.1 GeometryAttribute 的构造

3.1.1 position 的构造 - 数值类型

3.1.2 顶点着色器中 attribute 变量的名称

3.1.3 顶点着色器必须有 batchId attribute

3.2 仅 3D 模式

3.3 Appearance 的 renderState

3.4 Geometry 的 boundingSphere

3.5 Primitive 的异步计算

有如下一个经纬高数组,表示三角形的三个点,逆时针顺序:

其在GIS软件中绘制的形状如下:

Cesium Primitive API 实践:绘制一个三角形

最终在 Cesium 的绘制效果如下:

Cesium Primitive API 实践:绘制一个三角形

使用 Primitive 创建静态图形,不依赖官方封装好的 XXGeometry(最方便的应该是 PolygonGeometry)和 XXAppearance,只用最基础的 Geometry 类和 Appearance 类。

Primitive API 创建图形对象的结构如下:

如果使用 ENU 坐标,则需要计算转换矩阵,官方已提供了例子。

此处全为经纬高坐标,需要借助 Cesium 数学API 进行世界坐标转换。

Primitive API 直到传递给 WebGL 之前,想要在地球上绘制正确,必须是世界坐标。

使用 <code>Cesium.ComponentDatatype.DOUBLE</code>,values 必须传递 <code>Float64Array</code>,否则顶点着色器中匹配不到 <code>attribute vec3 position3DHigh</code> 和 <code>attribute vec3 position3DLow</code>。

若改为 <code>Cesium.ComponentDatatype.FLOAT</code>,values 传递 <code>Float32Array</code>,会导致异常。

暂不清楚传递 <code>Float32Array</code> 时,顶点着色器的坐标 attribute 应该改成什么(或许根本不应传递 Float32Array)

参考 <code>GeometryAttributes</code> 的文档,允许的 attribute 有如下几个:

坐标 position,需为 Float64 的数值,且每个点必须是 xyz 三个维度的

纹理坐标 st,需为 Float32 的数值,且必须是 xy 两个维度的

顶点颜色 color,需为 Uint8 的数值,且必须是 xyzw 四个维度的

顶点法线 normal,需为 Float32 的数值,且必须是 xyz 三个维度的

(不知道是什么,应该是切线之类的)bitangent,需为 Float32 的数值,且必须是 xyz 三个维度的

顶点切线向量 tangent,需为 Float32 的数值,且必须是 xyz 三个维度的

在 Primitive.prototype.update 方法运行时,有一个 <code>if (createSP)</code> 分支会调用 <code>createShaderProgram</code> 函数,其内会调用函数 <code>validateShaderMatching</code> 来检测着色器与 js 对象中 GeometryAttribute 的匹配情况。

顶点着色器中的 attribute 变量名,理应与 <code>attributes</code> 中的 key 一样,除了 position 被分解成了 <code>position3DHigh</code> 和 <code>position3DLow</code>(原因大家应该都知道,就是精度不够,需要分别编码)。

否则会报错。

Cesium Primitive API 实践:绘制一个三角形

若 new Viewer 时不指定 <code>scene3DOnly</code>,Primitive 的着色器要处理二三维的全部情况,这里只关心三维的情况,故要指定仅使用三维模式。

若不指定仅三维模式,且不计算范围球(见3.4),必报错。

一个对象,这个 renderState 对象的属性会在渲染时覆盖默认的 renderState。

depthMask:是否将深度值写入缓冲区

blending:透明度混合

depthTest:

enabled 深度检测

具体更多细节见 Renderer/RenderState.js

这里必须指明的是,即使什么 renderState 都不给,也要在 new Appearance 时给 renderState 一个空对象:

否则会报错:

Cesium Primitive API 实践:绘制一个三角形

若不指定,图形就不会出现。

coords_world 是世界坐标数组,[x1, y1, z1, x2, y2, z2, ...]

若不计算包围球且不指定仅三维模式(见3.2),程序将报错:

Cesium Primitive API 实践:绘制一个三角形

new Primitive 时,有一个 <code>asynchronous</code> 选项用于指定异步计算生成图形,要自己写 <code>WebWorker</code>,在这里因为没有写 <code>WebWorker</code>,所以将其指定为 false 进行同步计算。

若不写 WebWorker 也不指定其为 false,将报错:

Cesium Primitive API 实践:绘制一个三角形

继续阅读