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;
|