cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
512 lines (447 loc) • 22.4 kB
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 PixelFormat from '../Core/PixelFormat.js';
import ClearCommand from '../Renderer/ClearCommand.js';
import Framebuffer from '../Renderer/Framebuffer.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 TextureMagnificationFilter from '../Renderer/TextureMagnificationFilter.js';
import TextureMinificationFilter from '../Renderer/TextureMinificationFilter.js';
import TextureWrap from '../Renderer/TextureWrap.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._globeColorTexture = undefined;
this._primitiveColorTexture = undefined;
this._depthStencilTexture = undefined;
this._globeDepthTexture = undefined;
this._tempGlobeDepthTexture = undefined;
this._tempCopyDepthTexture = undefined;
this._globeColorFramebuffer = undefined;
this._primitiveColorFramebuffer = undefined;
this._copyDepthFramebuffer = undefined;
this._tempCopyDepthFramebuffer = undefined;
this._updateDepthFramebuffer = undefined;
this._clearGlobeColorCommand = undefined;
this._clearPrimitiveColorCommand = undefined;
this._copyColorCommand = undefined;
this._copyDepthCommand = undefined;
this._tempCopyDepthCommand = undefined;
this._updateDepthCommand = undefined;
this._mergeColorCommand = undefined;
this._viewport = new BoundingRectangle();
this._rs = undefined;
this._rsBlend = undefined;
this._rsUpdate = undefined;
this._useScissorTest = false;
this._scissorRectangle = undefined;
this._useLogDepth = undefined;
this._useHdr = undefined;
this._clearGlobeDepth = undefined;
this._debugGlobeDepthViewportCommand = undefined;
}
Object.defineProperties(GlobeDepth.prototype, {
framebuffer : {
get : function() {
return this._globeColorFramebuffer;
}
},
primitiveFramebuffer : {
get : function() {
return this._primitiveColorFramebuffer;
}
}
});
function executeDebugGlobeDepth(globeDepth, context, passState, useLogDepth) {
if (!defined(globeDepth._debugGlobeDepthViewportCommand) || useLogDepth !== globeDepth._useLogDepth) {
var fsSource =
'uniform sampler2D u_depthTexture;\n' +
'varying vec2 v_textureCoordinates;\n' +
'void main()\n' +
'{\n' +
' float z_window = czm_unpackDepth(texture2D(u_depthTexture, v_textureCoordinates));\n' +
' z_window = czm_reverseLogDepth(z_window); \n' +
' float n_range = czm_depthRange.near;\n' +
' float f_range = czm_depthRange.far;\n' +
' float z_ndc = (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n' +
' float scale = pow(z_ndc * 0.5 + 0.5, 8.0);\n' +
' gl_FragColor = vec4(mix(vec3(0.0), vec3(1.0), scale), 1.0);\n' +
'}\n';
var fs = new ShaderSource({
defines : [useLogDepth ? 'LOG_DEPTH' : ''],
sources : [fsSource]
});
globeDepth._debugGlobeDepthViewportCommand = context.createViewportQuadCommand(fs, {
uniformMap : {
u_depthTexture : function() {
return globeDepth._globeDepthTexture;
}
},
owner : globeDepth
});
globeDepth._useLogDepth = useLogDepth;
}
globeDepth._debugGlobeDepthViewportCommand.execute(context, passState);
}
function destroyTextures(globeDepth) {
globeDepth._globeColorTexture = globeDepth._globeColorTexture && !globeDepth._globeColorTexture.isDestroyed() && globeDepth._globeColorTexture.destroy();
globeDepth._depthStencilTexture = globeDepth._depthStencilTexture && !globeDepth._depthStencilTexture.isDestroyed() && globeDepth._depthStencilTexture.destroy();
globeDepth._globeDepthTexture = globeDepth._globeDepthTexture && !globeDepth._globeDepthTexture.isDestroyed() && globeDepth._globeDepthTexture.destroy();
}
function destroyFramebuffers(globeDepth) {
globeDepth._globeColorFramebuffer = globeDepth._globeColorFramebuffer && !globeDepth._globeColorFramebuffer.isDestroyed() && globeDepth._globeColorFramebuffer.destroy();
globeDepth._copyDepthFramebuffer = globeDepth._copyDepthFramebuffer && !globeDepth._copyDepthFramebuffer.isDestroyed() && globeDepth._copyDepthFramebuffer.destroy();
}
function destroyUpdateDepthResources(globeDepth) {
globeDepth._tempCopyDepthFramebuffer = globeDepth._tempCopyDepthFramebuffer && !globeDepth._tempCopyDepthFramebuffer.isDestroyed() && globeDepth._tempCopyDepthFramebuffer.destroy();
globeDepth._updateDepthFramebuffer = globeDepth._updateDepthFramebuffer && !globeDepth._updateDepthFramebuffer.isDestroyed() && globeDepth._updateDepthFramebuffer.destroy();
globeDepth._tempGlobeDepthTexture = globeDepth._tempGlobeDepthTexture && !globeDepth._tempGlobeDepthTexture.isDestroyed() && globeDepth._tempGlobeDepthTexture.destroy();
}
function createUpdateDepthResources(globeDepth, context, width, height, passState) {
globeDepth._tempGlobeDepthTexture = new Texture({
context : context,
width : width,
height : height,
pixelFormat : PixelFormat.RGBA,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
sampler : new Sampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
wrapT : TextureWrap.CLAMP_TO_EDGE,
minificationFilter : TextureMinificationFilter.NEAREST,
magnificationFilter : TextureMagnificationFilter.NEAREST
})
});
globeDepth._tempCopyDepthFramebuffer = new Framebuffer({
context : context,
colorTextures : [globeDepth._tempGlobeDepthTexture],
destroyAttachments : false
});
globeDepth._updateDepthFramebuffer = new Framebuffer({
context : context,
colorTextures : [globeDepth._globeDepthTexture],
depthStencilTexture : passState.framebuffer.depthStencilTexture,
destroyAttachments : false
});
}
function createTextures(globeDepth, context, width, height, hdr) {
var pixelDatatype = hdr ? (context.halfFloatingPointTexture ? PixelDatatype.HALF_FLOAT : PixelDatatype.FLOAT) : PixelDatatype.UNSIGNED_BYTE;
globeDepth._globeColorTexture = new Texture({
context : context,
width : width,
height : height,
pixelFormat : PixelFormat.RGBA,
pixelDatatype : pixelDatatype,
sampler : new Sampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
wrapT : TextureWrap.CLAMP_TO_EDGE,
minificationFilter : TextureMinificationFilter.NEAREST,
magnificationFilter : TextureMagnificationFilter.NEAREST
})
});
globeDepth._depthStencilTexture = new Texture({
context : context,
width : width,
height : height,
pixelFormat : PixelFormat.DEPTH_STENCIL,
pixelDatatype : PixelDatatype.UNSIGNED_INT_24_8
});
globeDepth._globeDepthTexture = new Texture({
context : context,
width : width,
height : height,
pixelFormat : PixelFormat.RGBA,
pixelDatatype : PixelDatatype.UNSIGNED_BYTE,
sampler : new Sampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
wrapT : TextureWrap.CLAMP_TO_EDGE,
minificationFilter : TextureMinificationFilter.NEAREST,
magnificationFilter : TextureMagnificationFilter.NEAREST
})
});
}
function createFramebuffers(globeDepth, context) {
globeDepth._globeColorFramebuffer = new Framebuffer({
context : context,
colorTextures : [globeDepth._globeColorTexture],
depthStencilTexture : globeDepth._depthStencilTexture,
destroyAttachments : false
});
globeDepth._copyDepthFramebuffer = new Framebuffer({
context : context,
colorTextures : [globeDepth._globeDepthTexture],
destroyAttachments : false
});
}
function createPrimitiveFramebuffer(globeDepth, context, width, height, hdr) {
var pixelDatatype = hdr ? (context.halfFloatingPointTexture ? PixelDatatype.HALF_FLOAT : PixelDatatype.FLOAT) : PixelDatatype.UNSIGNED_BYTE;
globeDepth._primitiveColorTexture = new Texture({
context : context,
width : width,
height : height,
pixelFormat : PixelFormat.RGBA,
pixelDatatype : pixelDatatype,
sampler : new Sampler({
wrapS : TextureWrap.CLAMP_TO_EDGE,
wrapT : TextureWrap.CLAMP_TO_EDGE,
minificationFilter : TextureMinificationFilter.NEAREST,
magnificationFilter : TextureMagnificationFilter.NEAREST
})
});
globeDepth._primitiveColorFramebuffer = new Framebuffer({
context : context,
colorTextures : [globeDepth._primitiveColorTexture],
depthStencilTexture : globeDepth._depthStencilTexture,
destroyAttachments : false
});
}
function destroyPrimitiveFramebuffer(globeDepth) {
globeDepth._primitiveColorTexture = globeDepth._primitiveColorTexture && !globeDepth._primitiveColorTexture.isDestroyed() && globeDepth._primitiveColorTexture.destroy();
globeDepth._primitiveColorFramebuffer = globeDepth._primitiveColorFramebuffer && !globeDepth._primitiveColorFramebuffer.isDestroyed() && globeDepth._primitiveColorFramebuffer.destroy();
}
function updateFramebuffers(globeDepth, context, width, height, hdr, clearGlobeDepth) {
var colorTexture = globeDepth._globeColorTexture;
var textureChanged = !defined(colorTexture) || colorTexture.width !== width || colorTexture.height !== height || hdr !== globeDepth._useHdr;
if (textureChanged) {
destroyTextures(globeDepth);
destroyFramebuffers(globeDepth);
createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth);
createFramebuffers(globeDepth, context, clearGlobeDepth);
}
if (textureChanged || clearGlobeDepth !== globeDepth._clearGlobeDepth) {
destroyPrimitiveFramebuffer(globeDepth);
if (clearGlobeDepth) {
createPrimitiveFramebuffer(globeDepth, context, width, height, hdr);
}
}
}
function updateCopyCommands(globeDepth, context, width, height, passState) {
globeDepth._viewport.width = width;
globeDepth._viewport.height = height;
var useScissorTest = !BoundingRectangle.equals(globeDepth._viewport, passState.viewport);
var 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._depthStencilTexture;
}
},
owner : globeDepth
});
}
globeDepth._copyDepthCommand.framebuffer = globeDepth._copyDepthFramebuffer;
globeDepth._copyDepthCommand.renderState = globeDepth._rs;
if (!defined(globeDepth._copyColorCommand)) {
globeDepth._copyColorCommand = context.createViewportQuadCommand(PassThrough, {
uniformMap : {
colorTexture : function() {
return globeDepth._globeColorTexture;
}
},
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;
globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs;
if (!defined(globeDepth._updateDepthCommand)) {
globeDepth._updateDepthCommand = context.createViewportQuadCommand(PassThrough, {
uniformMap : {
colorTexture : function() {
return globeDepth._tempGlobeDepthTexture;
}
},
owner : globeDepth
});
}
globeDepth._updateDepthCommand.framebuffer = globeDepth._updateDepthFramebuffer;
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._globeColorFramebuffer;
if (!defined(globeDepth._clearPrimitiveColorCommand)) {
globeDepth._clearPrimitiveColorCommand = new ClearCommand({
color : new Color(0.0, 0.0, 0.0, 0.0),
stencil : 0.0,
owner : globeDepth
});
}
globeDepth._clearPrimitiveColorCommand.framebuffer = globeDepth._primitiveColorFramebuffer;
if (!defined(globeDepth._mergeColorCommand)) {
globeDepth._mergeColorCommand = context.createViewportQuadCommand(PassThrough, {
uniformMap : {
colorTexture : function() {
return globeDepth._primitiveColorTexture;
}
},
owner : globeDepth
});
}
globeDepth._mergeColorCommand.framebuffer = globeDepth._globeColorFramebuffer;
globeDepth._mergeColorCommand.renderState = globeDepth._rsBlend;
}
GlobeDepth.prototype.executeDebugGlobeDepth = function(context, passState, useLogDepth) {
executeDebugGlobeDepth(this, context, passState, useLogDepth);
};
GlobeDepth.prototype.update = function(context, passState, viewport, hdr, clearGlobeDepth) {
var width = viewport.width;
var height = viewport.height;
updateFramebuffers(this, context, width, height, hdr, clearGlobeDepth);
updateCopyCommands(this, context, width, height, passState);
context.uniformState.globeDepthTexture = undefined;
this._useHdr = hdr;
this._clearGlobeDepth = clearGlobeDepth;
};
GlobeDepth.prototype.executeCopyDepth = function(context, passState) {
if (defined(this._copyDepthCommand)) {
this._copyDepthCommand.execute(context, passState);
context.uniformState.globeDepthTexture = this._globeDepthTexture;
}
};
GlobeDepth.prototype.executeUpdateDepth = function(context, passState, clearGlobeDepth) {
var depthTextureToCopy = passState.framebuffer.depthStencilTexture;
if (clearGlobeDepth || (depthTextureToCopy !== this._depthStencilTexture)) {
// 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) ||
(this._updateDepthFramebuffer.depthStencilTexture !== depthTextureToCopy) ||
(this._updateDepthFramebuffer.getColorTexture(0) !== this._globeDepthTexture)) {
var width = this._globeDepthTexture.width;
var height = this._globeDepthTexture.height;
destroyUpdateDepthResources(this);
createUpdateDepthResources(this, context, width, height, passState);
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.executeMergeColor = function(context, passState) {
if (defined(this._mergeColorCommand)) {
this._mergeColorCommand.execute(context, passState);
}
};
GlobeDepth.prototype.clear = function(context, passState, clearColor) {
var clear = this._clearGlobeColorCommand;
if (defined(clear)) {
Color.clone(clearColor, clear.color);
clear.execute(context, passState);
}
clear = this._clearPrimitiveColorCommand;
if (defined(clear) && defined(this._primitiveColorFramebuffer)) {
clear.execute(context, passState);
}
};
GlobeDepth.prototype.isDestroyed = function() {
return false;
};
GlobeDepth.prototype.destroy = function() {
destroyTextures(this);
destroyFramebuffers(this);
destroyPrimitiveFramebuffer(this);
destroyUpdateDepthResources(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();
}
if (defined(this._mergeColorCommand)) {
this._mergeColorCommand.shaderProgram = this._mergeColorCommand.shaderProgram.destroy();
}
if (defined(this._debugGlobeDepthViewportCommand)) {
this._debugGlobeDepthViewportCommand.shaderProgram = this._debugGlobeDepthViewportCommand.shaderProgram.destroy();
}
return destroyObject(this);
};
export default GlobeDepth;