| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- // @ts-check
-
- import defined from "../Core/defined.js";
- import Cartesian3 from "../Core/Cartesian3.js";
- import Color from "../Core/Color.js";
- import BufferPolygon from "./BufferPolygon.js";
- import Buffer from "../Renderer/Buffer.js";
- import BufferUsage from "../Renderer/BufferUsage.js";
- import VertexArray from "../Renderer/VertexArray.js";
- import ComponentDatatype from "../Core/ComponentDatatype.js";
- import RenderState from "../Renderer/RenderState.js";
- import BlendingState from "./BlendingState.js";
- import ShaderSource from "../Renderer/ShaderSource.js";
- import ShaderProgram from "../Renderer/ShaderProgram.js";
- import DrawCommand from "../Renderer/DrawCommand.js";
- import Pass from "../Renderer/Pass.js";
- import PrimitiveType from "../Core/PrimitiveType.js";
- import BufferPolygonMaterialVS from "../Shaders/BufferPolygonMaterialVS.js";
- import BufferPolygonMaterialFS from "../Shaders/BufferPolygonMaterialFS.js";
- import EncodedCartesian3 from "../Core/EncodedCartesian3.js";
- import AttributeCompression from "../Core/AttributeCompression.js";
- import IndexDatatype from "../Core/IndexDatatype.js";
- import BufferPolygonMaterial from "./BufferPolygonMaterial.js";
- import BlendOption from "./BlendOption.js";
-
- /** @import {TypedArray} from "../Core/globalTypes.js"; */
- /** @import FrameState from "./FrameState.js"; */
- /** @import BufferPolygonCollection from "./BufferPolygonCollection.js"; */
-
- /**
- * TODO(PR#13211): Need 'keyof' syntax to avoid duplicating attribute names.
- * @typedef {'positionHigh' | 'positionLow' | 'pickColor' | 'showColorAlpha'} BufferPolygonAttribute
- * @ignore
- */
-
- /**
- * Attribute locations when using 64-bit position precision.
- * @type {Record<BufferPolygonAttribute, number>}
- * @ignore
- */
- const BufferPolygonAttributeLocationsFloat64 = {
- positionHigh: 0,
- positionLow: 1,
- pickColor: 2,
- showColorAlpha: 3,
- };
-
- /**
- * Attribute locations when using <= 32-bit position precision.
- * @type {Record<string, number>}
- * @ignore
- */
- const BufferPolygonAttributeLocations = {
- position: 0,
- pickColor: 1,
- showColorAlpha: 2,
- };
-
- /**
- * @typedef {object} BufferPolygonRenderContext
- * @property {VertexArray} [vertexArray]
- * @property {Record<string, TypedArray>} [attributeArrays]
- * @property {TypedArray} [indexArray]
- * @property {RenderState} [renderState]
- * @property {ShaderProgram} [shaderProgram]
- * @property {DrawCommand} [command]
- * @property {Function} destroy
- * @ignore
- */
-
- // Scratch variables.
- const polygon = new BufferPolygon();
- const material = new BufferPolygonMaterial();
- const pickColor = new Color();
- const cartesian = new Cartesian3();
- const encodedCartesian = new EncodedCartesian3();
-
- /**
- * @param {BufferPolygonCollection} collection
- * @param {FrameState} frameState
- * @param {BufferPolygonRenderContext} [renderContext]
- * @returns {BufferPolygonRenderContext}
- * @ignore
- */
- function renderBufferPolygonCollection(collection, frameState, renderContext) {
- const context = frameState.context;
- renderContext = renderContext || { destroy: destroyRenderContext };
- const useFloat64 = collection._positionDatatype === ComponentDatatype.DOUBLE;
- const attributeLocations = useFloat64
- ? BufferPolygonAttributeLocationsFloat64
- : BufferPolygonAttributeLocations;
-
- if (
- !defined(renderContext.attributeArrays) ||
- !defined(renderContext.indexArray)
- ) {
- const { vertexCountMax, triangleCountMax } = collection;
-
- // @ts-expect-error Requires https://github.com/CesiumGS/cesium/pull/13203.
- renderContext.indexArray = IndexDatatype.createTypedArray(
- vertexCountMax,
- triangleCountMax * 3,
- );
-
- renderContext.attributeArrays = {
- ...(!useFloat64
- ? { position: collection._positionView }
- : {
- positionHigh: new Float32Array(vertexCountMax * 3),
- positionLow: new Float32Array(vertexCountMax * 3),
- }),
- pickColor: new Uint8Array(vertexCountMax * 4),
- showColorAlpha: new Float32Array(vertexCountMax * 3),
- };
- }
-
- if (collection._dirtyCount > 0) {
- const { attributeArrays } = renderContext;
- const { _dirtyOffset, _dirtyCount } = collection;
-
- const indexArray = renderContext.indexArray;
- const pickColorArray = attributeArrays.pickColor;
- const showColorAlphaArray = attributeArrays.showColorAlpha;
-
- for (let i = _dirtyOffset, il = _dirtyOffset + _dirtyCount; i < il; i++) {
- collection.get(i, polygon);
-
- if (!polygon._dirty) {
- continue;
- }
-
- let tOffset = polygon.triangleOffset;
- let vOffset = polygon.vertexOffset;
-
- const polygonIndexArray = polygon.getTriangles();
-
- // Update index.
- for (let j = 0, jl = polygon.triangleCount; j < jl; j++) {
- indexArray[tOffset * 3] = vOffset + polygonIndexArray[j * 3];
- indexArray[tOffset * 3 + 1] = vOffset + polygonIndexArray[j * 3 + 1];
- indexArray[tOffset * 3 + 2] = vOffset + polygonIndexArray[j * 3 + 2];
-
- tOffset++;
- }
-
- const show = polygon.show;
- const cartesianArray = !useFloat64 ? null : polygon.getPositions();
- polygon.getMaterial(material);
- const encodedColor = AttributeCompression.encodeRGB8(material.color);
- Color.fromRgba(polygon._pickId, pickColor);
-
- // Update vertex arrays.
- for (let j = 0, jl = polygon.vertexCount; j < jl; j++) {
- if (useFloat64) {
- // @ts-expect-error TODO(tsd-jsdoc): See https://github.com/CesiumGS/cesium/pull/13302.
- Cartesian3.fromArray(cartesianArray, j * 3, cartesian);
- EncodedCartesian3.fromCartesian(cartesian, encodedCartesian);
-
- attributeArrays.positionHigh[vOffset * 3] = encodedCartesian.high.x;
- attributeArrays.positionHigh[vOffset * 3 + 1] =
- encodedCartesian.high.y;
- attributeArrays.positionHigh[vOffset * 3 + 2] =
- encodedCartesian.high.z;
-
- attributeArrays.positionLow[vOffset * 3] = encodedCartesian.low.x;
- attributeArrays.positionLow[vOffset * 3 + 1] = encodedCartesian.low.y;
- attributeArrays.positionLow[vOffset * 3 + 2] = encodedCartesian.low.z;
- }
-
- pickColorArray[vOffset * 4] = Color.floatToByte(pickColor.red);
- pickColorArray[vOffset * 4 + 1] = Color.floatToByte(pickColor.green);
- pickColorArray[vOffset * 4 + 2] = Color.floatToByte(pickColor.blue);
- pickColorArray[vOffset * 4 + 3] = Color.floatToByte(pickColor.alpha);
-
- showColorAlphaArray[vOffset * 3] = show ? 1 : 0;
- showColorAlphaArray[vOffset * 3 + 1] = encodedColor;
- showColorAlphaArray[vOffset * 3 + 2] = material.color.alpha;
-
- vOffset++;
- }
-
- polygon._dirty = false;
- }
- }
-
- if (!defined(renderContext.vertexArray)) {
- const { attributeArrays } = renderContext;
-
- renderContext.vertexArray = new VertexArray({
- context,
-
- indexBuffer: Buffer.createIndexBuffer({
- context,
- typedArray: renderContext.indexArray,
- usage: BufferUsage.STATIC_DRAW,
- // @ts-expect-error https://github.com/CesiumGS/cesium/issues/13420
- indexDatatype: IndexDatatype.fromTypedArray(renderContext.indexArray),
- }),
-
- attributes: [
- ...(!useFloat64
- ? [
- {
- index: BufferPolygonAttributeLocations.position,
- componentDatatype: collection._positionDatatype,
- componentsPerAttribute: 3,
- normalize: collection._positionNormalized,
- vertexBuffer: Buffer.createVertexBuffer({
- typedArray: attributeArrays.position,
- context,
- usage: BufferUsage.STATIC_DRAW,
- }),
- },
- ]
- : [
- {
- index: BufferPolygonAttributeLocationsFloat64.positionHigh,
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 3,
- vertexBuffer: Buffer.createVertexBuffer({
- typedArray: attributeArrays.positionHigh,
- context,
- usage: BufferUsage.STATIC_DRAW,
- }),
- },
- {
- index: BufferPolygonAttributeLocationsFloat64.positionLow,
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 3,
- vertexBuffer: Buffer.createVertexBuffer({
- typedArray: attributeArrays.positionLow,
- context,
- usage: BufferUsage.STATIC_DRAW,
- }),
- },
- ]),
- {
- index: attributeLocations.pickColor,
- componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
- componentsPerAttribute: 4,
- vertexBuffer: Buffer.createVertexBuffer({
- typedArray: attributeArrays.pickColor,
- context,
- usage: BufferUsage.STATIC_DRAW,
- }),
- },
- {
- index: attributeLocations.showColorAlpha,
- componentDatatype: ComponentDatatype.FLOAT,
- componentsPerAttribute: 3,
- vertexBuffer: Buffer.createVertexBuffer({
- typedArray: attributeArrays.showColorAlpha,
- context,
- usage: BufferUsage.STATIC_DRAW,
- }),
- },
- ],
- });
- } else if (collection._dirtyCount > 0) {
- const { indexOffset, indexCount, vertexOffset, vertexCount } =
- getPolygonDirtyRanges(collection);
-
- renderContext.vertexArray.copyIndexFromRange(
- renderContext.indexArray,
- indexOffset,
- indexCount,
- );
-
- for (const key in attributeLocations) {
- if (Object.hasOwn(attributeLocations, key)) {
- const attribute = /** @type {BufferPolygonAttribute} */ (key);
- renderContext.vertexArray.copyAttributeFromRange(
- attributeLocations[attribute],
- renderContext.attributeArrays[attribute],
- vertexOffset,
- vertexCount,
- );
- }
- }
- }
-
- if (!defined(renderContext.renderState)) {
- renderContext.renderState = RenderState.fromCache({
- blending:
- collection._blendOption === BlendOption.OPAQUE
- ? BlendingState.DISABLED
- : BlendingState.ALPHA_BLEND,
- depthTest: { enabled: true },
- });
- }
-
- if (!defined(renderContext.shaderProgram)) {
- renderContext.shaderProgram = ShaderProgram.fromCache({
- context,
- vertexShaderSource: new ShaderSource({
- sources: [BufferPolygonMaterialVS],
- defines: useFloat64 ? ["USE_FLOAT64"] : [],
- }),
- fragmentShaderSource: new ShaderSource({
- sources: [BufferPolygonMaterialFS],
- }),
- attributeLocations,
- });
- }
-
- const drawCount = collection.triangleCount * 3;
-
- if (!defined(renderContext.command)) {
- renderContext.command = new DrawCommand({
- vertexArray: renderContext.vertexArray,
- renderState: renderContext.renderState,
- shaderProgram: renderContext.shaderProgram,
- primitiveType: PrimitiveType.TRIANGLES,
- pass:
- collection._blendOption === BlendOption.OPAQUE
- ? Pass.OPAQUE
- : Pass.TRANSLUCENT,
- pickId: collection._allowPicking ? "v_pickColor" : undefined,
- owner: collection,
- count: drawCount,
- modelMatrix: collection.modelMatrix, // shared reference
- boundingVolume: collection.boundingVolume, // shared reference
- debugShowBoundingVolume: collection.debugShowBoundingVolume,
- });
- }
-
- const command = renderContext.command;
-
- if (command.count !== drawCount) {
- command.count = drawCount;
- }
-
- if (command.debugShowBoundingVolume !== collection.debugShowBoundingVolume) {
- command.debugShowBoundingVolume = collection.debugShowBoundingVolume;
- }
-
- frameState.commandList.push(command);
-
- collection._dirtyCount = 0;
- collection._dirtyOffset = 0;
-
- return renderContext;
- }
-
- /**
- * Computes dirty ranges for attribute and index buffers in a collection.
- * @param {BufferPolygonCollection} collection
- * @ignore
- */
- function getPolygonDirtyRanges(collection) {
- const { _dirtyOffset, _dirtyCount } = collection;
-
- collection.get(_dirtyOffset, polygon);
- const vertexOffset = polygon.vertexOffset;
- const indexOffset = polygon.triangleOffset * 3;
-
- collection.get(_dirtyOffset + _dirtyCount - 1, polygon);
- const vertexCount = polygon.vertexOffset + polygon.vertexCount - vertexOffset;
- const indexCount =
- (polygon.triangleOffset + polygon.triangleCount) * 3 - indexOffset;
-
- return { indexOffset, indexCount, vertexOffset, vertexCount };
- }
-
- /**
- * Destroys render context resources. Deleting properties from the context
- * object isn't necessary, as collection.destroy() will discard the object.
- * @ignore
- */
- function destroyRenderContext() {
- const context = /** @type {BufferPolygonRenderContext} */ (this);
-
- if (defined(context.vertexArray)) {
- context.vertexArray.destroy();
- }
-
- if (defined(context.shaderProgram)) {
- context.shaderProgram.destroy();
- }
-
- if (defined(context.renderState)) {
- RenderState.removeFromCache(context.renderState);
- }
- }
-
- export default renderBufferPolygonCollection;
|