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 model 2D z-fighting #3933

Merged
merged 7 commits into from
May 19, 2016
Merged
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 @@ -16,6 +16,7 @@ Change Log
* Fixed a bug that was causing errors to be thrown when picking and terrain was enabled. [#3779](https://github.com/AnalyticalGraphicsInc/cesium/issues/3779)
* Fixed issue where labels were disappearing. [3730](https://github.com/AnalyticalGraphicsInc/cesium/issues/3730)
* Added `CullingVolume.fromBoundingSphere`.
* Added `Scene.nearToFarDistance2D` that determines the size of each frustum of the multifrustum in 2D.

### 1.21 - 2016-05-02

Expand Down
61 changes: 52 additions & 9 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,15 @@ define([
*/
this.farToNearRatio = 1000.0;

/**
* Determines the uniform depth size in meters of each frustum of the multifrustum in 2D. If a primitive or model close
* to the surface shows z-fighting, decreasing this will eliminate the artifact, but decrease performance. On the
* other hand, increasing this will increase performance but may cause z-fighting among primitives close to thesurface.
* @type {Number}
* @default 1.75e6
*/
this.nearToFarDistance2D = 1.75e6;

/**
* This property is for debugging only; it is not for production use.
* <p>
Expand Down Expand Up @@ -581,7 +590,7 @@ define([
var near = camera.frustum.near;
var far = camera.frustum.far;
var numFrustums = Math.ceil(Math.log(far / near) / Math.log(this.farToNearRatio));
updateFrustums(near, far, this.farToNearRatio, numFrustums, this._frustumCommandsList);
updateFrustums(near, far, this.farToNearRatio, numFrustums, this._frustumCommandsList, false, undefined);

// give frameState, camera, and screen space camera controller initial state before rendering
updateFrameState(this, 0.0, JulianDate.now());
Expand Down Expand Up @@ -1086,11 +1095,19 @@ define([
clearPasses(frameState.passes);
}

function updateFrustums(near, far, farToNearRatio, numFrustums, frustumCommandsList) {
function updateFrustums(near, far, farToNearRatio, numFrustums, frustumCommandsList, is2D, nearToFarDistance2D) {
frustumCommandsList.length = numFrustums;
for (var m = 0; m < numFrustums; ++m) {
var curNear = Math.max(near, Math.pow(farToNearRatio, m) * near);
var curFar = Math.min(far, farToNearRatio * curNear);
var curNear;
var curFar;

if (!is2D) {
curNear = Math.max(near, Math.pow(farToNearRatio, m) * near);
curFar = Math.min(far, farToNearRatio * curNear);
} else {
curNear = near + m * nearToFarDistance2D;
curFar = Math.min(far, curNear + nearToFarDistance2D);
}

var frustumCommands = frustumCommandsList[m];
if (!defined(frustumCommands)) {
Expand Down Expand Up @@ -1257,11 +1274,25 @@ define([

// Exploit temporal coherence. If the frustums haven't changed much, use the frustums computed
// last frame, else compute the new frustums and sort them by frustum again.
var is2D = scene.mode === SceneMode.SCENE2D;
var farToNearRatio = scene.farToNearRatio;
var numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio));

var numFrustums;
if (!is2D) {
// The multifrustum for 3D/CV is non-uniformly distributed.
numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio));
} else {
// The multifrustum for 2D is uniformly distributed. To avoid z-fighting in 2D,
// the camera i smoved to just before the frustum and the frustum depth is scaled
// to be in [1.0, nearToFarDistance2D].
far = Math.min(far, camera.position.z + scene.nearToFarDistance2D);
near = Math.min(near, far);
numFrustums = Math.ceil(Math.max(1.0, far - near) / scene.nearToFarDistance2D);
}

if (near !== Number.MAX_VALUE && (numFrustums !== numberOfFrustums || (frustumCommandsList.length !== 0 &&
(near < frustumCommandsList[0].near || far > frustumCommandsList[numberOfFrustums - 1].far)))) {
updateFrustums(near, far, farToNearRatio, numFrustums, frustumCommandsList);
updateFrustums(near, far, farToNearRatio, numFrustums, frustumCommandsList, is2D, scene.nearToFarDistance2D);
createPotentiallyVisibleSet(scene);
}
}
Expand Down Expand Up @@ -1544,6 +1575,8 @@ define([
var clearDepth = scene._depthClearCommand;
var depthPlane = scene._depthPlane;

var height2D = camera.position.z;

// Execute commands in each frustum in back to front order
var j;
var frustumCommandsList = scene._frustumCommandsList;
Expand All @@ -1556,6 +1589,7 @@ define([
// Avoid tearing artifacts between adjacent frustums in the opaque passes
frustum.near = index !== 0 ? frustumCommands.near * OPAQUE_FRUSTUM_NEAR_OFFSET : frustumCommands.near;
frustum.far = frustumCommands.far;
us.updateFrustum(frustum);

var globeDepth = scene.debugShowGlobeDepth ? getDebugGlobeDepth(scene, index) : scene._globeDepth;

Expand All @@ -1565,7 +1599,6 @@ define([
passState.framebuffer = globeDepth.framebuffer;
}

us.updateFrustum(frustum);
clearDepth.execute(context, passState);

us.updatePass(Pass.GLOBE);
Expand Down Expand Up @@ -1598,6 +1631,16 @@ define([
}
}

if (scene.mode === SceneMode.SCENE2D) {
// To avoid z-fighting in 2D, move the camera to just before the frustum
// and scale the frustum depth to be in [1.0, nearToFarDistance2D].
camera.position.z = height2D - frustumCommands.near + 1.0;
frustum.far = Math.max(1.0, frustumCommands.far - frustumCommands.near);
frustum.near = 1.0;
us.update(scene.frameState);
us.updateFrustum(frustum);
}

// Execute commands in order by pass up to the translucent pass.
// Translucent geometry needs special handling (sorting/OIT).
var startPass = Pass.GROUND + 1;
Expand All @@ -1611,7 +1654,7 @@ define([
}
}

if (index !== 0) {
if (index !== 0 && scene.mode !== SceneMode.SCENE2D) {
// Do not overlap frustums in the translucent pass to avoid blending artifacts
frustum.near = frustumCommands.near;
us.updateFrustum(frustum);
Expand Down Expand Up @@ -2522,4 +2565,4 @@ define([
};

return Scene;
});
});