379 lines
11 KiB
JavaScript
379 lines
11 KiB
JavaScript
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 ClearCommand from "../Renderer/ClearCommand.js";
|
|
import FramebufferManager from "../Renderer/FramebufferManager.js";
|
|
import PixelDatatype from "../Renderer/PixelDatatype.js";
|
|
import RenderState from "../Renderer/RenderState.js";
|
|
import PassThrough from "../Shaders/PostProcessStages/PassThrough.js";
|
|
import PassThroughDepth from "../Shaders/PostProcessStages/PassThroughDepth.js";
|
|
import BlendingState from "./BlendingState.js";
|
|
import StencilConstants from "./StencilConstants.js";
|
|
import StencilFunction from "./StencilFunction.js";
|
|
import StencilOperation from "./StencilOperation.js";
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function GlobeDepth() {
|
|
this._picking = false;
|
|
this._numSamples = 1;
|
|
this._tempCopyDepthTexture = undefined;
|
|
|
|
this._pickColorFramebuffer = new FramebufferManager({
|
|
depthStencil: true,
|
|
supportsDepthTexture: true,
|
|
});
|
|
this._outputFramebuffer = new FramebufferManager({
|
|
depthStencil: true,
|
|
supportsDepthTexture: true,
|
|
});
|
|
this._copyDepthFramebuffer = new FramebufferManager();
|
|
this._tempCopyDepthFramebuffer = new FramebufferManager();
|
|
this._updateDepthFramebuffer = new FramebufferManager({
|
|
createColorAttachments: false,
|
|
createDepthAttachments: false,
|
|
depthStencil: true,
|
|
});
|
|
|
|
this._clearGlobeColorCommand = undefined;
|
|
this._copyColorCommand = undefined;
|
|
this._copyDepthCommand = undefined;
|
|
this._tempCopyDepthCommand = undefined;
|
|
this._updateDepthCommand = undefined;
|
|
|
|
this._viewport = new BoundingRectangle();
|
|
this._rs = undefined;
|
|
this._rsBlend = undefined;
|
|
this._rsUpdate = undefined;
|
|
|
|
this._useScissorTest = false;
|
|
this._scissorRectangle = undefined;
|
|
|
|
this._useHdr = undefined;
|
|
this._clearGlobeDepth = undefined;
|
|
}
|
|
|
|
Object.defineProperties(GlobeDepth.prototype, {
|
|
colorFramebufferManager: {
|
|
get: function () {
|
|
return this._picking
|
|
? this._pickColorFramebuffer
|
|
: this._outputFramebuffer;
|
|
},
|
|
},
|
|
framebuffer: {
|
|
get: function () {
|
|
return this.colorFramebufferManager.framebuffer;
|
|
},
|
|
},
|
|
depthStencilTexture: {
|
|
get: function () {
|
|
return this.colorFramebufferManager.getDepthStencilTexture();
|
|
},
|
|
},
|
|
picking: {
|
|
get: function () {
|
|
return this._picking;
|
|
},
|
|
set: function (value) {
|
|
this._picking = value;
|
|
},
|
|
},
|
|
});
|
|
|
|
function destroyFramebuffers(globeDepth) {
|
|
globeDepth._pickColorFramebuffer.destroy();
|
|
globeDepth._outputFramebuffer.destroy();
|
|
globeDepth._copyDepthFramebuffer.destroy();
|
|
globeDepth._tempCopyDepthFramebuffer.destroy();
|
|
globeDepth._updateDepthFramebuffer.destroy();
|
|
}
|
|
|
|
function updateCopyCommands(globeDepth, context, width, height, passState) {
|
|
globeDepth._viewport.width = width;
|
|
globeDepth._viewport.height = height;
|
|
|
|
const useScissorTest = !BoundingRectangle.equals(
|
|
globeDepth._viewport,
|
|
passState.viewport
|
|
);
|
|
let updateScissor = useScissorTest !== globeDepth._useScissorTest;
|
|
globeDepth._useScissorTest = useScissorTest;
|
|
|
|
if (
|
|
!BoundingRectangle.equals(globeDepth._scissorRectangle, passState.viewport)
|
|
) {
|
|
globeDepth._scissorRectangle = BoundingRectangle.clone(
|
|
passState.viewport,
|
|
globeDepth._scissorRectangle
|
|
);
|
|
updateScissor = true;
|
|
}
|
|
|
|
if (
|
|
!defined(globeDepth._rs) ||
|
|
!BoundingRectangle.equals(globeDepth._viewport, globeDepth._rs.viewport) ||
|
|
updateScissor
|
|
) {
|
|
globeDepth._rs = RenderState.fromCache({
|
|
viewport: globeDepth._viewport,
|
|
scissorTest: {
|
|
enabled: globeDepth._useScissorTest,
|
|
rectangle: globeDepth._scissorRectangle,
|
|
},
|
|
});
|
|
globeDepth._rsBlend = RenderState.fromCache({
|
|
viewport: globeDepth._viewport,
|
|
scissorTest: {
|
|
enabled: globeDepth._useScissorTest,
|
|
rectangle: globeDepth._scissorRectangle,
|
|
},
|
|
blending: BlendingState.ALPHA_BLEND,
|
|
});
|
|
|
|
// Copy packed depth only if the 3D Tiles bit is set
|
|
globeDepth._rsUpdate = RenderState.fromCache({
|
|
viewport: globeDepth._viewport,
|
|
scissorTest: {
|
|
enabled: globeDepth._useScissorTest,
|
|
rectangle: globeDepth._scissorRectangle,
|
|
},
|
|
stencilTest: {
|
|
enabled: true,
|
|
frontFunction: StencilFunction.EQUAL,
|
|
frontOperation: {
|
|
fail: StencilOperation.KEEP,
|
|
zFail: StencilOperation.KEEP,
|
|
zPass: StencilOperation.KEEP,
|
|
},
|
|
backFunction: StencilFunction.NEVER,
|
|
reference: StencilConstants.CESIUM_3D_TILE_MASK,
|
|
mask: StencilConstants.CESIUM_3D_TILE_MASK,
|
|
},
|
|
});
|
|
}
|
|
|
|
if (!defined(globeDepth._copyDepthCommand)) {
|
|
globeDepth._copyDepthCommand = context.createViewportQuadCommand(
|
|
PassThroughDepth,
|
|
{
|
|
uniformMap: {
|
|
u_depthTexture: function () {
|
|
return globeDepth.colorFramebufferManager.getDepthStencilTexture();
|
|
},
|
|
},
|
|
owner: globeDepth,
|
|
}
|
|
);
|
|
}
|
|
|
|
globeDepth._copyDepthCommand.framebuffer =
|
|
globeDepth._copyDepthFramebuffer.framebuffer;
|
|
globeDepth._copyDepthCommand.renderState = globeDepth._rs;
|
|
|
|
if (!defined(globeDepth._copyColorCommand)) {
|
|
globeDepth._copyColorCommand = context.createViewportQuadCommand(
|
|
PassThrough,
|
|
{
|
|
uniformMap: {
|
|
colorTexture: function () {
|
|
return globeDepth.colorFramebufferManager.getColorTexture();
|
|
},
|
|
},
|
|
owner: globeDepth,
|
|
}
|
|
);
|
|
}
|
|
|
|
globeDepth._copyColorCommand.renderState = globeDepth._rs;
|
|
|
|
if (!defined(globeDepth._tempCopyDepthCommand)) {
|
|
globeDepth._tempCopyDepthCommand = context.createViewportQuadCommand(
|
|
PassThroughDepth,
|
|
{
|
|
uniformMap: {
|
|
u_depthTexture: function () {
|
|
return globeDepth._tempCopyDepthTexture;
|
|
},
|
|
},
|
|
owner: globeDepth,
|
|
}
|
|
);
|
|
}
|
|
|
|
globeDepth._tempCopyDepthCommand.framebuffer =
|
|
globeDepth._tempCopyDepthFramebuffer.framebuffer;
|
|
globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs;
|
|
|
|
if (!defined(globeDepth._updateDepthCommand)) {
|
|
globeDepth._updateDepthCommand = context.createViewportQuadCommand(
|
|
PassThrough,
|
|
{
|
|
uniformMap: {
|
|
colorTexture: function () {
|
|
return globeDepth._tempCopyDepthFramebuffer.getColorTexture();
|
|
},
|
|
},
|
|
owner: globeDepth,
|
|
}
|
|
);
|
|
}
|
|
|
|
globeDepth._updateDepthCommand.framebuffer =
|
|
globeDepth._updateDepthFramebuffer.framebuffer;
|
|
globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate;
|
|
|
|
if (!defined(globeDepth._clearGlobeColorCommand)) {
|
|
globeDepth._clearGlobeColorCommand = new ClearCommand({
|
|
color: new Color(0.0, 0.0, 0.0, 0.0),
|
|
stencil: 0.0,
|
|
owner: globeDepth,
|
|
});
|
|
}
|
|
|
|
globeDepth._clearGlobeColorCommand.framebuffer = globeDepth.framebuffer;
|
|
}
|
|
|
|
GlobeDepth.prototype.update = function (
|
|
context,
|
|
passState,
|
|
viewport,
|
|
numSamples,
|
|
hdr,
|
|
clearGlobeDepth
|
|
) {
|
|
const width = viewport.width;
|
|
const height = viewport.height;
|
|
|
|
const pixelDatatype = hdr
|
|
? context.halfFloatingPointTexture
|
|
? PixelDatatype.HALF_FLOAT
|
|
: PixelDatatype.FLOAT
|
|
: PixelDatatype.UNSIGNED_BYTE;
|
|
this._numSamples = numSamples;
|
|
if (this.picking) {
|
|
this._pickColorFramebuffer.update(context, width, height);
|
|
} else {
|
|
this._outputFramebuffer.update(
|
|
context,
|
|
width,
|
|
height,
|
|
numSamples,
|
|
pixelDatatype
|
|
);
|
|
}
|
|
this._copyDepthFramebuffer.update(context, width, height);
|
|
updateCopyCommands(this, context, width, height, passState);
|
|
context.uniformState.globeDepthTexture = undefined;
|
|
|
|
this._useHdr = hdr;
|
|
this._clearGlobeDepth = clearGlobeDepth;
|
|
};
|
|
|
|
GlobeDepth.prototype.prepareColorTextures = function (context, blitStencil) {
|
|
if (!this.picking && this._numSamples > 1) {
|
|
this._outputFramebuffer.prepareTextures(context, blitStencil);
|
|
}
|
|
};
|
|
|
|
GlobeDepth.prototype.executeCopyDepth = function (context, passState) {
|
|
if (defined(this._copyDepthCommand)) {
|
|
this.prepareColorTextures(context);
|
|
this._copyDepthCommand.execute(context, passState);
|
|
context.uniformState.globeDepthTexture = this._copyDepthFramebuffer.getColorTexture();
|
|
}
|
|
};
|
|
|
|
GlobeDepth.prototype.executeUpdateDepth = function (
|
|
context,
|
|
passState,
|
|
clearGlobeDepth,
|
|
depthTexture
|
|
) {
|
|
const depthTextureToCopy = defined(depthTexture)
|
|
? depthTexture
|
|
: passState.framebuffer.depthStencilTexture;
|
|
if (
|
|
clearGlobeDepth ||
|
|
depthTextureToCopy !== this.colorFramebufferManager.getDepthStencilTexture()
|
|
) {
|
|
// First copy the depth to a temporary globe depth texture, then update the
|
|
// main globe depth texture where the stencil bit for 3D Tiles is set.
|
|
// This preserves the original globe depth except where 3D Tiles is rendered.
|
|
// The additional texture and framebuffer resources are created on demand.
|
|
if (defined(this._updateDepthCommand)) {
|
|
if (
|
|
!defined(this._updateDepthFramebuffer.framebuffer) ||
|
|
this._updateDepthFramebuffer.getDepthStencilTexture() !==
|
|
depthTextureToCopy ||
|
|
this._updateDepthFramebuffer.getColorTexture() !==
|
|
this._copyDepthFramebuffer.getColorTexture()
|
|
) {
|
|
const width = this._copyDepthFramebuffer.getColorTexture().width;
|
|
const height = this._copyDepthFramebuffer.getColorTexture().height;
|
|
this._tempCopyDepthFramebuffer.destroy();
|
|
this._tempCopyDepthFramebuffer.update(context, width, height);
|
|
|
|
const colorTexture = this._copyDepthFramebuffer.getColorTexture();
|
|
this._updateDepthFramebuffer.setColorTexture(colorTexture, 0);
|
|
this._updateDepthFramebuffer.setDepthStencilTexture(depthTextureToCopy);
|
|
this._updateDepthFramebuffer.update(context, width, height);
|
|
|
|
updateCopyCommands(this, context, width, height, passState);
|
|
}
|
|
this._tempCopyDepthTexture = depthTextureToCopy;
|
|
this._tempCopyDepthCommand.execute(context, passState);
|
|
this._updateDepthCommand.execute(context, passState);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Fast path - the depth texture can be copied normally.
|
|
if (defined(this._copyDepthCommand)) {
|
|
this._copyDepthCommand.execute(context, passState);
|
|
}
|
|
};
|
|
|
|
GlobeDepth.prototype.executeCopyColor = function (context, passState) {
|
|
if (defined(this._copyColorCommand)) {
|
|
this._copyColorCommand.execute(context, passState);
|
|
}
|
|
};
|
|
|
|
GlobeDepth.prototype.clear = function (context, passState, clearColor) {
|
|
const clear = this._clearGlobeColorCommand;
|
|
if (defined(clear)) {
|
|
Color.clone(clearColor, clear.color);
|
|
this.colorFramebufferManager.clear(context, clear, passState);
|
|
}
|
|
};
|
|
|
|
GlobeDepth.prototype.isDestroyed = function () {
|
|
return false;
|
|
};
|
|
|
|
GlobeDepth.prototype.destroy = function () {
|
|
destroyFramebuffers(this);
|
|
|
|
if (defined(this._copyColorCommand)) {
|
|
this._copyColorCommand.shaderProgram = this._copyColorCommand.shaderProgram.destroy();
|
|
}
|
|
|
|
if (defined(this._copyDepthCommand)) {
|
|
this._copyDepthCommand.shaderProgram = this._copyDepthCommand.shaderProgram.destroy();
|
|
}
|
|
|
|
if (defined(this._tempCopyDepthCommand)) {
|
|
this._tempCopyDepthCommand.shaderProgram = this._tempCopyDepthCommand.shaderProgram.destroy();
|
|
}
|
|
|
|
if (defined(this._updateDepthCommand)) {
|
|
this._updateDepthCommand.shaderProgram = this._updateDepthCommand.shaderProgram.destroy();
|
|
}
|
|
|
|
return destroyObject(this);
|
|
};
|
|
export default GlobeDepth;
|