cesium drawcommand介绍

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://zhuanlan.zhihu.com/p/453880906

class MyPrimitive {

constructor(modelMatrix) {
this.modelMatrix = modelMatrix || Cesium.Matrix4.IDENTITY.clone()
this.drawCommand = null;
}

/**
* 创建 DrawCommand
* @param {Cesium.Context} context
*/
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
})
}

/**
* 实现Primitive接口,供Cesium内部在每一帧中调用
* @param {Cesium.FrameState} frameState
*/
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)
作者

wangyawei

发布于

2025-03-20

更新于

2025-03-21

许可协议