Skip to content

Commit

Permalink
Account for slightly changing log depth equation when reversing. Clea…
Browse files Browse the repository at this point in the history
…nup.
  • Loading branch information
kring committed Feb 6, 2020
1 parent d9ab42c commit ae9bebf
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 12 deletions.
45 changes: 45 additions & 0 deletions Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,51 @@ import WebGLConstants from '../Core/WebGLConstants.js';
}
}),

/**
* Gets the far plane's distance from the near plane, plus 1.0.
*
* @alias czm_farDepthFromNearPlusOne
* @namespace
* @glslUniform
*/
czm_farDepthFromNearPlusOne : new AutomaticUniform({
size: 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.farDepthFromNearPlusOne;
}
}),

/**
* Gets the log2 of {@link AutomaticUniforms#czm_farDepthFromNearPlusOne}.
*
* @alias czm_oneOverLog2FarDepthFromNearPlusOne
* @namespace
* @glslUniform
*/
czm_log2FarDepthFromNearPlusOne : new AutomaticUniform({
size: 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.log2FarDepthFromNearPlusOne;
}
}),

/**
* Gets 1.0 divided by {@link AutomaticUniforms#czm_log2FarDepthFromNearPlusOne}.
*
* @alias czm_oneOverLog2FarDepthFromNearPlusOne
* @namespace
* @glslUniform
*/
czm_oneOverLog2FarDepthFromNearPlusOne : new AutomaticUniform({
size: 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.oneOverLog2FarDepthFromNearPlusOne;
}
}),

/**
* The log2 of the current frustums far plane. Used for computing the log depth.
*
Expand Down
43 changes: 43 additions & 0 deletions Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ import SunLight from '../Scene/SunLight.js';
this._entireFrustum = new Cartesian2();
this._currentFrustum = new Cartesian2();
this._frustumPlanes = new Cartesian4();
this._farDepthFromNearPlusOne = undefined;
this._log2FarDepthFromNearPlusOne = undefined;
this._oneOverLog2FarDepthFromNearPlusOne = undefined;
this._log2FarDistance = undefined;
this._log2FarPlusOne = undefined;
this._log2NearDistance = undefined;
Expand Down Expand Up @@ -637,6 +640,42 @@ import SunLight from '../Scene/SunLight.js';
}
},

/**
* The far plane's distance from the near plane, plus 1.0.
*
* @memberof UniformState.prototype
* @type {Number}
*/
farDepthFromNearPlusOne : {
get : function() {
return this._farDepthFromNearPlusOne;
}
},

/**
* The log2 of {@link UniformState#farDepthFromNearPlusOne}.
*
* @memberof UniformState.prototype
* @type {Number}
*/
log2FarDepthFromNearPlusOne : {
get : function() {
return this._log2FarDepthFromNearPlusOne;
}
},

/**
* 1.0 divided by {@link UniformState#log2FarDepthFromNearPlusOne}.
*
* @memberof UniformState.prototype
* @type {Number}
*/
oneOverLog2FarDepthFromNearPlusOne : {
get : function() {
return this._oneOverLog2FarDepthFromNearPlusOne;
}
},

