Add existing to tracked
This commit is contained in:
+514
@@ -0,0 +1,514 @@
|
||||
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 useLogDepth = scene.frameState.useLogDepth;
|
||||
const context = scene.context;
|
||||
const framebuffer = passState.framebuffer;
|
||||
|
||||
for (let i = 0; i < commands.length; ++i) {
|
||||
let 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 (let i = 0; i < commands.length; ++i) {
|
||||
let 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, 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 uniformState = context.uniformState;
|
||||
const framebuffer = passState.framebuffer;
|
||||
|
||||
passState.framebuffer = this._accumulationFBO.framebuffer;
|
||||
this._accumulateCommand.execute(context, passState);
|
||||
|
||||
passState.framebuffer = this._drawClassificationFBO.framebuffer;
|
||||
if (this._frustumsDrawn > 1) {
|
||||
this._clearColorCommand.execute(context, passState);
|
||||
}
|
||||
|
||||
uniformState.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION);
|
||||
const swapGlobeDepth = uniformState.globeDepthTexture;
|
||||
uniformState.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, passState);
|
||||
}
|
||||
|
||||
uniformState.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;
|
||||
Reference in New Issue
Block a user