赞
踩
为了实现自定义Primitive图元,对Cesium Primitive相关的源码进行了研究,理清了Primitive渲染流程。
- //Widgets/CesiumWidget/CesiumWidget.js
-
- CesiumWidget.prototype.render = function () {
- if (this._canRender) {
- this._scene.initializeFrame();
- var currentTime = this._clock.tick();
- this._scene.render(currentTime);
- } else {
- this._clock.tick();
- }
- };
- //Scene/Scene.js
-
- function updateAndRenderPrimitives(scene) {
- var frameState = scene._frameState;
-
- scene._groundPrimitives.update(frameState);
- scene._primitives.update(frameState);//primitivecollection.update()触发primitive.update()
-
- updateDebugFrustumPlanes(scene);
- updateShadowMaps(scene);
-
- if (scene._globe) {
- scene._globe.render(frameState);
- }
- }
- //Scene/Primitive.js
-
- Primitive.prototype.update = function (frameState) {
- if (
- (!defined(this.geometryInstances) && this._va.length === 0) ||
- (defined(this.geometryInstances) &&
- Array.isArray(this.geometryInstances) &&
- this.geometryInstances.length === 0) ||
- !defined(this.appearance) ||
- (frameState.mode !== SceneMode.SCENE3D && frameState.scene3DOnly) ||
- (!frameState.passes.render && !frameState.passes.pick)
- ) {
- return;
- }
-
- if (defined(this._error)) {
- throw this._error;
- }
-
- //>>includeStart('debug', pragmas.debug);
- if (defined(this.rtcCenter) && !frameState.scene3DOnly) {
- throw new DeveloperError(
- "RTC rendering is only available for 3D only scenes."
- );
- }
- //>>includeEnd('debug');
-
- if (this._state === PrimitiveState.FAILED) {
- return;
- }
-
- var context = frameState.context;
- if (!defined(this._batchTable)) {
- createBatchTable(this, context);//每个primitive唯一值属性,如拾取id,拾取颜色
- }
- if (this._batchTable.attributes.length > 0) {
- if (ContextLimits.maximumVertexTextureImageUnits === 0) {
- throw new RuntimeError(
- "Vertex texture fetch support is required to render primitives with per-instance attributes. The maximum number of vertex texture image units must be greater than zero."
- );
- }
- this._batchTable.update(frameState);
- }
-
- if (
- this._state !== PrimitiveState.COMPLETE &&
- this._state !== PrimitiveState.COMBINED
- ) {
- if (this.asynchronous) {
- loadAsynchronous(this, frameState);//异步装配,在Workers中
- } else {
- loadSynchronous(this, frameState);//同步装配顶点数据
- }
- }
-
- if (this._state === PrimitiveState.COMBINED) {
- updateBatchTableBoundingSpheres(this, frameState);
- updateBatchTableOffsets(this, frameState);
- createVertexArray(this, frameState);//创建webgl顶点缓冲区
- }
-
- if (!this.show || this._state !== PrimitiveState.COMPLETE) {
- return;
- }
-
- if (!this._batchTableOffsetsUpdated) {
- updateBatchTableOffsets(this, frameState);
- }
- if (this._recomputeBoundingSpheres) {
- recomputeBoundingSpheres(this, frameState);
- }
-
- // Create or recreate render state and shader program if appearance/material changed
- var appearance = this.appearance;
- var material = appearance.material;
- var createRS = false;
- var createSP = false;
-
- if (this._appearance !== appearance) {
- this._appearance = appearance;
- this._material = material;
- createRS = true;
- createSP = true;
- } else if (this._material !== material) {
- this._material = material;
- createSP = true;
- }
-
- var depthFailAppearance = this.depthFailAppearance;
- var depthFailMaterial = defined(depthFailAppearance)
- ? depthFailAppearance.material
- : undefined;
-
- if (this._depthFailAppearance !== depthFailAppearance) {
- this._depthFailAppearance = depthFailAppearance;
- this._depthFailMaterial = depthFailMaterial;
- createRS = true;
- createSP = true;
- } else if (this._depthFailMaterial !== depthFailMaterial) {
- this._depthFailMaterial = depthFailMaterial;
- createSP = true;
- }
-
- var translucent = this._appearance.isTranslucent();
- if (this._translucent !== translucent) {
- this._translucent = translucent;
- createRS = true;
- }
-
- if (defined(this._material)) {
- this._material.update(context);
- }
-
- var twoPasses = appearance.closed && translucent;
-
- if (createRS) {
- var rsFunc = defaultValue(
- this._createRenderStatesFunction,
- createRenderStates
- );
- rsFunc(this, context, appearance, twoPasses);//webgl渲染属性
- }
-
- if (createSP) {
- var spFunc = defaultValue(
- this._createShaderProgramFunction,
- createShaderProgram
- );
- spFunc(this, frameState, appearance);//创建webgl着色器程序
- }
-
- if (createRS || createSP) {
- var commandFunc = defaultValue(
- this._createCommandsFunction,
- createCommands
- );
- commandFunc( //创建DrawCommond绘制命令
- this,
- appearance,
- material,
- translucent,
- twoPasses,
- this._colorCommands,
- this._pickCommands,
- frameState
- );
- }
-
- var updateAndQueueCommandsFunc = defaultValue(
- this._updateAndQueueCommandsFunction,
- updateAndQueueCommands
- );
- updateAndQueueCommandsFunc( //将绘制命令加入绘制队列中
- this,
- frameState,
- this._colorCommands,
- this._pickCommands,
- this.modelMatrix,
- this.cull,
- this.debugShowBoundingVolume,
- twoPasses
- );
- };

