Skip to content

Commit

Permalink
Merge pull request #5851 from geoscan/log-depth-buffer
Browse files Browse the repository at this point in the history
Log depth buffer
  • Loading branch information
lilleyse authored Apr 12, 2018
2 parents bb5306a + d7d14a5 commit 50b1d5d
Show file tree
Hide file tree
Showing 71 changed files with 1,143 additions and 385 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Change Log

### 1.45 - 2018-05-01

##### Breaking Changes :mega:
* `Camera.distanceToBoundingSphere` now returns the signed distance to the bounding sphere. Positive values indicate that the bounding sphere is in the positive half-plane of the camera position and view direction while a negative value indicates it is in the negative half-plane.

##### Additions :tada:
* Added option `logDepthBuffer` to `Viewer`. With this option there is typically a single frustum using logarithmic depth rendered. This increases performance by issuing less draw calls to the GPU and helps to avoid artifacts on the connection of two frustums. [#5851](https://github.com/AnalyticalGraphicsInc/cesium/pull/5851)
* When a log depth buffer is supported, the frustum near and far planes default to `0.1` and `1e10` respectively.
* Added `Math.log2` to compute the base 2 logarithm of a number.

##### Fixes :wrench:
* Fixed bugs in `TimeIntervalCollection.removeInterval`. [#6418](https://github.com/AnalyticalGraphicsInc/cesium/pull/6418).
* Fixed glTF support to handle meshes with and without tangent vectors, and with/without morph targets, sharing one material. [#6421](https://github.com/AnalyticalGraphicsInc/cesium/pull/6421)
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
* [Dave Whipps](https://github.com/dwhipps)
* [Geoscan](https://www.geoscan.aero)
* [Andrey Orlov](https://github.com/AndreyOrlov)
* [George Vinokhodov](https://github.com/Vineg)
* [The Imagineers](https://www.theimagineers.com/)
* [Heerco Grond](https://github.com/HeercoGrond)
* [Camptocamp SA](https://www.camptocamp.com/)
Expand Down
12 changes: 12 additions & 0 deletions Source/Core/Math.js
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,18 @@ define([
*/
CesiumMath.cbrt = defined(Math.cbrt) ? Math.cbrt : cbrt;

function log2(x) {
return Math.log(x) * Math.LOG2E;
}

/**
* Finds the base 2 logarithm of a number.
*
* @param {Number} number The number.
* @returns {Number} The result.
*/
CesiumMath.log2 = defined(Math.log2) ? Math.log2 : log2;

/**
* @private
*/
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/OrthographicFrustum.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ define([
* @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
*/
OrthographicFrustum.prototype.equals = function(other) {
if (!defined(other)) {
if (!defined(other) || !(other instanceof OrthographicFrustum)) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/OrthographicOffCenterFrustum.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ define([
* @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
*/
OrthographicOffCenterFrustum.prototype.equals = function(other) {
return (defined(other) &&
return (defined(other) && other instanceof OrthographicOffCenterFrustum &&
this.right === other.right &&
this.left === other.left &&
this.top === other.top &&
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/PerspectiveFrustum.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ define([
* @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
*/
PerspectiveFrustum.prototype.equals = function(other) {
if (!defined(other)) {
if (!defined(other) || !(other instanceof PerspectiveFrustum)) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/PerspectiveOffCenterFrustum.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ define([
* @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
*/
PerspectiveOffCenterFrustum.prototype.equals = function(other) {
return (defined(other) &&
return (defined(other) && other instanceof PerspectiveOffCenterFrustum &&
this.right === other.right &&
this.left === other.left &&
this.top === other.top &&
Expand Down
75 changes: 52 additions & 23 deletions Source/Core/barycentricCoordinates.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ define([
'./Cartesian2',
'./Cartesian3',
'./Check',
'./defined'
'./defined',
'./Math'
], function(
Cartesian2,
Cartesian3,
Check,
defined) {
defined,
CesiumMath) {
'use strict';

var scratchCartesian1 = new Cartesian3();
Expand Down Expand Up @@ -47,34 +49,61 @@ define([
}

// Implementation based on http://www.blackpawn.com/texts/pointinpoly/default.html.
var v0, v1, v2;
var dot00, dot01, dot02, dot11, dot12;
var v0;
var v1;
var v2;
var dot00;
var dot01;
var dot02;
var dot11;
var dot12;

if(!defined(p0.z)) {
v0 = Cartesian2.subtract(p1, p0, scratchCartesian1);
v1 = Cartesian2.subtract(p2, p0, scratchCartesian2);
v2 = Cartesian2.subtract(point, p0, scratchCartesian3);
if (Cartesian2.equalsEpsilon(point, p0, CesiumMath.EPSILON14)) {
return Cartesian3.clone(Cartesian3.UNIT_X, result);
}
if (Cartesian2.equalsEpsilon(point, p1, CesiumMath.EPSILON14)) {
return Cartesian3.clone(Cartesian3.UNIT_Y, result);
}
if (Cartesian2.equalsEpsilon(point, p2, CesiumMath.EPSILON14)) {
return Cartesian3.clone(Cartesian3.UNIT_Z, result);
}

dot00 = Cartesian2.dot(v0, v0);
dot01 = Cartesian2.dot(v0, v1);
dot02 = Cartesian2.dot(v0, v2);
dot11 = Cartesian2.dot(v1, v1);
dot12 = Cartesian2.dot(v1, v2);
v0 = Cartesian2.subtract(p1, p0, scratchCartesian1);
v1 = Cartesian2.subtract(p2, p0, scratchCartesian2);
v2 = Cartesian2.subtract(point, p0, scratchCartesian3);

dot00 = Cartesian2.dot(v0, v0);
dot01 = Cartesian2.dot(v0, v1);
dot02 = Cartesian2.dot(v0, v2);
dot11 = Cartesian2.dot(v1, v1);
dot12 = Cartesian2.dot(v1, v2);
} else {
v0 = Cartesian3.subtract(p1, p0, scratchCartesian1);
v1 = Cartesian3.subtract(p2, p0, scratchCartesian2);
v2 = Cartesian3.subtract(point, p0, scratchCartesian3);
if (Cartesian3.equalsEpsilon(point, p0, CesiumMath.EPSILON14)) {
return Cartesian3.clone(Cartesian3.UNIT_X, result);
}
if (Cartesian3.equalsEpsilon(point, p1, CesiumMath.EPSILON14)) {
return Cartesian3.clone(Cartesian3.UNIT_Y, result);
}
if (Cartesian3.equalsEpsilon(point, p2, CesiumMath.EPSILON14)) {
return Cartesian3.clone(Cartesian3.UNIT_Z, result);
}

v0 = Cartesian3.subtract(p1, p0, scratchCartesian1);
v1 = Cartesian3.subtract(p2, p0, scratchCartesian2);
v2 = Cartesian3.subtract(point, p0, scratchCartesian3);

dot00 = Cartesian3.dot(v0, v0);
dot01 = Cartesian3.dot(v0, v1);
dot02 = Cartesian3.dot(v0, v2);
dot11 = Cartesian3.dot(v1, v1);
dot12 = Cartesian3.dot(v1, v2);
dot00 = Cartesian3.dot(v0, v0);
dot01 = Cartesian3.dot(v0, v1);
dot02 = Cartesian3.dot(v0, v2);
dot11 = Cartesian3.dot(v1, v1);
dot12 = Cartesian3.dot(v1, v2);
}

var q = 1.0 / (dot00 * dot11 - dot01 * dot01);
result.y = (dot11 * dot02 - dot01 * dot12) * q;
result.z = (dot00 * dot12 - dot01 * dot02) * q;
var q = dot00 * dot11 - dot01 * dot01;
var invQ = 1.0 / q;
result.y = (dot11 * dot02 - dot01 * dot12) * invQ;
result.z = (dot00 * dot12 - dot01 * dot02) * invQ;
result.x = 1.0 - result.y - result.z;
return result;
}
Expand Down
16 changes: 16 additions & 0 deletions Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,22 @@ define([
}
}),

/**
* The log of the current frustums far plane. Used for computing the log depth.
*
* @alias czm_logFarDistance
* @glslUniform
*
* @private
*/
czm_logFarDistance : new AutomaticUniform({
size : 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.logFarDistance;
}
}),

/**
* An automatic GLSL uniform representing the sun position in world coordinates.
*
Expand Down
14 changes: 14 additions & 0 deletions Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ define([
this._entireFrustum = new Cartesian2();
this._currentFrustum = new Cartesian2();
this._frustumPlanes = new Cartesian4();
this._logFarDistance = undefined;

this._frameState = undefined;
this._temeToPseudoFixed = Matrix3.clone(Matrix4.IDENTITY);
Expand Down Expand Up @@ -641,6 +642,17 @@ define([
}
},

/**
* The log of the current frustum's far distance. Used to compute the log depth.
* @memberof UniformState.prototype
* @type {Number}
*/
logFarDistance : {
get : function() {
return this._logFarDistance;
}
},

/**
* The the height (<code>x</code>) and the height squared (<code>y</code>)
* in meters of the camera above the 2D world plane. This uniform is only valid
Expand Down Expand Up @@ -987,6 +999,8 @@ define([
this._currentFrustum.x = frustum.near;
this._currentFrustum.y = frustum.far;

this._logFarDistance = 2.0 / CesiumMath.log2(frustum.far + 1.0);

if (defined(frustum._offCenterFrustum)) {
frustum = frustum._offCenterFrustum;
}
Expand Down
17 changes: 13 additions & 4 deletions Source/Scene/Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -2574,10 +2574,13 @@ define([
var scratchProj = new Cartesian3();

/**
* Return the distance from the camera to the front of the bounding sphere.
* Return the signed distance from the camera to the front of the bounding sphere.
* <p>
* Positive values indicate that the bounding sphere is in the positive half-plane of the camera position and view direction while a negative value indicates it is in the negative half-plane.
* </p>
*
* @param {BoundingSphere} boundingSphere The bounding sphere in world coordinates.
* @returns {Number} The distance to the bounding sphere.
* @returns {Number} The signed distance to the bounding sphere.
*/
Camera.prototype.distanceToBoundingSphere = function(boundingSphere) {
//>>includeStart('debug', pragmas.debug);
Expand All @@ -2587,8 +2590,10 @@ define([
//>>includeEnd('debug');

var toCenter = Cartesian3.subtract(this.positionWC, boundingSphere.center, scratchToCenter);
var proj = Cartesian3.multiplyByScalar(this.directionWC, Cartesian3.dot(toCenter, this.directionWC), scratchProj);
return Math.max(0.0, Cartesian3.magnitude(proj) - boundingSphere.radius);
var distance = -Cartesian3.dot(toCenter, this.directionWC);
var proj = Cartesian3.multiplyByScalar(this.directionWC, distance, scratchProj);
var unsignedDistance = Math.max(0.0, Cartesian3.magnitude(proj) - boundingSphere.radius);
return distance < 0.0 ? -unsignedDistance : unsignedDistance;
};

var scratchPixelSize = new Cartesian2();
Expand All @@ -2615,6 +2620,9 @@ define([
//>>includeEnd('debug');

var distance = this.distanceToBoundingSphere(boundingSphere);
if (distance < 0.0) {
return 0.0;
}
var pixelSize = this.frustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, scratchPixelSize);
return Math.max(pixelSize.x, pixelSize.y);
};
Expand Down Expand Up @@ -3229,6 +3237,7 @@ define([
Cartesian3.clone(camera.right, result.right);
Matrix4.clone(camera._transform, result.transform);
result._transformChanged = true;
result.frustum = camera.frustum.clone();

return result;
};
Expand Down
24 changes: 22 additions & 2 deletions Source/Scene/Cesium3DTileBatchTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ define([
if (bivariateVisibilityTest) {
if (command.pass !== Pass.TRANSLUCENT && !finalResolution) {
if (!defined(derivedCommands.zback)) {
derivedCommands.zback = deriveZBackfaceCommand(derivedCommands.originalCommand);
derivedCommands.zback = deriveZBackfaceCommand(frameState.context, derivedCommands.originalCommand);
}
tileset._backfaceCommands.push(derivedCommands.zback);
}
Expand Down Expand Up @@ -1436,7 +1436,24 @@ define([
return derivedCommand;
}

function deriveZBackfaceCommand(command) {
function getDisableLogDepthFragmentShaderProgram(context, shaderProgram) {
var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'zBackfaceLogDepth');
if (!defined(shader)) {
var fs = shaderProgram.fragmentShaderSource.clone();
fs.defines = defined(fs.defines) ? fs.defines.slice(0) : [];
fs.defines.push('DISABLE_LOG_DEPTH_FRAGMENT_WRITE');

shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'zBackfaceLogDepth', {
vertexShaderSource : shaderProgram.vertexShaderSource,
fragmentShaderSource : fs,
attributeLocations : shaderProgram._attributeLocations
});
}

return shader;
}

function deriveZBackfaceCommand(context, command) {
// Write just backface depth of unresolved tiles so resolved stenciled tiles do not appear in front
var derivedCommand = DrawCommand.shallowClone(command);
var rs = clone(derivedCommand.renderState, true);
Expand All @@ -1459,6 +1476,9 @@ define([
derivedCommand.renderState = RenderState.fromCache(rs);
derivedCommand.castShadows = false;
derivedCommand.receiveShadows = false;
// Disable the depth writes in the fragment shader. The back face commands were causing the higher resolution
// tiles to disappear.
derivedCommand.shaderProgram = getDisableLogDepthFragmentShaderProgram(context, command.shaderProgram);
return derivedCommand;
}

Expand Down
28 changes: 19 additions & 9 deletions Source/Scene/ClassificationModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -663,34 +663,38 @@ define([
}

function createProgram(model) {
var positionName = ModelUtility.getAttributeOrUniformBySemantic(model.gltf, 'POSITION');
var batchIdName = ModelUtility.getAttributeOrUniformBySemantic(model.gltf, '_BATCHID');
var gltf = model.gltf;

var positionName = ModelUtility.getAttributeOrUniformBySemantic(gltf, 'POSITION');
var batchIdName = ModelUtility.getAttributeOrUniformBySemantic(gltf, '_BATCHID');

var attributeLocations = {};
attributeLocations[positionName] = 0;
attributeLocations[batchIdName] = 1;

var modelViewProjectionName = ModelUtility.getAttributeOrUniformBySemantic(model.gltf, 'MODELVIEWPROJECTION');
var modelViewProjectionName = ModelUtility.getAttributeOrUniformBySemantic(gltf, 'MODELVIEWPROJECTION');

var uniformDecl;
var computePosition;
var toClip;

if (!defined(modelViewProjectionName)) {
var projectionName = ModelUtility.getAttributeOrUniformBySemantic(model.gltf, 'PROJECTION');
var modelViewName = ModelUtility.getAttributeOrUniformBySemantic(model.gltf, 'MODELVIEW');
var projectionName = ModelUtility.getAttributeOrUniformBySemantic(gltf, 'PROJECTION');
var modelViewName = ModelUtility.getAttributeOrUniformBySemantic(gltf, 'MODELVIEW');
if (!defined(modelViewName)) {
modelViewName = ModelUtility.getAttributeOrUniformBySemantic(model.gltf, 'CESIUM_RTC_MODELVIEW');
modelViewName = ModelUtility.getAttributeOrUniformBySemantic(gltf, 'CESIUM_RTC_MODELVIEW');
}

uniformDecl =
'uniform mat4 ' + modelViewName + ';\n' +
'uniform mat4 ' + projectionName + ';\n';
computePosition = ' vec4 positionInClipCoords = ' + projectionName + ' * ' + modelViewName + ' * vec4(' + positionName + ', 1.0);\n';
toClip = projectionName + ' * ' + modelViewName + ' * vec4(' + positionName + ', 1.0)';
} else {
uniformDecl = 'uniform mat4 ' + modelViewProjectionName + ';\n';
computePosition = ' vec4 positionInClipCoords = ' + modelViewProjectionName + ' * vec4(' + positionName + ', 1.0);\n';
toClip = modelViewProjectionName + ' * vec4(' + positionName + ', 1.0)';
}

var computePosition = ' vec4 positionInClipCoords = ' + toClip + ';\n';

var vs =
'attribute vec3 ' + positionName + ';\n' +
'attribute float ' + batchIdName + ';\n' +
Expand All @@ -716,6 +720,9 @@ define([
var drawVS = modifyShader(vs, model._vertexShaderLoaded);
var drawFS = modifyShader(fs, model._classificationShaderLoaded);

drawVS = ModelUtility.modifyVertexShaderForLogDepth(drawVS, toClip);
drawFS = ModelUtility.modifyFragmentShaderForLogDepth(drawFS);

model._shaderProgram = {
vertexShaderSource : drawVS,
fragmentShaderSource : drawFS,
Expand All @@ -726,6 +733,9 @@ define([
var pickVS = modifyShader(vs, model._pickVertexShaderLoaded);
var pickFS = modifyShader(fs, model._pickFragmentShaderLoaded);

pickVS = ModelUtility.modifyVertexShaderForLogDepth(pickVS, toClip);
pickFS = ModelUtility.modifyFragmentShaderForLogDepth(pickFS);

model._pickShaderProgram = {
vertexShaderSource : pickVS,
fragmentShaderSource : pickFS,
Expand Down
Loading

0 comments on commit 50b1d5d

Please sign in to comment.