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

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 的异步计算

1 目的与结果

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

const coords_geo = [  [112.470, 25.694, 200000],  [109.961, 19.862, 200000],  [118.122, 21.921, 200000]]

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

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

2 实现原理

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

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

+Primitive  - GeometryInstance | GeometryInstance[]    - Geometry      - GeometryAttributes        - GeometryAttribute  - Appearance

坐标系统选择

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

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

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

3 踩坑点

3.1 GeometryAttribute 的构造

3.1.1 position 的构造 - 数值类型

使用 Cesium.ComponentDatatype.DOUBLE,values 必须传递 Float64Array,否则顶点着色器中匹配不到 attribute vec3 position3DHighattribute vec3 position3DLow

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

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

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

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

  • 坐标 position,需为 Float64 的数值,且每个点必须是 xyz 三个维度的
  • 纹理坐标 st,需为 Float32 的数值,且必须是 xy 两个维度的
  • 顶点颜色 color,需为 Uint8 的数值,且必须是 xyzw 四个维度的
  • 顶点法线 normal,需为 Float32 的数值,且必须是 xyz 三个维度的
  • (不知道是什么,应该是切线之类的)bitangent,需为 Float32 的数值,且必须是 xyz 三个维度的
  • 顶点切线向量 tangent,需为 Float32 的数值,且必须是 xyz 三个维度的

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

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

3.1.3 顶点着色器必须有 batchId attribute

否则会报错。

3.2 仅 3D 模式

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

new Cesium.Viewer('cesiumViewport', {  scene3DOnly: true,})

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

3.3 Appearance 的 renderState

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

  • depthMask:是否将深度值写入缓冲区
  • blending:透明度混合
  • depthTest:
    • enabled 深度检测

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

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

new Cesium.Appearance({  renderState: { },  vertexShaderSource: `...`,  fragmentShaderSource: `...`})

否则会报错:

3.4 Geometry 的 boundingSphere

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

Cesium.BoundingSphere.fromVertices(coords_world)

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

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

3.5 Primitive 的异步计算

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

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

const primitive = new Cesium.Primitive({  /* 其他属性 */  asynchronous: false})
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部