diff --git a/CHANGES.md b/CHANGES.md index 8d068b31228c..347607b74667 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ Change Log ### 1.63 - 2019-11-01 ##### Fixes :wrench: + +* Fixed seam artifacts when log depth is disabled, `scene.globe.depthTestAgainstTerrain` is false, and primitives are under the globe. [#8205](https://github.com/AnalyticalGraphicsInc/cesium/pull/8205) * Fix dynamic ellipsoids using `innerRadii`, `minimumClock`, `maximumClock`, `minimumCone` or `maximumCone`. [#8277](https://github.com/AnalyticalGraphicsInc/cesium/pull/8277) ### 1.62 - 2019-10-01 diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js index 9dfe4671ec23..7d30cfd48cbc 100644 --- a/Source/Scene/GlobeDepth.js +++ b/Source/Scene/GlobeDepth.js @@ -1,6 +1,7 @@ import BoundingRectangle from '../Core/BoundingRectangle.js'; import Color from '../Core/Color.js'; import defined from '../Core/defined.js'; +import defineProperties from '../Core/defineProperties.js'; import destroyObject from '../Core/destroyObject.js'; import PixelFormat from '../Core/PixelFormat.js'; import ClearCommand from '../Renderer/ClearCommand.js'; @@ -15,6 +16,7 @@ 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'; @@ -23,25 +25,30 @@ import StencilOperation from './StencilOperation.js'; * @private */ function GlobeDepth() { - this._colorTexture = undefined; + this._globeColorTexture = undefined; + this._primitiveColorTexture = undefined; this._depthStencilTexture = undefined; this._globeDepthTexture = undefined; this._tempGlobeDepthTexture = undefined; this._tempCopyDepthTexture = undefined; - this.framebuffer = undefined; + this._globeColorFramebuffer = undefined; + this._primitiveColorFramebuffer = undefined; this._copyDepthFramebuffer = undefined; this._tempCopyDepthFramebuffer = undefined; this._updateDepthFramebuffer = undefined; - this._clearColorCommand = 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; @@ -49,10 +56,24 @@ import StencilOperation from './StencilOperation.js'; this._useLogDepth = undefined; this._useHdr = undefined; + this._clearGlobeDepth = undefined; this._debugGlobeDepthViewportCommand = undefined; } + 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 = @@ -89,13 +110,15 @@ import StencilOperation from './StencilOperation.js'; } function destroyTextures(globeDepth) { - globeDepth._colorTexture = globeDepth._colorTexture && !globeDepth._colorTexture.isDestroyed() && globeDepth._colorTexture.destroy(); + globeDepth._globeColorTexture = globeDepth._globeColorTexture && !globeDepth._globeColorTexture.isDestroyed() && globeDepth._globeColorTexture.destroy(); + globeDepth._primitiveColorTexture = globeDepth._primitiveColorTexture && !globeDepth._primitiveColorTexture.isDestroyed() && globeDepth._primitiveColorTexture.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.framebuffer = globeDepth.framebuffer && !globeDepth.framebuffer.isDestroyed() && globeDepth.framebuffer.destroy(); + globeDepth._globeColorFramebuffer = globeDepth._globeColorFramebuffer && !globeDepth._globeColorFramebuffer.isDestroyed() && globeDepth._globeColorFramebuffer.destroy(); + globeDepth._primitiveColorFramebuffer = globeDepth._primitiveColorFramebuffer && !globeDepth._primitiveColorFramebuffer.isDestroyed() && globeDepth._primitiveColorFramebuffer.destroy(); globeDepth._copyDepthFramebuffer = globeDepth._copyDepthFramebuffer && !globeDepth._copyDepthFramebuffer.isDestroyed() && globeDepth._copyDepthFramebuffer.destroy(); } @@ -132,9 +155,9 @@ import StencilOperation from './StencilOperation.js'; }); } - function createTextures(globeDepth, context, width, height, hdr) { + function createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth) { var pixelDatatype = hdr ? (context.halfFloatingPointTexture ? PixelDatatype.HALF_FLOAT : PixelDatatype.FLOAT) : PixelDatatype.UNSIGNED_BYTE; - globeDepth._colorTexture = new Texture({ + globeDepth._globeColorTexture = new Texture({ context : context, width : width, height : height, @@ -169,12 +192,28 @@ import StencilOperation from './StencilOperation.js'; magnificationFilter : TextureMagnificationFilter.NEAREST }) }); + + if (clearGlobeDepth) { + 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 + }) + }); + } } - function createFramebuffers(globeDepth, context) { - globeDepth.framebuffer = new Framebuffer({ + function createFramebuffers(globeDepth, context, clearGlobeDepth) { + globeDepth._globeColorFramebuffer = new Framebuffer({ context : context, - colorTextures : [globeDepth._colorTexture], + colorTextures : [globeDepth._globeColorTexture], depthStencilTexture : globeDepth._depthStencilTexture, destroyAttachments : false }); @@ -184,16 +223,26 @@ import StencilOperation from './StencilOperation.js'; colorTextures : [globeDepth._globeDepthTexture], destroyAttachments : false }); + + if (clearGlobeDepth) { + globeDepth._primitiveColorFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._primitiveColorTexture], + depthStencilTexture : globeDepth._depthStencilTexture, + destroyAttachments : false + }); + } } - function updateFramebuffers(globeDepth, context, width, height, hdr) { - var colorTexture = globeDepth._colorTexture; - var textureChanged = !defined(colorTexture) || colorTexture.width !== width || colorTexture.height !== height || hdr !== globeDepth._useHdr; - if (!defined(globeDepth.framebuffer) || textureChanged) { + 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 || clearGlobeDepth !== globeDepth._clearGlobeDepth; + if (!defined(globeDepth._globeColorFramebuffer) || textureChanged) { destroyTextures(globeDepth); destroyFramebuffers(globeDepth); - createTextures(globeDepth, context, width, height, hdr); - createFramebuffers(globeDepth, context); + createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth); + createFramebuffers(globeDepth, context, clearGlobeDepth); } } @@ -218,6 +267,15 @@ import StencilOperation from './StencilOperation.js'; 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, @@ -258,7 +316,7 @@ import StencilOperation from './StencilOperation.js'; globeDepth._copyColorCommand = context.createViewportQuadCommand(PassThrough, { uniformMap : { colorTexture : function() { - return globeDepth._colorTexture; + return globeDepth._globeColorTexture; } }, owner : globeDepth @@ -295,30 +353,55 @@ import StencilOperation from './StencilOperation.js'; globeDepth._updateDepthCommand.framebuffer = globeDepth._updateDepthFramebuffer; globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate; - if (!defined(globeDepth._clearColorCommand)) { - globeDepth._clearColorCommand = new ClearCommand({ + 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._clearColorCommand.framebuffer = globeDepth.framebuffer; + 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) { + GlobeDepth.prototype.update = function(context, passState, viewport, hdr, clearGlobeDepth) { var width = viewport.width; var height = viewport.height; - updateFramebuffers(this, context, width, height, hdr); + 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) { @@ -364,12 +447,22 @@ import StencilOperation from './StencilOperation.js'; } }; + 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._clearColorCommand; + 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() { @@ -389,9 +482,20 @@ import StencilOperation from './StencilOperation.js'; this._copyDepthCommand.shaderProgram = this._copyDepthCommand.shaderProgram.destroy(); } - var command = this._debugGlobeDepthViewportCommand; - if (defined(command)) { - command.shaderProgram = command.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); diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index f4654f3e0d1d..bbdd42739e2f 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -619,6 +619,7 @@ import View from './View.js'; originalFramebuffer : undefined, useGlobeDepthFramebuffer : false, + separatePrimitiveFramebuffer : false, useOIT : false, useInvertClassification : false, usePostProcess : false, @@ -2192,8 +2193,12 @@ import View from './View.js'; executeTranslucentCommands = executeTranslucentCommandsFrontToBack; } + var frustumCommandsList = view.frustumCommandsList; + var numFrustums = frustumCommandsList.length; + var clearGlobeDepth = environmentState.clearGlobeDepth; var useDepthPlane = environmentState.useDepthPlane; + var separatePrimitiveFramebuffer = environmentState.separatePrimitiveFramebuffer = (numFrustums > 1) && clearGlobeDepth && environmentState.useGlobeDepthFramebuffer; var clearDepth = scene._depthClearCommand; var clearStencil = scene._stencilClearCommand; var clearClassificationStencil = scene._classificationStencilClearCommand; @@ -2204,9 +2209,6 @@ import View from './View.js'; // Execute commands in each frustum in back to front order var j; - var frustumCommandsList = view.frustumCommandsList; - var numFrustums = frustumCommandsList.length; - for (var i = 0; i < numFrustums; ++i) { var index = numFrustums - i - 1; var frustumCommands = frustumCommandsList[index]; @@ -2228,9 +2230,14 @@ import View from './View.js'; var globeDepth = scene.debugShowGlobeDepth ? getDebugGlobeDepth(scene, index) : view.globeDepth; + if (separatePrimitiveFramebuffer) { + // Render to globe framebuffer in GLOBE pass + passState.framebuffer = globeDepth.framebuffer; + } + var fb; if (scene.debugShowGlobeDepth && defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { - globeDepth.update(context, passState, view.viewport); + globeDepth.update(context, passState, view.viewport, scene._hdr, clearGlobeDepth); globeDepth.clear(context, passState, scene._clearColorCommand.color); fb = passState.framebuffer; passState.framebuffer = globeDepth.framebuffer; @@ -2272,6 +2279,11 @@ import View from './View.js'; } } + if (separatePrimitiveFramebuffer) { + // Render to primitive framebuffer in all other passes + passState.framebuffer = globeDepth.primitiveFramebuffer; + } + if (!environmentState.useInvertClassification || picking) { // Common/fastest path. Draw 3D Tiles and classification normally. @@ -2414,6 +2426,11 @@ import View from './View.js'; pickDepth.executeCopyDepth(context, passState); } + if (separatePrimitiveFramebuffer) { + // Reset framebuffer + passState.framebuffer = globeDepth.framebuffer; + } + if (picking || !usePostProcessSelected) { continue; } @@ -2998,7 +3015,7 @@ import View from './View.js'; // Globe depth is copied for the pick pass to support picking batched geometries in GroundPrimitives. var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer = defined(view.globeDepth); if (useGlobeDepthFramebuffer) { - view.globeDepth.update(context, passState, view.viewport, scene._hdr); + view.globeDepth.update(context, passState, view.viewport, scene._hdr, environmentState.clearGlobeDepth); view.globeDepth.clear(context, passState, clearColor); } @@ -3071,16 +3088,22 @@ import View from './View.js'; var frameState = this._frameState; var environmentState = this._environmentState; var view = this._view; + var globeDepth = view.globeDepth; var useOIT = environmentState.useOIT; var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer; var usePostProcess = environmentState.usePostProcess; var defaultFramebuffer = environmentState.originalFramebuffer; - var globeFramebuffer = useGlobeDepthFramebuffer ? view.globeDepth.framebuffer : undefined; + var globeFramebuffer = useGlobeDepthFramebuffer ? globeDepth.framebuffer : undefined; var sceneFramebuffer = view.sceneFramebuffer.getFramebuffer(); var idFramebuffer = view.sceneFramebuffer.getIdFramebuffer(); + if (environmentState.separatePrimitiveFramebuffer) { + // Merge primitive framebuffer into globe framebuffer + globeDepth.executeMergeColor(context, passState); + } + if (useOIT) { passState.framebuffer = usePostProcess ? sceneFramebuffer : defaultFramebuffer; view.oit.execute(context, passState); @@ -3102,7 +3125,7 @@ import View from './View.js'; if (!useOIT && !usePostProcess && useGlobeDepthFramebuffer) { passState.framebuffer = defaultFramebuffer; - view.globeDepth.executeCopyColor(context, passState); + globeDepth.executeCopyColor(context, passState); } var useLogDepth = frameState.useLogDepth;