当前位置:   article > 正文

【Cesium-源码解析】Primitive渲染流程,_vertex texture fetch support is required to render

vertex texture fetch support is required to render primitives with per-insta

为了实现自定义Primitive图元,对Cesium Primitive相关的源码进行了研究,理清了Primitive渲染流程。

1、Viewer和CesiumWidget中的render(),进行帧动画,触发Scene.render()

  1. //Widgets/CesiumWidget/CesiumWidget.js
  2. CesiumWidget.prototype.render = function () {
  3. if (this._canRender) {
  4. this._scene.initializeFrame();
  5. var currentTime = this._clock.tick();
  6. this._scene.render(currentTime);
  7. } else {
  8. this._clock.tick();
  9. }
  10. };

2、Scene.render()触发primitiveCollection.update(),每个primitive调用update()

  1. //Scene/Scene.js
  2. function updateAndRenderPrimitives(scene) {
  3. var frameState = scene._frameState;
  4. scene._groundPrimitives.update(frameState);
  5. scene._primitives.update(frameState);//primitivecollection.update()触发primitive.update()
  6. updateDebugFrustumPlanes(scene);
  7. updateShadowMaps(scene);
  8. if (scene._globe) {
  9. scene._globe.render(frameState);
  10. }
  11. }
  1. //Scene/Primitive.js
  2. Primitive.prototype.update = function (frameState) {
  3. if (
  4. (!defined(this.geometryInstances) && this._va.length === 0) ||
  5. (defined(this.geometryInstances) &&
  6. Array.isArray(this.geometryInstances) &&
  7. this.geometryInstances.length === 0) ||
  8. !defined(this.appearance) ||
  9. (frameState.mode !== SceneMode.SCENE3D && frameState.scene3DOnly) ||
  10. (!frameState.passes.render && !frameState.passes.pick)
  11. ) {
  12. return;
  13. }
  14. if (defined(this._error)) {
  15. throw this._error;
  16. }
  17. //>>includeStart('debug', pragmas.debug);
  18. if (defined(this.rtcCenter) && !frameState.scene3DOnly) {
  19. throw new DeveloperError(
  20. "RTC rendering is only available for 3D only scenes."
  21. );
  22. }
  23. //>>includeEnd('debug');
  24. if (this._state === PrimitiveState.FAILED) {
  25. return;
  26. }
  27. var context = frameState.context;
  28. if (!defined(this._batchTable)) {
  29. createBatchTable(this, context);//每个primitive唯一值属性,如拾取id,拾取颜色
  30. }
  31. if (this._batchTable.attributes.length > 0) {
  32. if (ContextLimits.maximumVertexTextureImageUnits === 0) {
  33. throw new RuntimeError(
  34. "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."
  35. );
  36. }
  37. this._batchTable.update(frameState);
  38. }
  39. if (
  40. this._state !== PrimitiveState.COMPLETE &&
  41. this._state !== PrimitiveState.COMBINED
  42. ) {
  43. if (this.asynchronous) {
  44. loadAsynchronous(this, frameState);//异步装配,在Workers中
  45. } else {
  46. loadSynchronous(this, frameState);//同步装配顶点数据
  47. }
  48. }
  49. if (this._state === PrimitiveState.COMBINED) {
  50. updateBatchTableBoundingSpheres(this, frameState);
  51. updateBatchTableOffsets(this, frameState);
  52. createVertexArray(this, frameState);//创建webgl顶点缓冲区
  53. }
  54. if (!this.show || this._state !== PrimitiveState.COMPLETE) {
  55. return;
  56. }
  57. if (!this._batchTableOffsetsUpdated) {
  58. updateBatchTableOffsets(this, frameState);
  59. }
  60. if (this._recomputeBoundingSpheres) {
  61. recomputeBoundingSpheres(this, frameState);
  62. }
  63. // Create or recreate render state and shader program if appearance/material changed
  64. var appearance = this.appearance;
  65. var material = appearance.material;
  66. var createRS = false;
  67. var createSP = false;
  68. if (this._appearance !== appearance) {
  69. this._appearance = appearance;
  70. this._material = material;
  71. createRS = true;
  72. createSP = true;
  73. } else if (this._material !== material) {
  74. this._material = material;
  75. createSP = true;
  76. }
  77. var depthFailAppearance = this.depthFailAppearance;
  78. var depthFailMaterial = defined(depthFailAppearance)
  79. ? depthFailAppearance.material
  80. : undefined;
  81. if (this._depthFailAppearance !== depthFailAppearance) {
  82. this._depthFailAppearance = depthFailAppearance;
  83. this._depthFailMaterial = depthFailMaterial;
  84. createRS = true;
  85. createSP = true;
  86. } else if (this._depthFailMaterial !== depthFailMaterial) {
  87. this._depthFailMaterial = depthFailMaterial;
  88. createSP = true;
  89. }
  90. var translucent = this._appearance.isTranslucent();
  91. if (this._translucent !== translucent) {
  92. this._translucent = translucent;
  93. createRS = true;
  94. }
  95. if (defined(this._material)) {
  96. this._material.update(context);
  97. }
  98. var twoPasses = appearance.closed && translucent;
  99. if (createRS) {
  100. var rsFunc = defaultValue(
  101. this._createRenderStatesFunction,
  102. createRenderStates
  103. );
  104. rsFunc(this, context, appearance, twoPasses);//webgl渲染属性
  105. }
  106. if (createSP) {
  107. var spFunc = defaultValue(
  108. this._createShaderProgramFunction,
  109. createShaderProgram
  110. );
  111. spFunc(this, frameState, appearance);//创建webgl着色器程序
  112. }
  113. if (createRS || createSP) {
  114. var commandFunc = defaultValue(
  115. this._createCommandsFunction,
  116. createCommands
  117. );
  118. commandFunc( //创建DrawCommond绘制命令
  119. this,
  120. appearance,
  121. material,
  122. translucent,
  123. twoPasses,
  124. this._colorCommands,
  125. this._pickCommands,
  126. frameState
  127. );
  128. }
  129. var updateAndQueueCommandsFunc = defaultValue(
  130. this._updateAndQueueCommandsFunction,
  131. updateAndQueueCommands
  132. );
  133. updateAndQueueCommandsFunc( //将绘制命令加入绘制队列中
  134. this,
  135. frameState,
  136. this._colorCommands,
  137. this._pickCommands,
  138. this.modelMatrix,
  139. this.cull,
  140. this.debugShowBoundingVolume,
  141. twoPasses
  142. );
  143. };

