Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pickPosition accuracy when depthTestAgainstTerrain is false #8207

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
84 changes: 78 additions & 6 deletions Source/Scene/PickDepth.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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' +
Expand All @@ -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();
Expand All @@ -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() {
Expand All @@ -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);
};
Expand Down
5 changes: 3 additions & 2 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down