智慧水务管理系统 - 精河县供水工程综合管理平台

renderBufferPointCollection.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // @ts-check
  2. import defined from "../Core/defined.js";
  3. import Cartesian3 from "../Core/Cartesian3.js";
  4. import Color from "../Core/Color.js";
  5. import BufferPoint from "./BufferPoint.js";
  6. import Buffer from "../Renderer/Buffer.js";
  7. import BufferUsage from "../Renderer/BufferUsage.js";
  8. import VertexArray from "../Renderer/VertexArray.js";
  9. import ComponentDatatype from "../Core/ComponentDatatype.js";
  10. import RenderState from "../Renderer/RenderState.js";
  11. import BlendingState from "./BlendingState.js";
  12. import ShaderSource from "../Renderer/ShaderSource.js";
  13. import ShaderProgram from "../Renderer/ShaderProgram.js";
  14. import DrawCommand from "../Renderer/DrawCommand.js";
  15. import Pass from "../Renderer/Pass.js";
  16. import PrimitiveType from "../Core/PrimitiveType.js";
  17. import BufferPointMaterialVS from "../Shaders/BufferPointMaterialVS.js";
  18. import BufferPointMaterialFS from "../Shaders/BufferPointMaterialFS.js";
  19. import EncodedCartesian3 from "../Core/EncodedCartesian3.js";
  20. import AttributeCompression from "../Core/AttributeCompression.js";
  21. import BufferPointMaterial from "./BufferPointMaterial.js";
  22. import BlendOption from "./BlendOption.js";
  23. /** @import FrameState from "./FrameState.js"; */
  24. /** @import BufferPointCollection from "./BufferPointCollection.js"; */
  25. /** @import {TypedArray} from "../Core/globalTypes.js"; */
  26. /**
  27. * TODO(PR#13211): Need 'keyof' syntax to avoid duplicating attribute names.
  28. * @typedef {'positionHigh' | 'positionLow' | 'pickColor' | 'showSizeColorAlpha' | 'outlineWidthColorAlpha'} BufferPointAttribute
  29. * @ignore
  30. */
  31. /**
  32. * Attribute locations when using 64-bit position precision.
  33. * @type {Record<BufferPointAttribute, number>}
  34. * @ignore
  35. */
  36. const BufferPointAttributeLocationsFloat64 = {
  37. positionHigh: 0,
  38. positionLow: 1,
  39. pickColor: 2,
  40. showSizeColorAlpha: 3,
  41. outlineWidthColorAlpha: 4,
  42. };
  43. /**
  44. * Attribute locations when using <= 32-bit position precision.
  45. * @type {Record<string, number>}
  46. * @ignore
  47. */
  48. const BufferPointAttributeLocations = {
  49. position: 0,
  50. pickColor: 1,
  51. showSizeColorAlpha: 2,
  52. outlineWidthColorAlpha: 3,
  53. };
  54. /**
  55. * @typedef {object} BufferPointRenderContext
  56. * @property {VertexArray} [vertexArray]
  57. * @property {Record<string, TypedArray>} [attributeArrays]
  58. * @property {RenderState} [renderState]
  59. * @property {ShaderProgram} [shaderProgram]
  60. * @property {DrawCommand} [command]
  61. * @property {Function} destroy
  62. * @ignore
  63. */
  64. // Scratch variables.
  65. const point = new BufferPoint();
  66. const material = new BufferPointMaterial();
  67. const pickColor = new Color();
  68. const cartesian = new Cartesian3();
  69. const encodedCartesian = new EncodedCartesian3();
  70. /**
  71. * @param {BufferPointCollection} collection
  72. * @param {FrameState} frameState
  73. * @param {BufferPointRenderContext} [renderContext]
  74. * @returns {BufferPointRenderContext}
  75. * @ignore
  76. */
  77. function renderBufferPointCollection(collection, frameState, renderContext) {
  78. const context = frameState.context;
  79. renderContext = renderContext || { destroy: destroyRenderContext };
  80. const useFloat64 = collection._positionDatatype === ComponentDatatype.DOUBLE;
  81. const attributeLocations = useFloat64
  82. ? BufferPointAttributeLocationsFloat64
  83. : BufferPointAttributeLocations;
  84. if (!defined(renderContext.attributeArrays)) {
  85. const featureCountMax = collection.primitiveCountMax;
  86. renderContext.attributeArrays = {
  87. ...(useFloat64
  88. ? {
  89. positionHigh: new Float32Array(featureCountMax * 3),
  90. positionLow: new Float32Array(featureCountMax * 3),
  91. }
  92. : { position: collection._positionView }),
  93. pickColor: new Uint8Array(featureCountMax * 4),
  94. showSizeColorAlpha: new Float32Array(featureCountMax * 4),
  95. outlineWidthColorAlpha: new Float32Array(featureCountMax * 3),
  96. };
  97. }
  98. if (collection._dirtyCount > 0) {
  99. const { attributeArrays } = renderContext;
  100. const pickColorArray = attributeArrays.pickColor;
  101. const showSizeColorAlphaArray = attributeArrays.showSizeColorAlpha;
  102. const outlineWidthColorAlphaArray = attributeArrays.outlineWidthColorAlpha;
  103. const { _dirtyOffset, _dirtyCount } = collection;
  104. for (let i = _dirtyOffset, il = _dirtyOffset + _dirtyCount; i < il; i++) {
  105. collection.get(i, point);
  106. if (!point._dirty) {
  107. continue;
  108. }
  109. if (useFloat64) {
  110. point.getPosition(cartesian);
  111. EncodedCartesian3.fromCartesian(cartesian, encodedCartesian);
  112. attributeArrays.positionHigh[i * 3] = encodedCartesian.high.x;
  113. attributeArrays.positionHigh[i * 3 + 1] = encodedCartesian.high.y;
  114. attributeArrays.positionHigh[i * 3 + 2] = encodedCartesian.high.z;
  115. attributeArrays.positionLow[i * 3] = encodedCartesian.low.x;
  116. attributeArrays.positionLow[i * 3 + 1] = encodedCartesian.low.y;
  117. attributeArrays.positionLow[i * 3 + 2] = encodedCartesian.low.z;
  118. }
  119. point.getMaterial(material);
  120. Color.fromRgba(point._pickId, pickColor);
  121. pickColorArray[i * 4] = Color.floatToByte(pickColor.red);
  122. pickColorArray[i * 4 + 1] = Color.floatToByte(pickColor.green);
  123. pickColorArray[i * 4 + 2] = Color.floatToByte(pickColor.blue);
  124. pickColorArray[i * 4 + 3] = Color.floatToByte(pickColor.alpha);
  125. showSizeColorAlphaArray[i * 4] = point.show ? 1 : 0;
  126. showSizeColorAlphaArray[i * 4 + 1] = material.size;
  127. showSizeColorAlphaArray[i * 4 + 2] = AttributeCompression.encodeRGB8(
  128. material.color,
  129. );
  130. showSizeColorAlphaArray[i * 4 + 3] = material.color.alpha;
  131. outlineWidthColorAlphaArray[i * 3] = material.outlineWidth;
  132. outlineWidthColorAlphaArray[i * 3 + 1] = AttributeCompression.encodeRGB8(
  133. material.outlineColor,
  134. );
  135. outlineWidthColorAlphaArray[i * 3 + 2] = material.outlineColor.alpha;
  136. point._dirty = false;
  137. }
  138. }
  139. if (!defined(renderContext.vertexArray)) {
  140. const { attributeArrays } = renderContext;
  141. renderContext.vertexArray = new VertexArray({
  142. context,
  143. attributes: [
  144. ...(!useFloat64
  145. ? [
  146. {
  147. index: BufferPointAttributeLocations.position,
  148. componentDatatype: collection._positionDatatype,
  149. componentsPerAttribute: 3,
  150. normalize: collection._positionNormalized,
  151. vertexBuffer: Buffer.createVertexBuffer({
  152. typedArray: collection._positionView,
  153. context,
  154. usage: BufferUsage.STATIC_DRAW,
  155. }),
  156. },
  157. ]
  158. : [
  159. {
  160. index: BufferPointAttributeLocationsFloat64.positionHigh,
  161. componentDatatype: ComponentDatatype.FLOAT,
  162. componentsPerAttribute: 3,
  163. vertexBuffer: Buffer.createVertexBuffer({
  164. typedArray: attributeArrays.positionHigh,
  165. context,
  166. usage: BufferUsage.STATIC_DRAW,
  167. }),
  168. },
  169. {
  170. index: BufferPointAttributeLocationsFloat64.positionLow,
  171. componentDatatype: ComponentDatatype.FLOAT,
  172. componentsPerAttribute: 3,
  173. vertexBuffer: Buffer.createVertexBuffer({
  174. typedArray: attributeArrays.positionLow,
  175. context,
  176. usage: BufferUsage.STATIC_DRAW,
  177. }),
  178. },
  179. ]),
  180. {
  181. index: attributeLocations.pickColor,
  182. componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
  183. componentsPerAttribute: 4,
  184. vertexBuffer: Buffer.createVertexBuffer({
  185. typedArray: attributeArrays.pickColor,
  186. context,
  187. usage: BufferUsage.STATIC_DRAW,
  188. }),
  189. },
  190. {
  191. index: attributeLocations.showSizeColorAlpha,
  192. componentDatatype: ComponentDatatype.FLOAT,
  193. componentsPerAttribute: 4,
  194. vertexBuffer: Buffer.createVertexBuffer({
  195. typedArray: attributeArrays.showSizeColorAlpha,
  196. context,
  197. usage: BufferUsage.STATIC_DRAW,
  198. }),
  199. },
  200. {
  201. index: attributeLocations.outlineWidthColorAlpha,
  202. componentDatatype: ComponentDatatype.FLOAT,
  203. componentsPerAttribute: 3,
  204. vertexBuffer: Buffer.createVertexBuffer({
  205. typedArray: attributeArrays.outlineWidthColorAlpha,
  206. context,
  207. usage: BufferUsage.STATIC_DRAW,
  208. }),
  209. },
  210. ],
  211. });
  212. } else if (collection._dirtyCount > 0) {
  213. for (const key in attributeLocations) {
  214. if (Object.hasOwn(attributeLocations, key)) {
  215. const attribute = /** @type {BufferPointAttribute} */ (key);
  216. renderContext.vertexArray.copyAttributeFromRange(
  217. attributeLocations[attribute],
  218. renderContext.attributeArrays[attribute],
  219. collection._dirtyOffset,
  220. collection._dirtyCount,
  221. );
  222. }
  223. }
  224. }
  225. if (!defined(renderContext.renderState)) {
  226. renderContext.renderState = RenderState.fromCache({
  227. blending:
  228. collection._blendOption === BlendOption.OPAQUE
  229. ? BlendingState.DISABLED
  230. : BlendingState.ALPHA_BLEND,
  231. depthTest: { enabled: true },
  232. });
  233. }
  234. if (!defined(renderContext.shaderProgram)) {
  235. renderContext.shaderProgram = ShaderProgram.fromCache({
  236. context,
  237. vertexShaderSource: new ShaderSource({
  238. sources: [BufferPointMaterialVS],
  239. defines: useFloat64 ? ["USE_FLOAT64"] : [],
  240. }),
  241. fragmentShaderSource: new ShaderSource({
  242. sources: [BufferPointMaterialFS],
  243. }),
  244. attributeLocations,
  245. });
  246. }
  247. if (!defined(renderContext.command)) {
  248. renderContext.command = new DrawCommand({
  249. vertexArray: renderContext.vertexArray,
  250. renderState: renderContext.renderState,
  251. shaderProgram: renderContext.shaderProgram,
  252. primitiveType: PrimitiveType.POINTS,
  253. pass:
  254. collection._blendOption === BlendOption.OPAQUE
  255. ? Pass.OPAQUE
  256. : Pass.TRANSLUCENT,
  257. pickId: collection._allowPicking ? "v_pickColor" : undefined,
  258. owner: collection,
  259. count: collection.primitiveCount,
  260. modelMatrix: collection.modelMatrix, // shared reference
  261. boundingVolume: collection.boundingVolume, // shared reference
  262. debugShowBoundingVolume: collection.debugShowBoundingVolume,
  263. });
  264. }
  265. const command = renderContext.command;
  266. if (command.count !== collection.primitiveCount) {
  267. command.count = collection.primitiveCount;
  268. }
  269. if (command.debugShowBoundingVolume !== collection.debugShowBoundingVolume) {
  270. command.debugShowBoundingVolume = collection.debugShowBoundingVolume;
  271. }
  272. frameState.commandList.push(command);
  273. collection._dirtyCount = 0;
  274. collection._dirtyOffset = 0;
  275. return renderContext;
  276. }
  277. /**
  278. * Destroys render context resources. Deleting properties from the context
  279. * object isn't necessary, as collection.destroy() will discard the object.
  280. * @ignore
  281. */
  282. function destroyRenderContext() {
  283. const context = /** @type {BufferPointRenderContext} */ (this);
  284. if (defined(context.vertexArray)) {
  285. context.vertexArray.destroy();
  286. }
  287. if (defined(context.shaderProgram)) {
  288. context.shaderProgram.destroy();
  289. }
  290. if (defined(context.renderState)) {
  291. RenderState.removeFromCache(context.renderState);
  292. }
  293. }
  294. export default renderBufferPointCollection;