1、createBatchTable函数:创建每个primitive的唯一值属性,如拾取ID,拾取颜色;
2、loadSynchronous函数:初始化primitive顶点数据
1) PrimitivePipeLine.combineGeometry函数
- //Scene/PrimitivePipeline.js
-
- PrimitivePipeline.combineGeometry = function (parameters) {
- var geometries;
- var attributeLocations;
- var instances = parameters.instances;
- var length = instances.length;
- var pickOffsets;
-
- var offsetInstanceExtend;
- var hasOffset = false;
- if (length > 0) {
- //将图元建模坐标利用ModelMatrix转换到世界坐标,并新增batchID
- geometries = geometryPipeline(parameters);
- if (geometries.length > 0) {
- //将创建cesium内置的顶点着色器中的Attribute属性
- //[position3DHigh,position3DLow,position2DHigh,position2DLow,batchId]
- attributeLocations = GeometryPipeline.createAttributeLocations(
- geometries[0]
- );
- if (parameters.createPickOffsets) {
- pickOffsets = createInstancePickOffsets(instances, geometries);
- }
- }
- if (
- defined(instances[0].attributes) &&
- defined(instances[0].attributes.offset)
- ) {
- offsetInstanceExtend = new Array(length);
- hasOffset = true;
- }
- }
- .....
- .....
- };

3、createVertextArray函数:创建webgl顶点缓冲区
4、createRenderStates函数:设置webgl渲染属性,如背面剔除,深度测试,融合等
5、createShaderProgram函数:初始化webgl着色器程序
顶点着色器程序和片元着色器程序来自于primitive.appearance,在此过程中在着色器程序中添加cesium内置shader函数。
- //Renderer/ShaderProgram.js
-
- function createAndLinkProgram(gl, shader) {
- var vsSource = shader._vertexShaderText;//顶点着色器程序
- var fsSource = shader._fragmentShaderText;//片元着色器程序
-
- var vertexShader = gl.createShader(gl.VERTEX_SHADER);
- gl.shaderSource(vertexShader, vsSource);
- gl.compileShader(vertexShader);
-
- var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
- gl.shaderSource(fragmentShader, fsSource);
- gl.compileShader(fragmentShader);
-
- var program = gl.createProgram();
- gl.attachShader(program, vertexShader);
- gl.attachShader(program, fragmentShader);
-
- gl.deleteShader(vertexShader);
- gl.deleteShader(fragmentShader);
-
- var attributeLocations = shader._attributeLocations;
- if (defined(attributeLocations)) {
- for (var attribute in attributeLocations) {
- if (attributeLocations.hasOwnProperty(attribute)) {
- gl.bindAttribLocation(
- program,
- attributeLocations[attribute],
- attribute
- );
- }
- }
- }
-
- gl.linkProgram(program);
-
- .....
-
- return program;
- }

6、createCommands函数:创建DrawCommand绘制命令,该命令属于primitive,最后通过updateAndQueueCommands函数将该绘制命令加入到队列中,Scene的每一帧都会执行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。