cesium/packages/engine/Source/Scene/TranslucentTileClassificati...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

515 lines
15 KiB
JavaScript
Raw Permalink Normal View History

2021-03-03 04:11:58 +08:00
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";
2021-12-15 03:21:46 +08:00
import FramebufferManager from "../Renderer/FramebufferManager.js";
2021-03-03 04:11:58 +08:00
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) {
2021-12-15 03:21:46 +08:00
this._drawClassificationFBO = new FramebufferManager({
createDepthAttachments: false,
});
this._accumulationFBO = new FramebufferManager({
createDepthAttachments: false,
});
this._packFBO = new FramebufferManager();
2021-03-03 04:11:58 +08:00
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}
2021-03-03 04:11:58 +08:00
* @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) {
2021-12-18 06:19:05 +08:00
transpClass._drawClassificationFBO.destroy();
transpClass._accumulationFBO.destroy();
transpClass._packFBO.destroy();
2021-03-03 04:11:58 +08:00
}
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,
2021-03-05 04:04:48 +08:00
sampler: Sampler.NEAREST,
2021-03-03 04:11:58 +08:00
});
}
2021-12-15 03:21:46 +08:00
function updateFramebuffers(transpClass, context, width, height) {
2021-03-03 04:11:58 +08:00
destroyFramebuffers(transpClass);
2021-12-15 03:21:46 +08:00
transpClass._drawClassificationFBO.setDepthStencilTexture(
transpClass._translucentDepthStencilTexture,
);
2021-12-16 07:50:52 +08:00
transpClass._drawClassificationFBO.update(context, width, height);
2021-03-03 04:11:58 +08:00
2021-12-15 03:21:46 +08:00
transpClass._accumulationFBO.setDepthStencilTexture(
transpClass._translucentDepthStencilTexture,
);
2021-12-16 07:50:52 +08:00
transpClass._accumulationFBO.update(context, width, height);
2021-03-03 04:11:58 +08:00
2021-12-16 07:50:52 +08:00
transpClass._packFBO.update(context, width, height);
2021-03-03 04:11:58 +08:00
}
function updateResources(
transpClass,
context,
passState,
globeDepthStencilTexture,
2021-03-03 04:11:58 +08:00
) {
if (!transpClass.isSupported()) {
return;
}
transpClass._opaqueDepthStencilTexture = globeDepthStencilTexture;
2021-03-03 04:11:58 +08:00
const width = transpClass._opaqueDepthStencilTexture.width;
const height = transpClass._opaqueDepthStencilTexture.height;
2021-12-15 03:21:46 +08:00
if (transpClass._drawClassificationFBO.isDirty(width, height)) {
2021-03-03 04:11:58 +08:00
updateTextures(transpClass, context, width, height);
2021-12-15 03:21:46 +08:00
updateFramebuffers(transpClass, context, width, height);
2021-03-03 04:11:58 +08:00
}
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 () {
2021-12-15 03:21:46 +08:00
return transpClass._packFBO.getColorTexture();
2021-03-03 04:11:58 +08:00
};
}
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 () {
2021-12-15 03:21:46 +08:00
return transpClass._drawClassificationFBO.getColorTexture();
2021-03-03 04:11:58 +08:00
},
};
transpClass._copyCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap,
owner: transpClass,
});
}
if (!defined(transpClass._accumulateCommand)) {
fs = new ShaderSource({
sources: [CompositeTranslucentClassification],
});
uniformMap = {
colorTexture: function () {
2021-12-15 03:21:46 +08:00
return transpClass._drawClassificationFBO.getColorTexture();
2021-03-03 04:11:58 +08:00
},
};
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,
2021-03-03 04:11:58 +08:00
) {
// 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];
2021-03-03 04:11:58 +08:00
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
if (command.depthForTranslucentClassification) {
this._hasTranslucentDepth = true;
break;
}
}
if (!this._hasTranslucentDepth) {
return;
}
updateResources(this, context, passState, globeDepthStencilTexture);
2021-03-03 04:11:58 +08:00
// Get translucent depth
2021-12-15 03:21:46 +08:00
passState.framebuffer = this._drawClassificationFBO.framebuffer;
2021-03-03 04:11:58 +08:00
// Clear depth for multifrustum
this._clearDepthStencilCommand.execute(context, passState);
for (let i = 0; i < commands.length; ++i) {
let command = commands[i];
2021-03-03 04:11:58 +08:00
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
if (!command.depthForTranslucentClassification) {
continue;
}
2021-03-27 05:37:29 +08:00
// Depth-only commands are created for all translucent 3D Tiles commands
const depthOnlyCommand = command.derivedCommands.depth.depthOnlyCommand;
executeCommand(depthOnlyCommand, scene, passState);
2021-03-03 04:11:58 +08:00
}
this._frustumsDrawn += this._hasTranslucentDepth ? 1 : 0;
// Pack depth if any translucent depth commands were performed
if (this._hasTranslucentDepth) {
2021-12-15 03:21:46 +08:00
passState.framebuffer = this._packFBO.framebuffer;
2021-03-03 04:11:58 +08:00
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;
2021-03-03 04:11:58 +08:00
const framebuffer = passState.framebuffer;
2021-12-15 03:21:46 +08:00
passState.framebuffer = this._accumulationFBO.framebuffer;
this._accumulateCommand.execute(context, passState);
2021-03-03 04:11:58 +08:00
2021-12-15 03:21:46 +08:00
passState.framebuffer = this._drawClassificationFBO.framebuffer;
2021-03-24 03:25:19 +08:00
if (this._frustumsDrawn > 1) {
2021-03-03 04:11:58 +08:00
this._clearColorCommand.execute(context, passState);
}
uniformState.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION);
const swapGlobeDepth = uniformState.globeDepthTexture;
uniformState.globeDepthTexture = this._packFBO.getColorTexture();
2021-03-03 04:11:58 +08:00
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);
2021-03-03 04:11:58 +08:00
}
uniformState.globeDepthTexture = swapGlobeDepth;
2021-03-03 04:11:58 +08:00
passState.framebuffer = framebuffer;
if (this._frustumsDrawn === 1) {
return;
}
2021-12-15 03:21:46 +08:00
passState.framebuffer = this._accumulationFBO.framebuffer;
2021-03-03 04:11:58 +08:00
this._accumulateCommand.execute(context, passState);
passState.framebuffer = framebuffer;
};
TranslucentTileClassification.prototype.execute = function (scene, passState) {
if (!this._hasTranslucentDepth) {
return;
}
if (this._frustumsDrawn === 1) {
2021-12-15 03:21:46 +08:00
this._textureToComposite = this._drawClassificationFBO.getColorTexture();
2021-03-03 04:11:58 +08:00
} else {
2021-12-15 03:21:46 +08:00
this._textureToComposite = this._accumulationFBO.getColorTexture();
2021-03-03 04:11:58 +08:00
}
const command = scene.frameState.passes.pick
? this._compositeCommand.derivedCommands.pick
: this._compositeCommand;
command.execute(scene.context, passState);
2021-03-24 23:10:15 +08:00
clear(this, scene, passState);
2021-03-24 03:25:19 +08:00
};
2021-03-24 23:10:15 +08:00
function clear(translucentTileClassification, scene, passState) {
if (!translucentTileClassification._hasTranslucentDepth) {
2021-03-24 03:25:19 +08:00
return;
}
2021-03-03 04:11:58 +08:00
2021-03-24 23:10:15 +08:00
const framebuffer = passState.framebuffer;
2021-12-15 03:21:46 +08:00
passState.framebuffer =
translucentTileClassification._drawClassificationFBO.framebuffer;
2021-03-24 23:10:15 +08:00
translucentTileClassification._clearColorCommand.execute(
scene._context,
passState,
);
passState.framebuffer = framebuffer;
if (translucentTileClassification._frustumsDrawn > 1) {
2021-12-15 03:21:46 +08:00
passState.framebuffer =
translucentTileClassification._accumulationFBO.framebuffer;
2021-03-24 23:10:15 +08:00
translucentTileClassification._clearColorCommand.execute(
scene._context,
passState,
);
2021-03-03 04:11:58 +08:00
}
2021-03-24 23:10:15 +08:00
translucentTileClassification._hasTranslucentDepth = false;
translucentTileClassification._frustumsDrawn = 0;
}
2021-03-03 04:11:58 +08:00
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;