diff --git a/CHANGES.md b/CHANGES.md index 8858b2d78bc..5abb891cc2d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,7 @@ Change Log * Fixed per-feature post processing from sometimes selecting the wrong feature. [#7929](https://github.com/AnalyticalGraphicsInc/cesium/pull/7929) * Fixed labels not showing for individual entities in data sources when clustering is enabled. [#6087](https://github.com/AnalyticalGraphicsInc/cesium/issues/6087) * Fixed a crash for 3D Tiles that have zero volume. [#7945](https://github.com/AnalyticalGraphicsInc/cesium/pull/7945) +* `pickPosition` no longer returns incorrect results on the globe when `scene.globe.depthTestAgainstTerrain` is `false`. [#8207](https://github.com/AnalyticalGraphicsInc/cesium/pull/8207) * 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) * Spread out KMl loading across multiple frames to prevent freezing. [#8195](https://github.com/AnalyticalGraphicsInc/cesium/pull/8195) * Fixed a bug where dynamic polylines did not use the given arcType. [#8191](https://github.com/AnalyticalGraphicsInc/cesium/issues/8191) diff --git a/Source/Scene/PickDepth.js b/Source/Scene/PickDepth.js index 6e643747762..bc1cb627a52 100644 --- a/Source/Scene/PickDepth.js +++ b/Source/Scene/PickDepth.js @@ -28,7 +28,10 @@ define([ this._depthTexture = undefined; this._textureToCopy = undefined; + this._colorTextureMask = undefined; this._copyDepthCommand = undefined; + this._copyDepthCommandRender = undefined; + this._copyDepthCommandPick = undefined; this._useLogDepth = undefined; @@ -112,9 +115,11 @@ define([ } } - function updateCopyCommands(pickDepth, context, depthTexture) { + function updateCopyCommands(pickDepth, context, depthTexture, colorTextureMask) { + var fs; if (!defined(pickDepth._copyDepthCommand)) { - var fs = + // Passthrough depth copy + fs = 'uniform sampler2D u_texture;\n' + 'varying vec2 v_textureCoordinates;\n' + 'void main()\n' + @@ -132,17 +137,76 @@ define([ }); } + if (!defined(pickDepth._copyDepthCommandRender)) { + // If alpha is less than one, use globe depth instead of scene depth. Globe depth will overwrite areas where + // there is translucent geometry or no geometry (like the depth plane). + fs = + 'uniform sampler2D u_texture;\n' + + 'uniform sampler2D u_colorTextureMask;\n' + + 'varying vec2 v_textureCoordinates;\n' + + 'void main()\n' + + '{\n' + + ' vec4 pickDepth = czm_packDepth(texture2D(u_texture, v_textureCoordinates).r);\n' + + ' vec4 globeDepth = texture2D(czm_globeDepthTexture, v_textureCoordinates);\n' + + ' bool mask = texture2D(u_colorTextureMask, v_textureCoordinates).a < 1.0;\n' + + ' gl_FragColor = czm_branchFreeTernary(mask, globeDepth, pickDepth);\n' + + '}\n'; + pickDepth._copyDepthCommandRender = context.createViewportQuadCommand(fs, { + renderState : RenderState.fromCache(), + uniformMap : { + u_texture : function() { + return pickDepth._textureToCopy; + }, + u_colorTextureMask : function() { + return pickDepth._colorTextureMask; + } + }, + owner : pickDepth + }); + } + + if (!defined(pickDepth._copyDepthCommandPick)) { + // If color is (0,0,0,0), use globe depth instead of scene depth. Globe depth will overwrite areas where + // there is no geometry (like the depth plane). + fs = + 'uniform sampler2D u_texture;\n' + + 'uniform sampler2D u_colorTextureMask;\n' + + 'varying vec2 v_textureCoordinates;\n' + + 'void main()\n' + + '{\n' + + ' vec4 pickDepth = czm_packDepth(texture2D(u_texture, v_textureCoordinates).r);\n' + + ' vec4 globeDepth = texture2D(czm_globeDepthTexture, v_textureCoordinates);\n' + + ' bool mask = all(equal(texture2D(u_colorTextureMask, v_textureCoordinates), vec4(0.0)));\n' + + ' gl_FragColor = czm_branchFreeTernary(mask, globeDepth, pickDepth);\n' + + '}\n'; + pickDepth._copyDepthCommandPick = context.createViewportQuadCommand(fs, { + renderState : RenderState.fromCache(), + uniformMap : { + u_texture : function() { + return pickDepth._textureToCopy; + }, + u_colorTextureMask : function() { + return pickDepth._colorTextureMask; + } + }, + owner : pickDepth + }); + } + pickDepth._textureToCopy = depthTexture; + pickDepth._colorTextureMask = colorTextureMask; pickDepth._copyDepthCommand.framebuffer = pickDepth._framebuffer; + pickDepth._copyDepthCommandRender.framebuffer = pickDepth._framebuffer; + pickDepth._copyDepthCommandPick.framebuffer = pickDepth._framebuffer; } PickDepth.prototype.executeDebugPickDepth = function(context, passState, useLogDepth) { executeDebugPickDepth(this, context, passState, useLogDepth); }; - PickDepth.prototype.update = function(context, depthTexture) { + PickDepth.prototype.update = function(context, depthTexture, colorTextureMask) { updateFramebuffers(this, context, depthTexture); - updateCopyCommands(this, context, depthTexture); + updateCopyCommands(this, context, depthTexture, colorTextureMask); }; var scratchPackedDepth = new Cartesian4(); @@ -162,8 +226,14 @@ define([ return Cartesian4.dot(packedDepth, packedDepthScale); }; - PickDepth.prototype.executeCopyDepth = function(context, passState) { - this._copyDepthCommand.execute(context, passState); + PickDepth.prototype.executeCopyDepth = function(context, passState, copyGlobeDepth, picking) { + if (!copyGlobeDepth) { + this._copyDepthCommand.execute(context, passState); + } else if (picking) { + this._copyDepthCommandPick.execute(context, passState); + } else { + this._copyDepthCommandRender.execute(context, passState); + } }; PickDepth.prototype.isDestroyed = function() { @@ -175,6 +245,8 @@ define([ destroyFramebuffers(this); this._copyDepthCommand.shaderProgram = defined(this._copyDepthCommand.shaderProgram) && this._copyDepthCommand.shaderProgram.destroy(); + this._copyDepthCommandRender.shaderProgram = defined(this._copyDepthCommandRender.shaderProgram) && this._copyDepthCommandRender.shaderProgram.destroy(); + this._copyDepthCommandPick.shaderProgram = defined(this._copyDepthCommandPick.shaderProgram) && this._copyDepthCommandPick.shaderProgram.destroy(); return destroyObject(this); }; diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index c45c884e53f..211d815dfc5 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -2484,9 +2484,10 @@ define([ if (context.depthTexture && scene.useDepthPicking && (environmentState.useGlobeDepthFramebuffer || renderTranslucentDepthForPick)) { // PERFORMANCE_IDEA: Use MRT to avoid the extra copy. var depthStencilTexture = renderTranslucentDepthForPick ? passState.framebuffer.depthStencilTexture : globeDepth.framebuffer.depthStencilTexture; + var colorTexture = passState.framebuffer.getColorTexture(0); var pickDepth = scene._picking.getPickDepth(scene, index); - pickDepth.update(context, depthStencilTexture); - pickDepth.executeCopyDepth(context, passState); + pickDepth.update(context, depthStencilTexture, colorTexture); + pickDepth.executeCopyDepth(context, passState, usePrimitiveFramebuffer, picking); } if (usePrimitiveFramebuffer) {