Cesium渲染模块之Command
1. 引言
Cesium是一款三维地球和地图可视化开源JavaScript库,使用WebGL来进行硬件加速图形,使用时不需要任何插件支持,基于Apache2.0许可的开源程序,可以免费用于商业和非商业用途
Cesium官网:Cesium: The Platform for 3D Geospatial
Cesium GitHub站点:CesiumGS/cesium: An open-source JavaScript library for world-class 3D globes and maps (github.com)
API文档:Index - Cesium Documentation
通过阅读源码,理清代码逻辑,有助于扩展与开发,笔者主要参考了以下两个系列的文章
渲染是前端可视化的核心,本文描述Cesium渲染模块的Command
2. Cesium中的Command
Cesium中的Command对象包含执行的指令参数和执行方法,比如最简单的ClearCommand:
function ClearCommand(options) {
// ...
this.color = options.color;
this.depth = options.depth;
this.stencil = options.stencil;
this.renderState = options.renderState;
this.framebuffer = options.framebuffer;
this.owner = options.owner;
this.pass = options.pass;
}
ClearCommand.prototype.execute = function (context, passState) {
context.clear(this, passState);
};
ClearCommand包含颜色、深度、通道等指令参数和执行方法context.clear(this, passState)
Command对象主要有三类:
- ClearCommand
- DrawCommand
- ComputeCommand
正如其名,ClearCommand用于清除,DrawCommand用于绘制,ComputeCommand用于计算
3. ClearCommand
ClearCommand的封装很简单,如上述代码所示:
function ClearCommand(options) {
// ...
this.color = options.color;
this.depth = options.depth;
this.stencil = options.stencil;
this.renderState = options.renderState;
this.framebuffer = options.framebuffer;
this.owner = options.owner;
this.pass = options.pass;
}
ClearCommand.prototype.execute = function (context, passState) {
context.clear(this, passState);
};
context.clear()
会执行清除的WebGL指令:
Context.prototype.clear = function (clearCommand, passState) {
// ...
const c = clearCommand.color;
const d = clearCommand.depth;
const s = clearCommand.stencil;
gl.clearColor(c.red, c.green, c.blue, c.alpha);
gl.clearDepth(d);
gl.clearStencil(s);
bindFramebuffer(this, framebuffer);
gl.clear(bitmask);
};
ClearCommand在Scene中的调用:
初始化Scene时初始化ClearCommand
function Scene(options) {
// ...
this._clearColorCommand = new ClearCommand({
color: new Color(),
stencil: 0,
owner: this,
});
// ...
}
执行更新时调用ClearCommand的execute
()方法
Scene.prototype.updateAndExecuteCommands = function (passState, backgroundColor) {
// ...
updateAndClearFramebuffers(this, passState, backgroundColor);
// ...
};
function updateAndClearFramebuffers(scene, passState, clearColor) {
// ...
// Clear the pass state framebuffer.
const clear = scene._clearColorCommand;
Color.clone(clearColor, clear.color);
clear.execute(context, passState);
// ...
}
4. DrawCommand
DrawCommand是最常用的指令,它是绘制的主角
DrawCommand封装如下:
function DrawCommand(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
this._boundingVolume = options.boundingVolume;
this._orientedBoundingBox = options.orientedBoundingBox;
this._modelMatrix = options.modelMatrix;
this._primitiveType = defaultValue(
options.primitiveType,
PrimitiveType.TRIANGLES
);
this._vertexArray = options.vertexArray;
this._count = options.count;
this._offset = defaultValue(options.offset, 0);
this._instanceCount = defaultValue(options.instanceCount, 0);
this._shaderProgram = options.shaderProgram;
this._uniformMap = options.uniformMap;
this._renderState = options.renderState;
this._framebuffer = options.framebuffer;
this._pass = options.pass;
this._owner = options.owner;
this._debugOverlappingFrustums = 0;
this._pickId = options.pickId;
// ...
}
DrawCommand.prototype.execute = function (context, passState) {
context.draw(this, passState);
};
context.draw()
执行WebGL的绘制指令:
Context.prototype.draw = function (drawCommand, passState, shaderProgram, uniformMap) {
// ...
beginDraw(this, framebuffer, passState, shaderProgram, renderState);
continueDraw(this, drawCommand, shaderProgram, uniformMap);
};
function continueDraw(context, drawCommand, shaderProgram, uniformMap) {
// ...
va._bind();
context._gl.drawArrays(primitiveType, offset, count);
// ...
va._unBind();
}