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 log depth woes #8600

Merged
merged 19 commits into from
Feb 25, 2020
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 @@ -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