Skip to content

Commit

Permalink
Merge pull request #8600 from CesiumGS/fix-log-depth
Browse files Browse the repository at this point in the history
Fix log depth woes
  • Loading branch information
lilleyse authored Feb 25, 2020
2 parents d75254a + e979008 commit 178bdcf
Show file tree
Hide file tree
Showing 21 changed files with 179 additions and 149 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Change Log

##### Fixes :wrench:

* Fixed a bug that caused large, nearby geometry to be clipped when using a logarithmic depth buffer, which is the default on most systems. [#8600](https://github.com/CesiumGS/cesium/pull/8600)
* Fixed a bug where tiles would not load if the camera was tracking a moving tileset. [#8598](https://github.com/CesiumGS/cesium/pull/8598)
* Fixed a bug where applying a new 3D Tiles style during a flight would not update all existing tiles. [#8622](https://github.com/CesiumGS/cesium/pull/8622)

Expand Down
34 changes: 15 additions & 19 deletions Source/Renderer/AutomaticUniforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -1132,51 +1132,47 @@ import WebGLConstants from '../Core/WebGLConstants.js';
}),

/**
* The log2 of the current frustums far plane. Used for computing the log depth.
* Gets the far plane's distance from the near plane, plus 1.0.
*
* @alias czm_log2FarDistance
* @alias czm_farDepthFromNearPlusOne
* @namespace
* @glslUniform
*
* @private
*/
czm_log2FarDistance : new AutomaticUniform({
size : 1,
czm_farDepthFromNearPlusOne : new AutomaticUniform({
size: 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.log2FarDistance;
return uniformState.farDepthFromNearPlusOne;
}
}),

/**
* An automatic GLSL uniform containing log2 of the far distance + 1.0.
* This is used when reversing log depth computations.
* Gets the log2 of {@link AutomaticUniforms#czm_farDepthFromNearPlusOne}.
*
* @alias czm_log2FarPlusOne
* @alias czm_oneOverLog2FarDepthFromNearPlusOne
* @namespace
* @glslUniform
*/
czm_log2FarPlusOne : new AutomaticUniform({
size : 1,
czm_log2FarDepthFromNearPlusOne : new AutomaticUniform({
size: 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.log2FarPlusOne;
return uniformState.log2FarDepthFromNearPlusOne;
}
}),

/**
* An automatic GLSL uniform containing log2 of the near distance.
* This is used when writing log depth in the fragment shader.
* Gets 1.0 divided by {@link AutomaticUniforms#czm_log2FarDepthFromNearPlusOne}.
*
* @alias czm_log2NearDistance
* @alias czm_oneOverLog2FarDepthFromNearPlusOne
* @namespace
* @glslUniform
*/
czm_log2NearDistance : new AutomaticUniform({
size : 1,
czm_oneOverLog2FarDepthFromNearPlusOne : new AutomaticUniform({
size: 1,
datatype : WebGLConstants.FLOAT,
getValue : function(uniformState) {
return uniformState.log2NearDistance;
return uniformState.oneOverLog2FarDepthFromNearPlusOne;
}
}),

Expand Down
33 changes: 18 additions & 15 deletions Source/Renderer/UniformState.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ import SunLight from '../Scene/SunLight.js';
this._entireFrustum = new Cartesian2();
this._currentFrustum = new Cartesian2();
this._frustumPlanes = new Cartesian4();
this._log2FarDistance = undefined;
this._log2FarPlusOne = undefined;
this._log2NearDistance = undefined;
this._farDepthFromNearPlusOne = undefined;
this._log2FarDepthFromNearPlusOne = undefined;
this._oneOverLog2FarDepthFromNearPlusOne = undefined;

this._frameState = undefined;
this._temeToPseudoFixed = Matrix3.clone(Matrix4.IDENTITY);
Expand Down Expand Up @@ -638,35 +638,38 @@ import SunLight from '../Scene/SunLight.js';
},

/**
* The log2 of the current frustum's far distance. Used to compute the log depth.
* The far plane's distance from the near plane, plus 1.0.
*
* @memberof UniformState.prototype
* @type {Number}
*/
log2FarDistance : {
farDepthFromNearPlusOne : {
get : function() {
return this._log2FarDistance;
return this._farDepthFromNearPlusOne;
}
},

/**
* The log2 of 1 + the current frustum's far distance. Used to reverse log depth.
* The log2 of {@link UniformState#farDepthFromNearPlusOne}.
*
* @memberof UniformState.prototype
* @type {Number}
*/
log2FarPlusOne : {
log2FarDepthFromNearPlusOne : {
get : function() {
return this._log2FarPlusOne;
return this._log2FarDepthFromNearPlusOne;
}
},

/**
* The log2 current frustum's near distance. Used when writing log depth in the fragment shader.
* 1.0 divided by {@link UniformState#log2FarDepthFromNearPlusOne}.
*
* @memberof UniformState.prototype
* @type {Number}
*/
log2NearDistance : {
oneOverLog2FarDepthFromNearPlusOne : {
get : function() {
return this._log2NearDistance;
return this._oneOverLog2FarDepthFromNearPlusOne;
}
},

Expand Down Expand Up @@ -1110,9 +1113,9 @@ import SunLight from '../Scene/SunLight.js';
this._currentFrustum.x = frustum.near;
this._currentFrustum.y = frustum.far;

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

if (defined(frustum._offCenterFrustum)) {
frustum = frustum._offCenterFrustum;
Expand Down
17 changes: 13 additions & 4 deletions Source/Scene/Cesium3DTileBatchTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -1330,13 +1330,14 @@ import StencilOperation from './StencilOperation.js';
return derivedCommand;
}

function getDisableLogDepthFragmentShaderProgram(context, shaderProgram) {
function getLogDepthPolygonOffsetFragmentShaderProgram(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');
fs.defines.push('POLYGON_OFFSET');

fs.sources.unshift('#ifdef GL_OES_standard_derivatives\n#extension GL_OES_standard_derivatives : enable\n#endif\n');
shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'zBackfaceLogDepth', {
vertexShaderSource : shaderProgram.vertexShaderSource,
fragmentShaderSource : fs,
Expand Down Expand Up @@ -1374,9 +1375,17 @@ import StencilOperation from './StencilOperation.js';
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
derivedCommand.uniformMap = clone(command.uniformMap);

var polygonOffset = new Cartesian2(5.0, 5.0);
derivedCommand.uniformMap.u_polygonOffset = function() {
return polygonOffset;
};

// Make the log depth depth fragment write account for the polygon offset, too.
// Otherwise, the back face commands will cause the higher resolution
// tiles to disappear.
derivedCommand.shaderProgram = getDisableLogDepthFragmentShaderProgram(context, command.shaderProgram);
derivedCommand.shaderProgram = getLogDepthPolygonOffsetFragmentShaderProgram(context, command.shaderProgram);
return derivedCommand;
}

Expand Down
17 changes: 6 additions & 11 deletions Source/Scene/ClassificationPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -533,14 +533,9 @@ import StencilOperation from './StencilOperation.js';
}

var extrudedDefine = classificationPrimitive._extruded ? 'EXTRUDED_GEOMETRY' : '';
// Tesselation on ClassificationPrimitives tends to be low,
// which causes problems when interpolating log depth from vertices.
// So force computing and writing logarithmic depth in the fragment shader.
// Re-enable at far distances to avoid z-fighting.
var disableGlPositionLogDepth = 'ENABLE_GL_POSITION_LOG_DEPTH_AT_HEIGHT';

var vsSource = new ShaderSource({
defines : [extrudedDefine, disableGlPositionLogDepth],
defines : [extrudedDefine],
sources : [vs]
});
var fsSource = new ShaderSource({
Expand All @@ -564,7 +559,7 @@ import StencilOperation from './StencilOperation.js';
vsPick = Primitive._updatePickColorAttribute(vsPick);

var pickFS3D = shadowVolumeAppearance.createPickFragmentShader(false);
var pickVS3D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine, disableGlPositionLogDepth], vsPick, false, frameState.mapProjection);
var pickVS3D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine], vsPick, false, frameState.mapProjection);

classificationPrimitive._spPick = ShaderProgram.replaceCache({
context : context,
Expand All @@ -580,7 +575,7 @@ import StencilOperation from './StencilOperation.js';
var pickProgram2D = context.shaderCache.getDerivedShaderProgram(classificationPrimitive._spPick, '2dPick');
if (!defined(pickProgram2D)) {
var pickFS2D = shadowVolumeAppearance.createPickFragmentShader(true);
var pickVS2D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine, disableGlPositionLogDepth], vsPick, true, frameState.mapProjection);
var pickVS2D = shadowVolumeAppearance.createPickVertexShader([extrudedDefine], vsPick, true, frameState.mapProjection);

pickProgram2D = context.shaderCache.createDerivedShaderProgram(classificationPrimitive._spPick, '2dPick', {
vertexShaderSource : pickVS2D,
Expand All @@ -601,7 +596,7 @@ import StencilOperation from './StencilOperation.js';

vs = Primitive._appendShowToShader(primitive, vs);
vsSource = new ShaderSource({
defines : [extrudedDefine, disableGlPositionLogDepth],
defines : [extrudedDefine],
sources : [vs]
});

Expand All @@ -615,7 +610,7 @@ import StencilOperation from './StencilOperation.js';

// Create a fragment shader that computes only required material hookups using screen space techniques
var fsColorSource = shadowVolumeAppearance.createFragmentShader(false);
var vsColorSource = shadowVolumeAppearance.createVertexShader([extrudedDefine, disableGlPositionLogDepth], vs, false, frameState.mapProjection);
var vsColorSource = shadowVolumeAppearance.createVertexShader([extrudedDefine], vs, false, frameState.mapProjection);

classificationPrimitive._spColor = ShaderProgram.replaceCache({
context : context,
Expand All @@ -632,7 +627,7 @@ import StencilOperation from './StencilOperation.js';
var colorProgram2D = context.shaderCache.getDerivedShaderProgram(classificationPrimitive._spColor, '2dColor');
if (!defined(colorProgram2D)) {
var fsColorSource2D = shadowVolumeAppearance.createFragmentShader(true);
var vsColorSource2D = shadowVolumeAppearance.createVertexShader([extrudedDefine, disableGlPositionLogDepth], vs, true, frameState.mapProjection);
var vsColorSource2D = shadowVolumeAppearance.createVertexShader([extrudedDefine], vs, true, frameState.mapProjection);

colorProgram2D = context.shaderCache.createDerivedShaderProgram(classificationPrimitive._spColor, '2dColor', {
vertexShaderSource : vsColorSource2D,
Expand Down
1 change: 0 additions & 1 deletion Source/Scene/DepthPlane.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ import SceneMode from './SceneMode.js';
fs.sources.push(extension);
fs.defines.push('LOG_DEPTH');
vs.defines.push('LOG_DEPTH');
vs.defines.push('DISABLE_GL_POSITION_LOG_DEPTH');
}

this._sp = ShaderProgram.replaceCache({
Expand Down
2 changes: 1 addition & 1 deletion Source/Scene/EllipsoidPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ import SceneMode from './SceneMode.js';
fs.defines.push('WRITE_DEPTH');
}
if (this._useLogDepth) {
vs.defines.push('LOG_DEPTH', 'DISABLE_GL_POSITION_LOG_DEPTH');
vs.defines.push('LOG_DEPTH');
fs.defines.push('LOG_DEPTH');
fs.sources.push(logDepthExtension);
}
Expand Down
20 changes: 6 additions & 14 deletions Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,6 @@ import SceneMode from './SceneMode.js';
quantizationDefine = 'QUANTIZATION_BITS12';
}

var vertexLogDepth = 0;
var vertexLogDepthDefine = '';
if (!defined(surfaceTile.vertexArray) || !defined(surfaceTile.terrainData) || surfaceTile.terrainData._createdByUpsampling) {
vertexLogDepth = 1;
vertexLogDepthDefine = 'DISABLE_GL_POSITION_LOG_DEPTH';
}

var cartographicLimitRectangleFlag = 0;
var cartographicLimitRectangleDefine = '';
if (clippedByBoundaries) {
Expand Down Expand Up @@ -139,12 +132,11 @@ import SceneMode from './SceneMode.js';
(quantization << 18) |
(applySplit << 19) |
(enableClippingPlanes << 20) |
(vertexLogDepth << 21) |
(cartographicLimitRectangleFlag << 22) |
(imageryCutoutFlag << 23) |
(colorCorrect << 24) |
(highlightFillTile << 25) |
(colorToAlpha << 26);
(cartographicLimitRectangleFlag << 21) |
(imageryCutoutFlag << 22) |
(colorCorrect << 23) |
(highlightFillTile << 24) |
(colorToAlpha << 25);

var currentClippingShaderState = 0;
if (defined(clippingPlanes) && clippingPlanes.length > 0) {
Expand Down Expand Up @@ -176,7 +168,7 @@ import SceneMode from './SceneMode.js';
fs.sources.unshift(getClippingFunction(clippingPlanes, frameState.context)); // Need to go before GlobeFS
}

vs.defines.push(quantizationDefine, vertexLogDepthDefine);
vs.defines.push(quantizationDefine);
fs.defines.push('TEXTURE_UNITS ' + numberOfDayTextures, cartographicLimitRectangleDefine, imageryCutoutDefine);

if (applyBrightness) {
Expand Down
6 changes: 1 addition & 5 deletions Source/Scene/GroundPolylinePrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,7 @@ import StencilOperation from './StencilOperation.js';
// Helps with varying budget.
var fs = primitive._batchTable.getVertexShaderCallback()(PolylineShadowVolumeFS);

// Tesselation on these volumes tends to be low,
// which causes problems when interpolating log depth from vertices.
// So force computing and writing log depth in the fragment shader.
// Re-enable at far distances to avoid z-fighting.
var vsDefines = ['ENABLE_GL_POSITION_LOG_DEPTH_AT_HEIGHT', 'GLOBE_MINIMUM_ALTITUDE ' + frameState.mapProjection.ellipsoid.minimumRadius.toFixed(1)];
var vsDefines = ['GLOBE_MINIMUM_ALTITUDE ' + frameState.mapProjection.ellipsoid.minimumRadius.toFixed(1)];
var colorDefine = '';
var materialShaderSource = '';
if (defined(appearance.material)) {
Expand Down
7 changes: 6 additions & 1 deletion Source/Scene/PointCloudEyeDomeLighting.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,12 @@ import PointCloudEyeDomeLightingShader from '../Shaders/PostProcessStages/PointC
'void main() \n' +
'{ \n' +
' czm_point_cloud_post_process_main(); \n' +
' gl_FragData[1] = czm_packDepth(gl_FragCoord.z); \n' +
'#ifdef LOG_DEPTH\n' +
' czm_writeLogDepth();\n' +
' gl_FragData[1] = czm_packDepth(gl_FragDepthEXT); \n' +
'#else\n' +
' gl_FragData[1] = czm_packDepth(gl_FragCoord.z);\n' +
'#endif\n' +
'}');

shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, 'EC', {
Expand Down
8 changes: 6 additions & 2 deletions Source/Scene/Primitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,12 @@ import ShadowMode from './ShadowMode.js';
'varying float v_WindowZ;\n' +
'void main() {\n' +
' czm_non_depth_clamp_main();\n' +
'#if defined(GL_EXT_frag_depth) && !defined(LOG_DEPTH)\n' +
' gl_FragDepthEXT = min(v_WindowZ * gl_FragCoord.w, 1.0);\n' +
'#if defined(GL_EXT_frag_depth)\n' +
' #if defined(LOG_DEPTH)\n' +
' czm_writeLogDepth();\n' +
' #else\n' +
' gl_FragDepthEXT = min(v_WindowZ * gl_FragCoord.w, 1.0);\n' +
' #endif\n' +
'#endif\n' +
'}\n';
modifiedFS =
Expand Down
16 changes: 12 additions & 4 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -2875,11 +2875,19 @@ import View from './View.js';
environmentState.sunComputeCommand = undefined;
environmentState.moonCommand = undefined;
} else {
if (defined(skyAtmosphere) && defined(globe)) {
skyAtmosphere.setDynamicAtmosphereColor(globe.enableLighting && globe.dynamicAtmosphereLighting, globe.dynamicAtmosphereLightingFromSun);
environmentState.isReadyForAtmosphere = environmentState.isReadyForAtmosphere || globe._surface._tilesToRender.length > 0;
if (defined(skyAtmosphere)) {
if (defined(globe)) {
skyAtmosphere.setDynamicAtmosphereColor(globe.enableLighting && globe.dynamicAtmosphereLighting, globe.dynamicAtmosphereLightingFromSun);
environmentState.isReadyForAtmosphere = environmentState.isReadyForAtmosphere || globe._surface._tilesToRender.length > 0;
}
environmentState.skyAtmosphereCommand = skyAtmosphere.update(frameState);
if (defined(environmentState.skyAtmosphereCommand)) {
this.updateDerivedCommands(environmentState.skyAtmosphereCommand);
}
} else {
environmentState.skyAtmosphereCommand = undefined;
}
environmentState.skyAtmosphereCommand = defined(skyAtmosphere) ? skyAtmosphere.update(frameState) : undefined;

environmentState.skyBoxCommand = defined(this.skyBox) ? this.skyBox.update(frameState, this._hdr) : undefined;
var sunCommands = defined(this.sun) ? this.sun.update(frameState, view.passState, this._hdr) : undefined;
environmentState.sunDrawCommand = defined(sunCommands) ? sunCommands.drawCommand : undefined;
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
2 changes: 2 additions & 0 deletions Source/Shaders/BillboardCollectionFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ void main()
#endif
gl_FragColor = color;

#ifdef LOG_DEPTH
czm_writeLogDepth();
#endif

#ifdef FRAGMENT_DEPTH_CHECK
float temp = v_compressed.y;
Expand Down
Loading

0 comments on commit 178bdcf

Please sign in to comment.