/**
* The log2 of the current frustum's far distance. Used to compute the log depth.
* @memberof UniformState.prototype
Expand Down Expand Up @@ -1110,6 +1149,10 @@ import SunLight from '../Scene/SunLight.js';
this._currentFrustum.x = frustum.near;
this._currentFrustum.y = frustum.far;

this._farDepthFromNearPlusOne = (frustum.far - frustum.near) + 1.0;
this._log2FarDepthFromNearPlusOne = CesiumMath.log2(this._farDepthFromNearPlusOne);
this._oneOverLog2FarDepthFromNearPlusOne = 1.0 / this._log2FarDepthFromNearPlusOne;

this._log2FarDistance = 2.0 / CesiumMath.log2(frustum.far + 1.0);
this._log2FarPlusOne = CesiumMath.log2(frustum.far + 1.0);
this._log2NearDistance = CesiumMath.log2(frustum.near + 1.0);
Expand Down
5 changes: 3 additions & 2 deletions Source/Scene/SceneTransforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,9 @@ import SceneMode from './SceneMode.js';
// log2(z + 1) / log2( far + 1);
// to perspective form
// (far - far * near / z) / (far - near)
depth = Math.pow(2.0, depth * CesiumMath.log2(far + 1.0)) - 1.0;
depth = far * (1.0 - near / depth) / (far - near);
var log2Depth = depth * uniformState.log2FarDepthFromNearPlusOne;
var depthFromNear = Math.pow(2.0, log2Depth) - 1.0;
depth = far * (1.0 - near / (depthFromNear + near)) / (far - near);
}

var viewport = scene.view.passState.viewport;
Expand Down
5 changes: 3 additions & 2 deletions Source/Shaders/Builtin/Functions/reverseLogDepth.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ float czm_reverseLogDepth(float logZ)
#ifdef LOG_DEPTH
float near = czm_currentFrustum.x;
float far = czm_currentFrustum.y;
logZ = pow(2.0, logZ * czm_log2FarPlusOne) - 1.0;
logZ = far * (1.0 - near / logZ) / (far - near);
float log2Depth = logZ * czm_log2FarDepthFromNearPlusOne;
float depthFromNear = pow(2.0, log2Depth) - 1.0;
return far * (1.0 - near / (depthFromNear + near)) / (far - near);
#endif
return logZ;
}
15 changes: 11 additions & 4 deletions Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* The transform from window to normalized device coordinates is done using components
* of (@link czm_viewport} and {@link czm_viewportTransformation} instead of calculating
* the inverse of <code>czm_viewportTransformation</code>. The transformation from
* normalized device coordinates to clip coordinates is done using <code>positionWC.w</code>,
* normalized device coordinates to clip coordinates is done using <code>fragmentCoordinate.w</code>,
* which is expected to be the scalar used in the perspective divide. The transformation
* from clip to eye coordinates is done using {@link czm_inverseProjection}.
*
Expand All @@ -25,12 +25,16 @@
*/
vec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate)
{
// Reconstruct NDC coordinates
float x = 2.0 * (fragmentCoordinate.x - czm_viewport.x) / czm_viewport.z - 1.0;
float y = 2.0 * (fragmentCoordinate.y - czm_viewport.y) / czm_viewport.w - 1.0;
float z = (fragmentCoordinate.z - czm_viewportTransformation[3][2]) / czm_viewportTransformation[2][2];
vec4 q = vec4(x, y, z, 1.0);

// Reverse the perspective division to obtain clip coordinates.
q /= fragmentCoordinate.w;

// Reverse the projection transformation to obtain eye coordinates.
if (!(czm_inverseProjection == mat4(0.0))) // IE and Edge sometimes do something weird with != between mat4s
{
q = czm_inverseProjection * q;
Expand Down Expand Up @@ -80,10 +84,13 @@ vec4 czm_windowToEyeCoordinates(vec2 fragmentCoordinateXY, float depthOrLogDepth
#ifdef LOG_DEPTH
float near = czm_currentFrustum.x;
float far = czm_currentFrustum.y;
float unscaledDepth = pow(2.0, depthOrLogDepth * czm_log2FarPlusOne) - 1.0;
vec4 windowCoord = vec4(fragmentCoordinateXY, far * (1.0 - near / unscaledDepth) / (far - near), 1.0);
float log2Depth = depthOrLogDepth * czm_log2FarDepthFromNearPlusOne;
float depthFromNear = pow(2.0, log2Depth) - 1.0;
float depthFromCamera = depthFromNear + near;
vec4 windowCoord = vec4(fragmentCoordinateXY, far * (1.0 - near / depthFromCamera) / (far - near), 1.0);
vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
eyeCoordinate.w = 1.0 / unscaledDepth; // Better precision
eyeCoordinate.w = 1.0 / depthFromCamera; // Better precision
return eyeCoordinate;
#else
vec4 windowCoord = vec4(fragmentCoordinateXY, depthOrLogDepth, 1.0);
vec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);
Expand Down
6 changes: 2 additions & 4 deletions Source/Shaders/Builtin/Functions/writeLogDepth.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ uniform vec2 u_polygonOffset;
void czm_writeLogDepth(float depth)
{
#if defined(GL_EXT_frag_depth) && defined(LOG_DEPTH)
float farDepth = 1.0 - czm_currentFrustum.x + czm_currentFrustum.y;

// Discard the vertex if it's not between the near and far planes.
// We allow a bit of epsilon on the near plane comparison because a 1.0
// from the vertex shader (indicating the vertex should be _on_ the near
// plane) will not necessarily come here as exactly 1.0.
if (depth <= 0.9999999 || depth > farDepth) {
if (depth <= 0.9999999 || depth > czm_farDepthFromNearPlusOne) {
discard;
}

Expand All @@ -53,7 +51,7 @@ void czm_writeLogDepth(float depth)

#endif

gl_FragDepthEXT = log2(depth) / log2(farDepth);
gl_FragDepthEXT = log2(depth) * czm_oneOverLog2FarDepthFromNearPlusOne;

#ifdef POLYGON_OFFSET
// Apply the units after the log depth.
Expand Down

0 comments on commit ae9bebf

Please sign in to comment.