primitive渲染核心内容就在update函数中,依次经过了以下几个步骤:

1、createBatchTable函数:创建每个primitive的唯一值属性,如拾取ID,拾取颜色;

2、loadSynchronous函数:初始化primitive顶点数据

     1) PrimitivePipeLine.combineGeometry函数 

  1. //Scene/PrimitivePipeline.js
  2. PrimitivePipeline.combineGeometry = function (parameters) {
  3. var geometries;
  4. var attributeLocations;
  5. var instances = parameters.instances;
  6. var length = instances.length;
  7. var pickOffsets;
  8. var offsetInstanceExtend;
  9. var hasOffset = false;
  10. if (length > 0) {
  11. //将图元建模坐标利用ModelMatrix转换到世界坐标,并新增batchID
  12. geometries = geometryPipeline(parameters);
  13. if (geometries.length > 0) {
  14. //将创建cesium内置的顶点着色器中的Attribute属性
  15. //[position3DHigh,position3DLow,position2DHigh,position2DLow,batchId]
  16. attributeLocations = GeometryPipeline.createAttributeLocations(
  17. geometries[0]
  18. );
  19. if (parameters.createPickOffsets) {
  20. pickOffsets = createInstancePickOffsets(instances, geometries);
  21. }
  22. }
  23. if (
  24. defined(instances[0].attributes) &&
  25. defined(instances[0].attributes.offset)
  26. ) {
  27. offsetInstanceExtend = new Array(length);
  28. hasOffset = true;
  29. }
  30. }
  31. .....
  32. .....
  33. };

3、createVertextArray函数:创建webgl顶点缓冲区

4、createRenderStates函数:设置webgl渲染属性,如背面剔除,深度测试,融合等

5、createShaderProgram函数:初始化webgl着色器程序

顶点着色器程序和片元着色器程序来自于primitive.appearance,在此过程中在着色器程序中添加cesium内置shader函数。

  1. //Renderer/ShaderProgram.js
  2. function createAndLinkProgram(gl, shader) {
  3. var vsSource = shader._vertexShaderText;//顶点着色器程序
  4. var fsSource = shader._fragmentShaderText;//片元着色器程序
  5. var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  6. gl.shaderSource(vertexShader, vsSource);
  7. gl.compileShader(vertexShader);
  8. var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  9. gl.shaderSource(fragmentShader, fsSource);
  10. gl.compileShader(fragmentShader);
  11. var program = gl.createProgram();
  12. gl.attachShader(program, vertexShader);
  13. gl.attachShader(program, fragmentShader);
  14. gl.deleteShader(vertexShader);
  15. gl.deleteShader(fragmentShader);
  16. var attributeLocations = shader._attributeLocations;
  17. if (defined(attributeLocations)) {
  18. for (var attribute in attributeLocations) {
  19. if (attributeLocations.hasOwnProperty(attribute)) {
  20. gl.bindAttribLocation(
  21. program,
  22. attributeLocations[attribute],
  23. attribute
  24. );
  25. }
  26. }
  27. }
  28. gl.linkProgram(program);
  29. .....
  30. return program;
  31. }

6、createCommands函数:创建DrawCommand绘制命令,该命令属于primitive,最后通过updateAndQueueCommands函数将该绘制命令加入到队列中,Scene的每一帧都会执行。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/99764
推荐阅读
相关标签
  

闽ICP备14008679号