DrawCommand 是 Cesium 渲染器的核心类,常用的接口 Entity、Primitive、Cesium3DTileSet,以及地形和影像的渲染等等,底层都是一个个 DrawCommand 完成的。在进行扩展开发、视觉特效提升、性能优化、渲染到纹理(RTT),甚至基于 Cesium 封装自己的开发框架,定义独家数据格式等等,都需要开发人员对 DrawCommand 熟练掌握。而这部分接口,Cesium 官方文档没有公开,网上的相关资料也比较少,学习起来比较困难,所以接下来我们用几期文章,由浅入深,实用为主,力求全面地介绍 DrawCommand 及相关类的运用。

一个基本的 DrawCommand 至少包含:
vertexArray :顶点数组,向 GPU 传递顶点属性、索引(可选的)数组等几何信息;
shaderProgram :着色器程序对象,负责编译、链接顶点着色器(vertexShader)、片元着色器(fragmentShader);
renderState :渲染状态对象,封装如深度测试(depthTest)、剔除(cull)、混合(blending)等状态类型的参数设置;
pass :渲染通道,Cesium 提供的常用渲染通道(封装在 Cesium.Pass)有:
ENVIRONMENT:环境,如天空盒(星空背景)
COMPUTE :用于并行加速计算
GLOBE :地形瓦片等
TERRAIN_CLASSIFICATION :地形分类
CESIUM_3D_TILE :3D Tiles 瓦片
CESIUM_3D_TILE_CLASSIFICATION :3D Tiles 分类(单体化)
OPAQUE :不透明物体
TRANSLUCENT :半透明物体
:::
:::color1
modelMatrix:模型变换矩阵,用于指定所绘制物体的参考系,包括位置、旋转、缩放三方面参数。如果不设置,则参考系为世界坐标系,原点在地球球心
:::
1 2
| const modelCenter = Cesium.Cartesian3.fromDegrees(121.474509, 31.233368, 0); const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(modelCenter);
|
:::color1
uniformMap :用于传递 uniform 具体的值,是一个回调函数字典对象,key 是 uniform 变量名,value 是回调函数,回调函数的返回值可以是:
:::

:::color1
vertexArray 顶点数组的创建有多种方法,通常可以将几何数据用 Cesium.Geometry 来表达,然后用 Cesium.VertexArray.fromGeometry 可以用更少代码量完成创建
:::

attributeLocations :顶点属性索引,key 为属性名称,value 为顶点属性缓冲区在同一个着色器程序中的索引,相当于将 js 中的顶点数组,传递到 shader 中的 attribute 变量。在后面创建 shaderProgram 时还需要用到;
context:从 Primitive.update 方法的 frameState 参数中获取;
geometry:Cesium.Geometry,Cesium 自带的几何类型都提供一个静态方法 createGeometry 来生成这个类型的几何对象

:::color1
着色器程序,负责编译、链接顶点着色器(vertexShader)、片元着色器(fragmentShader),
:::
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const vertexShaderSource = ` in vec3 position; void main() { gl_Position = czm_projection * czm_view * czm_model * vec4(position, 1.0); } `; const fragmentShaderSource = ` #version 300 es precision highp float; out vec4 fragColor;
void main() { fragColor = vec4(1.0, 1.0, 0.0, 1.0); } `; const attributeLocations = { position: 0, };
const shaderProgram = Cesium.ShaderProgram.fromCache({ context: context, vertexShaderSource: vertexShaderSource, fragmentShaderSource: fragmentShaderSource, attributeLocations: attributeLocations, });
|
:::color1
uniformMap 用于传递自定义 uniform 变量的值,是一个回调函数字典对象,key 是 uniform 变量名,value 是回调函数
:::

:::color1
renderState 渲染状态对象,封装如深度测试(depthTest)、剔除(cull)、混合(blending)等状态类型的参数设置
:::
1 2 3 4 5
| const renderState = Cesium.RenderState.fromCache({ depthTest: { enabled: true, }, });
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| 链接:https:
class MyPrimitive {
constructor(modelMatrix) { this.modelMatrix = modelMatrix || Cesium.Matrix4.IDENTITY.clone() this.drawCommand = null; }
createCommand(context) {
var modelMatrix = this.modelMatrix;
var box = new Cesium.BoxGeometry({ vertexFormat: Cesium.VertexFormat.POSITION_ONLY, maximum: new Cesium.Cartesian3(250000.0, 250000.0, 250000.0), minimum: new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0) }); var geometry = Cesium.BoxGeometry.createGeometry(box);
var attributeLocations = Cesium.GeometryPipeline.createAttributeLocations(geometry)
var va = Cesium.VertexArray.fromGeometry({ context: context, geometry: geometry, attributeLocations: attributeLocations });
var vs = ` attribute vec3 position; void main(){ gl_Position = czm_projection * czm_modelView * vec4( position , 1. ); } `; var fs = ` uniform vec3 color; void main(){ gl_FragColor=vec4( color , 1. ); } `; var shaderProgram = Cesium.ShaderProgram.fromCache({ context: context, vertexShaderSource: vs, fragmentShaderSource: fs, attributeLocations: attributeLocations })
var uniformMap = { color() { return Cesium.Color.GRAY } }
var renderState = Cesium.RenderState.fromCache({ cull: { enabled: true, face: Cesium.CullFace.BACK }, depthTest: { enabled: true } })
this.drawCommand = new Cesium.DrawCommand({ modelMatrix: modelMatrix, vertexArray: va, shaderProgram: shaderProgram, uniformMap: uniformMap, renderState: renderState, pass: Cesium.Pass.OPAQUE }) }
update(frameState) { if (!this.drawCommand) { this.createCommand(frameState.context) } frameState.commandList.push(this.drawCommand) }
}
var viewer=new Cesium.Viewer('cesiumContainer'); viewer.scene.globe.depthTestAgainstTerrain = true;
var origin = Cesium.Cartesian3.fromDegrees(106, 26, 250000 / 2) var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin)
var primitive = new MyPrimitive(modelMatrix); viewer.scene.primitives.add(primitive)
|