| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 | import BoundingRectangle from "../Core/BoundingRectangle.js";import Color from "../Core/Color.js";import defined from "../Core/defined.js";import destroyObject from "../Core/destroyObject.js";import PixelFormat from "../Core/PixelFormat.js";import ClearCommand from "../Renderer/ClearCommand.js";import DrawCommand from "../Renderer/DrawCommand.js";import FramebufferManager from "../Renderer/FramebufferManager.js";import Pass from "../Renderer/Pass.js";import PixelDatatype from "../Renderer/PixelDatatype.js";import RenderState from "../Renderer/RenderState.js";import Sampler from "../Renderer/Sampler.js";import ShaderSource from "../Renderer/ShaderSource.js";import Texture from "../Renderer/Texture.js";import CompareAndPackTranslucentDepth from "../Shaders/CompareAndPackTranslucentDepth.js";import CompositeTranslucentClassification from "../Shaders/PostProcessStages/CompositeTranslucentClassification.js";import BlendingState from "./BlendingState.js";import StencilConstants from "./StencilConstants.js";import StencilFunction from "./StencilFunction.js";const debugShowPackedDepth = false;/** * Handles buffers, drawing, and deriving commands needed for classifying translucent 3D Tiles. * Uses a depth texture, so classification on translucent 3D Tiles is not available in Internet Explorer. * * @private */function TranslucentTileClassification(context) {  this._drawClassificationFBO = new FramebufferManager({    createDepthAttachments: false,  });  this._accumulationFBO = new FramebufferManager({    createDepthAttachments: false,  });  this._packFBO = new FramebufferManager();  this._opaqueDepthStencilTexture = undefined;  // Reference to either colorTexture or accumulationTexture  this._textureToComposite = undefined;  this._translucentDepthStencilTexture = undefined;  this._packDepthCommand = undefined;  this._accumulateCommand = undefined;  this._compositeCommand = undefined;  this._copyCommand = undefined;  this._clearColorCommand = new ClearCommand({    color: new Color(0.0, 0.0, 0.0, 0.0),    owner: this,  });  this._clearDepthStencilCommand = new ClearCommand({    depth: 1.0,    stencil: 0,    owner: this,  });  this._supported = context.depthTexture;  this._viewport = new BoundingRectangle();  this._rsDepth = undefined;  this._rsAccumulate = undefined;  this._rsComp = undefined;  this._useScissorTest = undefined;  this._scissorRectangle = undefined;  this._hasTranslucentDepth = false;  this._frustumsDrawn = 0;}Object.defineProperties(TranslucentTileClassification.prototype, {  /**   * Gets whether or not translucent depth was rendered.   * @memberof TranslucentTileClassification.prototype   *   * @type {Boolean}   * @readonly   */  hasTranslucentDepth: {    get: function () {      return this._hasTranslucentDepth;    },  },});function destroyTextures(transpClass) {  transpClass._textureToComposite = undefined;  transpClass._translucentDepthStencilTexture =    transpClass._translucentDepthStencilTexture &&    !transpClass._translucentDepthStencilTexture.isDestroyed() &&    transpClass._translucentDepthStencilTexture.destroy();}function destroyFramebuffers(transpClass) {  transpClass._drawClassificationFBO.destroy();  transpClass._accumulationFBO.destroy();  transpClass._packFBO.destroy();}function updateTextures(transpClass, context, width, height) {  destroyTextures(transpClass);  transpClass._translucentDepthStencilTexture = new Texture({    context: context,    width: width,    height: height,    pixelFormat: PixelFormat.DEPTH_STENCIL,    pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,    sampler: Sampler.NEAREST,  });}function updateFramebuffers(transpClass, context, width, height) {  destroyFramebuffers(transpClass);  transpClass._drawClassificationFBO.setDepthStencilTexture(    transpClass._translucentDepthStencilTexture  );  transpClass._drawClassificationFBO.update(context, width, height);  transpClass._accumulationFBO.setDepthStencilTexture(    transpClass._translucentDepthStencilTexture  );  transpClass._accumulationFBO.update(context, width, height);  transpClass._packFBO.update(context, width, height);}function updateResources(  transpClass,  context,  passState,  globeDepthStencilTexture) {  if (!transpClass.isSupported()) {    return;  }  transpClass._opaqueDepthStencilTexture = globeDepthStencilTexture;  const width = transpClass._opaqueDepthStencilTexture.width;  const height = transpClass._opaqueDepthStencilTexture.height;  if (transpClass._drawClassificationFBO.isDirty(width, height)) {    updateTextures(transpClass, context, width, height);    updateFramebuffers(transpClass, context, width, height);  }  let fs;  let uniformMap;  if (!defined(transpClass._packDepthCommand)) {    fs = new ShaderSource({      sources: [CompareAndPackTranslucentDepth],    });    uniformMap = {      u_opaqueDepthTexture: function () {        return transpClass._opaqueDepthStencilTexture;      },      u_translucentDepthTexture: function () {        return transpClass._translucentDepthStencilTexture;      },    };    transpClass._packDepthCommand = context.createViewportQuadCommand(fs, {      uniformMap: uniformMap,      owner: transpClass,    });  }  if (!defined(transpClass._compositeCommand)) {    fs = new ShaderSource({      sources: [CompositeTranslucentClassification],    });    uniformMap = {      colorTexture: function () {        return transpClass._textureToComposite;      },    };    if (debugShowPackedDepth) {      fs.defines = ["DEBUG_SHOW_DEPTH"];      uniformMap.u_packedTranslucentDepth = function () {        return transpClass._packFBO.getColorTexture();      };    }    transpClass._compositeCommand = context.createViewportQuadCommand(fs, {      uniformMap: uniformMap,      owner: transpClass,    });    const compositeCommand = transpClass._compositeCommand;    const compositeProgram = compositeCommand.shaderProgram;    const compositePickProgram = context.shaderCache.createDerivedShaderProgram(      compositeProgram,      "pick",      {        vertexShaderSource: compositeProgram.vertexShaderSource,        fragmentShaderSource: new ShaderSource({          sources: fs.sources,          defines: ["PICK"],        }),        attributeLocations: compositeProgram._attributeLocations,      }    );    const compositePickCommand = DrawCommand.shallowClone(compositeCommand);    compositePickCommand.shaderProgram = compositePickProgram;    compositeCommand.derivedCommands.pick = compositePickCommand;  }  if (!defined(transpClass._copyCommand)) {    fs = new ShaderSource({      sources: [CompositeTranslucentClassification],    });    uniformMap = {      colorTexture: function () {        return transpClass._drawClassificationFBO.getColorTexture();      },    };    transpClass._copyCommand = context.createViewportQuadCommand(fs, {      uniformMap: uniformMap,      owner: transpClass,    });  }  if (!defined(transpClass._accumulateCommand)) {    fs = new ShaderSource({      sources: [CompositeTranslucentClassification],    });    uniformMap = {      colorTexture: function () {        return transpClass._drawClassificationFBO.getColorTexture();      },    };    transpClass._accumulateCommand = context.createViewportQuadCommand(fs, {      uniformMap: uniformMap,      owner: transpClass,    });  }  transpClass._viewport.width = width;  transpClass._viewport.height = height;  const useScissorTest = !BoundingRectangle.equals(    transpClass._viewport,    passState.viewport  );  let updateScissor = useScissorTest !== transpClass._useScissorTest;  transpClass._useScissorTest = useScissorTest;  if (    !BoundingRectangle.equals(transpClass._scissorRectangle, passState.viewport)  ) {    transpClass._scissorRectangle = BoundingRectangle.clone(      passState.viewport,      transpClass._scissorRectangle    );    updateScissor = true;  }  if (    !defined(transpClass._rsDepth) ||    !BoundingRectangle.equals(      transpClass._viewport,      transpClass._rsDepth.viewport    ) ||    updateScissor  ) {    transpClass._rsDepth = RenderState.fromCache({      viewport: transpClass._viewport,      scissorTest: {        enabled: transpClass._useScissorTest,        rectangle: transpClass._scissorRectangle,      },    });  }  if (defined(transpClass._packDepthCommand)) {    transpClass._packDepthCommand.renderState = transpClass._rsDepth;  }  if (    !defined(transpClass._rsAccumulate) ||    !BoundingRectangle.equals(      transpClass._viewport,      transpClass._rsAccumulate.viewport    ) ||    updateScissor  ) {    transpClass._rsAccumulate = RenderState.fromCache({      viewport: transpClass._viewport,      scissorTest: {        enabled: transpClass._useScissorTest,        rectangle: transpClass._scissorRectangle,      },      stencilTest: {        enabled: true,        frontFunction: StencilFunction.EQUAL,        reference: StencilConstants.CESIUM_3D_TILE_MASK,      },    });  }  if (defined(transpClass._accumulateCommand)) {    transpClass._accumulateCommand.renderState = transpClass._rsAccumulate;  }  if (    !defined(transpClass._rsComp) ||    !BoundingRectangle.equals(      transpClass._viewport,      transpClass._rsComp.viewport    ) ||    updateScissor  ) {    transpClass._rsComp = RenderState.fromCache({      viewport: transpClass._viewport,      scissorTest: {        enabled: transpClass._useScissorTest,        rectangle: transpClass._scissorRectangle,      },      blending: BlendingState.ALPHA_BLEND,    });  }  if (defined(transpClass._compositeCommand)) {    transpClass._compositeCommand.renderState = transpClass._rsComp;    transpClass._compositeCommand.derivedCommands.pick.renderState =      transpClass._rsComp;  }}TranslucentTileClassification.prototype.executeTranslucentCommands = function (  scene,  executeCommand,  passState,  commands,  globeDepthStencilTexture) {  // Check for translucent commands that should be classified  const length = commands.length;  let command;  let i;  const useLogDepth = scene.frameState.useLogDepth;  const context = scene.context;  const framebuffer = passState.framebuffer;  for (i = 0; i < length; ++i) {    command = commands[i];    command = useLogDepth ? command.derivedCommands.logDepth.command : command;    if (command.depthForTranslucentClassification) {      this._hasTranslucentDepth = true;      break;    }  }  if (!this._hasTranslucentDepth) {    return;  }  updateResources(this, context, passState, globeDepthStencilTexture);  // Get translucent depth  passState.framebuffer = this._drawClassificationFBO.framebuffer;  // Clear depth for multifrustum  this._clearDepthStencilCommand.execute(context, passState);  for (i = 0; i < length; ++i) {    command = commands[i];    command = useLogDepth ? command.derivedCommands.logDepth.command : command;    if (!command.depthForTranslucentClassification) {      continue;    }    // Depth-only commands are created for all translucent 3D Tiles commands    const depthOnlyCommand = command.derivedCommands.depth.depthOnlyCommand;    executeCommand(depthOnlyCommand, scene, context, passState);  }  this._frustumsDrawn += this._hasTranslucentDepth ? 1 : 0;  // Pack depth if any translucent depth commands were performed  if (this._hasTranslucentDepth) {    passState.framebuffer = this._packFBO.framebuffer;    this._packDepthCommand.execute(context, passState);  }  passState.framebuffer = framebuffer;};TranslucentTileClassification.prototype.executeClassificationCommands = function (  scene,  executeCommand,  passState,  frustumCommands) {  if (!this._hasTranslucentDepth) {    return;  }  const context = scene.context;  const us = context.uniformState;  const framebuffer = passState.framebuffer;  if (this._frustumsDrawn === 2) {    // copy classification from first frustum    passState.framebuffer = this._accumulationFBO.framebuffer;    this._copyCommand.execute(context, passState);  }  passState.framebuffer = this._drawClassificationFBO.framebuffer;  if (this._frustumsDrawn > 1) {    this._clearColorCommand.execute(context, passState);  }  us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION);  const swapGlobeDepth = us.globeDepthTexture;  us.globeDepthTexture = this._packFBO.getColorTexture();  const commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION];  const length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION];  for (let i = 0; i < length; ++i) {    executeCommand(commands[i], scene, context, passState);  }  us.globeDepthTexture = swapGlobeDepth;  passState.framebuffer = framebuffer;  if (this._frustumsDrawn === 1) {    return;  }  passState.framebuffer = this._accumulationFBO.framebuffer;  this._accumulateCommand.execute(context, passState);  passState.framebuffer = framebuffer;};TranslucentTileClassification.prototype.execute = function (scene, passState) {  if (!this._hasTranslucentDepth) {    return;  }  if (this._frustumsDrawn === 1) {    this._textureToComposite = this._drawClassificationFBO.getColorTexture();  } else {    this._textureToComposite = this._accumulationFBO.getColorTexture();  }  const command = scene.frameState.passes.pick    ? this._compositeCommand.derivedCommands.pick    : this._compositeCommand;  command.execute(scene.context, passState);  clear(this, scene, passState);};function clear(translucentTileClassification, scene, passState) {  if (!translucentTileClassification._hasTranslucentDepth) {    return;  }  const framebuffer = passState.framebuffer;  passState.framebuffer =    translucentTileClassification._drawClassificationFBO.framebuffer;  translucentTileClassification._clearColorCommand.execute(    scene._context,    passState  );  passState.framebuffer = framebuffer;  if (translucentTileClassification._frustumsDrawn > 1) {    passState.framebuffer =      translucentTileClassification._accumulationFBO.framebuffer;    translucentTileClassification._clearColorCommand.execute(      scene._context,      passState    );  }  translucentTileClassification._hasTranslucentDepth = false;  translucentTileClassification._frustumsDrawn = 0;}TranslucentTileClassification.prototype.isSupported = function () {  return this._supported;};TranslucentTileClassification.prototype.isDestroyed = function () {  return false;};TranslucentTileClassification.prototype.destroy = function () {  destroyTextures(this);  destroyFramebuffers(this);  if (defined(this._compositeCommand)) {    this._compositeCommand.shaderProgram =      this._compositeCommand.shaderProgram &&      this._compositeCommand.shaderProgram.destroy();  }  if (defined(this._packDepthCommand)) {    this._packDepthCommand.shaderProgram =      this._packDepthCommand.shaderProgram &&      this._packDepthCommand.shaderProgram.destroy();  }  return destroyObject(this);};export default TranslucentTileClassification;
 |