diff --git a/packages/engine/Source/Scene/BillboardCollection.js b/packages/engine/Source/Scene/BillboardCollection.js index 7087dc4915c..23d28da8bf9 100644 --- a/packages/engine/Source/Scene/BillboardCollection.js +++ b/packages/engine/Source/Scene/BillboardCollection.js @@ -13,7 +13,6 @@ import EncodedCartesian3 from "../Core/EncodedCartesian3.js"; import IndexDatatype from "../Core/IndexDatatype.js"; import CesiumMath from "../Core/Math.js"; import Matrix4 from "../Core/Matrix4.js"; -import WebGLConstants from "../Core/WebGLConstants.js"; import Buffer from "../Renderer/Buffer.js"; import BufferUsage from "../Renderer/BufferUsage.js"; import ContextLimits from "../Renderer/ContextLimits.js"; @@ -34,6 +33,7 @@ import SceneMode from "./SceneMode.js"; import SDFSettings from "./SDFSettings.js"; import TextureAtlas from "../Renderer/TextureAtlas.js"; import VerticalOrigin from "./VerticalOrigin.js"; +import Ellipsoid from "../Core/Ellipsoid.js"; const SHOW_INDEX = Billboard.SHOW_INDEX; const POSITION_INDEX = Billboard.POSITION_INDEX; @@ -315,6 +315,8 @@ function BillboardCollection(options) { ]; this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints + this._coarseDepthTestDistance = Ellipsoid.default.minimumRadius / 100; + this._threePointDepthTestDistance = Ellipsoid.default.minimumRadius / 1000; this._uniforms = { u_atlas: () => { @@ -323,6 +325,16 @@ function BillboardCollection(options) { u_highlightColor: () => { return this._highlightColor; }, + // An eye-space distance, beyond which, the billboard is simply tested against a camera-facing plane at the ellipsoid's center, + // rather than against a depth texture. Note: only if the disableDepthTestingDistance property permits. + u_coarseDepthTestDistance: () => { + return this._coarseDepthTestDistance; + }, + // Within this distance, if the billboard is clamped to the ground, we'll depth-test 3 key points. + // If any key point is visible, the whole billboard will be visible. + u_threePointDepthTestDistance: () => { + return this._threePointDepthTestDistance; + }, }; const scene = this._scene; @@ -1372,9 +1384,6 @@ function writeCompressedAttribute3( const clampToGround = isHeightReferenceClamp(billboard.heightReference) && frameState.context.depthTexture; - if (!defined(disableDepthTestDistance)) { - disableDepthTestDistance = clampToGround ? 5000.0 : 0.0; - } disableDepthTestDistance *= disableDepthTestDistance; if (clampToGround || disableDepthTestDistance > 0.0) { @@ -2030,8 +2039,7 @@ BillboardCollection.prototype.update = function (frameState) { ) { this._rsOpaque = RenderState.fromCache({ depthTest: { - enabled: true, - func: WebGLConstants.LESS, + enabled: false, }, depthMask: true, }); @@ -2042,7 +2050,6 @@ BillboardCollection.prototype.update = function (frameState) { // If OPAQUE_AND_TRANSLUCENT is in use, only the opaque pass gets the benefit of the depth buffer, // not the translucent pass. Otherwise, if the TRANSLUCENT pass is on its own, it turns on // a depthMask in lieu of full depth sorting (because it has opaque-ish fragments that look bad in OIT). - // When the TRANSLUCENT depth mask is in use, label backgrounds require the depth func to be LEQUAL. const useTranslucentDepthMask = this._blendOption === BlendOption.TRANSLUCENT; @@ -2052,10 +2059,7 @@ BillboardCollection.prototype.update = function (frameState) { ) { this._rsTranslucent = RenderState.fromCache({ depthTest: { - enabled: true, - func: useTranslucentDepthMask - ? WebGLConstants.LEQUAL - : WebGLConstants.LESS, + enabled: false, }, depthMask: useTranslucentDepthMask, blending: BlendingState.ALPHA_BLEND, @@ -2141,9 +2145,9 @@ BillboardCollection.prototype.update = function (frameState) { } if (this._shaderClampToGround) { if (supportVSTextureReads) { - vs.defines.push("VERTEX_DEPTH_CHECK"); + vs.defines.push("VS_THREE_POINT_DEPTH_CHECK"); } else { - vs.defines.push("FRAGMENT_DEPTH_CHECK"); + vs.defines.push("FS_THREE_POINT_DEPTH_CHECK"); } } @@ -2162,9 +2166,9 @@ BillboardCollection.prototype.update = function (frameState) { }); if (this._shaderClampToGround) { if (supportVSTextureReads) { - fs.defines.push("VERTEX_DEPTH_CHECK"); + fs.defines.push("VS_THREE_POINT_DEPTH_CHECK"); } else { - fs.defines.push("FRAGMENT_DEPTH_CHECK"); + fs.defines.push("FS_THREE_POINT_DEPTH_CHECK"); } } @@ -2187,9 +2191,9 @@ BillboardCollection.prototype.update = function (frameState) { }); if (this._shaderClampToGround) { if (supportVSTextureReads) { - fs.defines.push("VERTEX_DEPTH_CHECK"); + fs.defines.push("VS_THREE_POINT_DEPTH_CHECK"); } else { - fs.defines.push("FRAGMENT_DEPTH_CHECK"); + fs.defines.push("FS_THREE_POINT_DEPTH_CHECK"); } } if (this._sdf) { @@ -2212,9 +2216,9 @@ BillboardCollection.prototype.update = function (frameState) { }); if (this._shaderClampToGround) { if (supportVSTextureReads) { - fs.defines.push("VERTEX_DEPTH_CHECK"); + fs.defines.push("VS_THREE_POINT_DEPTH_CHECK"); } else { - fs.defines.push("FRAGMENT_DEPTH_CHECK"); + fs.defines.push("FS_THREE_POINT_DEPTH_CHECK"); } } if (this._sdf) { @@ -2237,9 +2241,9 @@ BillboardCollection.prototype.update = function (frameState) { }); if (this._shaderClampToGround) { if (supportVSTextureReads) { - fs.defines.push("VERTEX_DEPTH_CHECK"); + fs.defines.push("VS_THREE_POINT_DEPTH_CHECK"); } else { - fs.defines.push("FRAGMENT_DEPTH_CHECK"); + fs.defines.push("FS_THREE_POINT_DEPTH_CHECK"); } } if (this._sdf) { diff --git a/packages/engine/Source/Shaders/BillboardCollectionFS.glsl b/packages/engine/Source/Shaders/BillboardCollectionFS.glsl index 4a6d8731ddd..74d21300a95 100644 --- a/packages/engine/Source/Shaders/BillboardCollectionFS.glsl +++ b/packages/engine/Source/Shaders/BillboardCollectionFS.glsl @@ -1,4 +1,6 @@ uniform sampler2D u_atlas; +uniform float u_coarseDepthTestDistance; +uniform float u_threePointDepthTestDistance; #ifdef VECTOR_TILE uniform vec4 u_highlightColor; @@ -14,18 +16,33 @@ in vec4 v_outlineColor; in float v_outlineWidth; #endif -#ifdef FRAGMENT_DEPTH_CHECK +in vec4 v_compressed; // x: eyeDepth, y: applyTranslate & enableDepthCheck, z: dimensions, w: imageSize +const float SHIFT_LEFT1 = 2.0; +const float SHIFT_RIGHT1 = 1.0 / 2.0; + +#ifdef FS_THREE_POINT_DEPTH_CHECK in vec4 v_textureCoordinateBounds; // the min and max x and y values for the texture coordinates in vec4 v_originTextureCoordinateAndTranslate; // texture coordinate at the origin, billboard translate (used for label glyphs) -in vec4 v_compressed; // x: eyeDepth, y: applyTranslate & enableDepthCheck, z: dimensions, w: imageSize in mat2 v_rotationMatrix; const float SHIFT_LEFT12 = 4096.0; -const float SHIFT_LEFT1 = 2.0; const float SHIFT_RIGHT12 = 1.0 / 4096.0; -const float SHIFT_RIGHT1 = 1.0 / 2.0; +#endif + +float getGlobeDepthAtCoords(vec2 st) +{ + float logDepthOrDepth = czm_unpackDepth(texture(czm_globeDepthTexture, st)); + if (logDepthOrDepth == 0.0) + { + return 0.0; // not on the globe + } + + vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth); + return eyeCoordinate.z / eyeCoordinate.w; +} +#ifdef FS_THREE_POINT_DEPTH_CHECK float getGlobeDepth(vec2 adjustedST, vec2 depthLookupST, bool applyTranslate, vec2 dimensions, vec2 imageSize) { vec2 lookupVector = imageSize * (depthLookupST - adjustedST); @@ -42,19 +59,10 @@ float getGlobeDepth(vec2 adjustedST, vec2 depthLookupST, bool applyTranslate, ve } vec2 st = ((lookupVector - translation + labelOffset) + gl_FragCoord.xy) / czm_viewport.zw; - float logDepthOrDepth = czm_unpackDepth(texture(czm_globeDepthTexture, st)); - - if (logDepthOrDepth == 0.0) - { - return 0.0; // not on the globe - } - - vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth); - return eyeCoordinate.z / eyeCoordinate.w; + return getGlobeDepthAtCoords(st); } #endif - #ifdef SDF // Get the distance from the edge of a glyph at a given position sampling an SDF texture. @@ -85,10 +93,89 @@ vec4 getSDFColor(vec2 position, float outlineWidth, vec4 outlineColor, float smo } #endif +#ifdef FS_THREE_POINT_DEPTH_CHECK +void doThreePointDepthTest(float eyeDepth, bool applyTranslate) { + + if (eyeDepth < -u_threePointDepthTestDistance) return; + float temp = v_compressed.z; + temp = temp * SHIFT_RIGHT12; + + vec2 dimensions; + dimensions.y = (temp - floor(temp)) * SHIFT_LEFT12; + dimensions.x = floor(temp); + + temp = v_compressed.w; + temp = temp * SHIFT_RIGHT12; + + vec2 imageSize; + imageSize.y = (temp - floor(temp)) * SHIFT_LEFT12; + imageSize.x = floor(temp); + + vec2 adjustedST = v_textureCoordinates - v_textureCoordinateBounds.xy; + adjustedST = adjustedST / vec2(v_textureCoordinateBounds.z - v_textureCoordinateBounds.x, v_textureCoordinateBounds.w - v_textureCoordinateBounds.y); + + float epsilonEyeDepth = v_compressed.x + czm_epsilon1; + float globeDepth1 = getGlobeDepth(adjustedST, v_originTextureCoordinateAndTranslate.xy, applyTranslate, dimensions, imageSize); + + // negative values go into the screen + if (globeDepth1 == 0.0 || globeDepth1 < epsilonEyeDepth) return; + + float globeDepth2 = getGlobeDepth(adjustedST, vec2(0.0, 1.0), applyTranslate, dimensions, imageSize); // top left corner + if (globeDepth2 == 0.0 || globeDepth2 < epsilonEyeDepth) return; + + float globeDepth3 = getGlobeDepth(adjustedST, vec2(1.0, 1.0), applyTranslate, dimensions, imageSize); // top right corner + if (globeDepth3 == 0.0 || globeDepth3 < epsilonEyeDepth) return; + + // All three key points are occluded, discard the fragment (and by extension the entire billboard) + discard; +} +#endif + +void doDepthTest() { + float temp = v_compressed.y; + temp = temp * SHIFT_RIGHT1; + float temp2 = (temp - floor(temp)) * SHIFT_LEFT1; + bool enableDepthCheck = temp2 != 0.0; + if (!enableDepthCheck) return; + + float eyeDepth = v_compressed.x; + +#ifdef FS_THREE_POINT_DEPTH_CHECK + // If the billboard is clamped to the ground and within a given distance, we do a 3-point depth test. This test is performed in the vertex shader, unless + // vertex texture sampling is not supported, in which case we do it here. + bool applyTranslate = floor(temp) != 0.0; + doThreePointDepthTest(eyeDepth, applyTranslate); + +#elif defined(VS_THREE_POINT_DEPTH_CHECK) + // Since discarding vertices is not possible, the vertex shader sets eyeDepth to 0 to indicate the depth test failed. Apply the discard here. + if (eyeDepth > -u_threePointDepthTestDistance) { + if (eyeDepth == 0.0) { + discard; + } + return; + } +#endif + + // Automatic depth testing of billboards is disabled (@see BillboardCollection#update). + // Instead, we do one of two types of manual depth tests (potentially in addition to the test above), depending on the camera's distance to the billboard fragment. + // If we're far away, we just compare against a flat, camera-facing depth-plane at the ellipsoid's center. + // If we're close, we compare against the globe depth texture (which includes depth from the 3D tile pass). + vec2 fragSt = gl_FragCoord.xy / czm_viewport.zw; + float globeDepth = getGlobeDepthAtCoords(fragSt); + if (globeDepth == 0.0) return; // Not on globe + + float distanceToEllipsoidCenter = -length(czm_viewerPositionWC); // depth is negative by convention + float testDistance = (eyeDepth > -u_coarseDepthTestDistance) ? globeDepth : distanceToEllipsoidCenter; + if (eyeDepth < testDistance) { + discard; + } +} + void main() { if (v_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard; if (v_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard; + doDepthTest(); vec4 color = texture(u_atlas, v_textureCoordinates); @@ -158,51 +245,4 @@ void main() #ifdef LOG_DEPTH czm_writeLogDepth(); #endif - -#ifdef FRAGMENT_DEPTH_CHECK - float temp = v_compressed.y; - - temp = temp * SHIFT_RIGHT1; - - float temp2 = (temp - floor(temp)) * SHIFT_LEFT1; - bool enableDepthTest = temp2 != 0.0; - bool applyTranslate = floor(temp) != 0.0; - - if (enableDepthTest) { - temp = v_compressed.z; - temp = temp * SHIFT_RIGHT12; - - vec2 dimensions; - dimensions.y = (temp - floor(temp)) * SHIFT_LEFT12; - dimensions.x = floor(temp); - - temp = v_compressed.w; - temp = temp * SHIFT_RIGHT12; - - vec2 imageSize; - imageSize.y = (temp - floor(temp)) * SHIFT_LEFT12; - imageSize.x = floor(temp); - - vec2 adjustedST = v_textureCoordinates - v_textureCoordinateBounds.xy; - adjustedST = adjustedST / vec2(v_textureCoordinateBounds.z - v_textureCoordinateBounds.x, v_textureCoordinateBounds.w - v_textureCoordinateBounds.y); - - float epsilonEyeDepth = v_compressed.x + czm_epsilon1; - float globeDepth1 = getGlobeDepth(adjustedST, v_originTextureCoordinateAndTranslate.xy, applyTranslate, dimensions, imageSize); - - // negative values go into the screen - if (globeDepth1 != 0.0 && globeDepth1 > epsilonEyeDepth) - { - float globeDepth2 = getGlobeDepth(adjustedST, vec2(0.0, 1.0), applyTranslate, dimensions, imageSize); // top left corner - if (globeDepth2 != 0.0 && globeDepth2 > epsilonEyeDepth) - { - float globeDepth3 = getGlobeDepth(adjustedST, vec2(1.0, 1.0), applyTranslate, dimensions, imageSize); // top right corner - if (globeDepth3 != 0.0 && globeDepth3 > epsilonEyeDepth) - { - discard; - } - } - } - } -#endif - -} +} \ No newline at end of file diff --git a/packages/engine/Source/Shaders/BillboardCollectionVS.glsl b/packages/engine/Source/Shaders/BillboardCollectionVS.glsl index cffc5b41965..c258b09bb10 100644 --- a/packages/engine/Source/Shaders/BillboardCollectionVS.glsl +++ b/packages/engine/Source/Shaders/BillboardCollectionVS.glsl @@ -1,3 +1,4 @@ +uniform float u_threePointDepthTestDistance; #ifdef INSTANCED in vec2 direction; #endif @@ -9,10 +10,10 @@ in vec4 compressedAttribute2; // label horizontal origin, in vec4 eyeOffset; // eye offset in meters, 4 bytes free (texture range) in vec4 scaleByDistance; // near, nearScale, far, farScale in vec4 pixelOffsetScaleByDistance; // near, nearScale, far, farScale -in vec4 compressedAttribute3; // distance display condition near, far, disableDepthTestDistance, dimensions +in vec4 compressedAttribute3; // distance display condition near, far, disableDepthTestDistanceSq, dimensions in vec2 sdf; // sdf outline color (rgb) and width (w) in float splitDirection; // splitDirection -#if defined(VERTEX_DEPTH_CHECK) || defined(FRAGMENT_DEPTH_CHECK) +#if defined(VS_THREE_POINT_DEPTH_CHECK) || defined(FS_THREE_POINT_DEPTH_CHECK) in vec4 textureCoordinateBoundsOrLabelTranslate; // the min and max x and y values for the texture coordinates #endif #ifdef VECTOR_TILE @@ -20,12 +21,12 @@ in float a_batchId; #endif out vec2 v_textureCoordinates; -#ifdef FRAGMENT_DEPTH_CHECK +#ifdef FS_THREE_POINT_DEPTH_CHECK out vec4 v_textureCoordinateBounds; out vec4 v_originTextureCoordinateAndTranslate; -out vec4 v_compressed; // x: eyeDepth, y: applyTranslate & enableDepthCheck, z: dimensions, w: imageSize out mat2 v_rotationMatrix; #endif +out vec4 v_compressed; // x: eyeDepth, y: applyTranslate & enableDepthCheck, z: dimensions, w: imageSize out vec4 v_pickColor; out vec4 v_color; @@ -92,7 +93,7 @@ vec4 addScreenSpaceOffset(vec4 positionEC, vec2 imageSize, float scale, vec2 dir return positionEC; } -#ifdef VERTEX_DEPTH_CHECK +#ifdef VS_THREE_POINT_DEPTH_CHECK float getGlobeDepth(vec4 positionEC) { vec4 posWC = czm_eyeToWindowCoordinates(positionEC); @@ -137,7 +138,7 @@ void main() origin.y = floor(compressed * SHIFT_RIGHT3); compressed -= origin.y * SHIFT_LEFT3; -#ifdef FRAGMENT_DEPTH_CHECK +#ifdef FS_THREE_POINT_DEPTH_CHECK vec2 depthOrigin = origin.xy; #endif origin -= vec2(1.0); @@ -176,10 +177,10 @@ void main() vec2 imageSize = vec2(floor(temp), temp2); -#ifdef FRAGMENT_DEPTH_CHECK +#ifdef FS_THREE_POINT_DEPTH_CHECK float labelHorizontalOrigin = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2)); float applyTranslate = 0.0; - if (labelHorizontalOrigin != 0.0) // is a billboard, so set apply translate to false + if (labelHorizontalOrigin != 0.0) // is a label, so set apply translate to true { applyTranslate = 1.0; labelHorizontalOrigin -= 2.0; @@ -200,7 +201,7 @@ void main() translucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0; #endif -#if defined(VERTEX_DEPTH_CHECK) || defined(FRAGMENT_DEPTH_CHECK) +#if defined(VS_THREE_POINT_DEPTH_CHECK) || defined(FS_THREE_POINT_DEPTH_CHECK) temp = compressedAttribute3.w; temp = temp * SHIFT_RIGHT12; @@ -250,10 +251,6 @@ void main() vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); vec4 positionEC = czm_modelViewRelativeToEye * p; -#if defined(FRAGMENT_DEPTH_CHECK) || defined(VERTEX_DEPTH_CHECK) - float eyeDepth = positionEC.z; -#endif - positionEC = czm_eyeOffset(positionEC, eyeOffset.xyz); positionEC.xyz *= show; @@ -311,35 +308,56 @@ void main() mat2 rotationMatrix; float mpp; + float enableDepthCheck = 1.0; #ifdef DISABLE_DEPTH_DISTANCE - float disableDepthTestDistance = compressedAttribute3.z; + float disableDepthTestDistanceSq = compressedAttribute3.z; + if (disableDepthTestDistanceSq == 0.0 && czm_minimumDisableDepthTestDistance != 0.0) + { + disableDepthTestDistanceSq = czm_minimumDisableDepthTestDistance; + } + + if (lengthSq < disableDepthTestDistanceSq || disableDepthTestDistanceSq < 0.0) + { + enableDepthCheck = 0.0; + } #endif -#ifdef VERTEX_DEPTH_CHECK -if (lengthSq < disableDepthTestDistance) { - float depthsilon = 10.0; + v_compressed.y = enableDepthCheck; - vec2 labelTranslate = textureCoordinateBoundsOrLabelTranslate.xy; - vec4 pEC1 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); +#ifdef VS_THREE_POINT_DEPTH_CHECK +if (lengthSq < (u_threePointDepthTestDistance * u_threePointDepthTestDistance) && (enableDepthCheck == 1.0)) { + float depthsilon = 10.0; + vec2 depthOrigin; + // Horizontal origin for labels comes from a special attribute. If that value is 0, this is a billboard - use the regular origin. + // Otherwise, transform the label origin to -1, 0, 1 (right, center, left). + depthOrigin.x = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2)); + depthOrigin.x = czm_branchFreeTernary(depthOrigin.x == 0.0, origin.x, depthOrigin.x - 2.0); + depthOrigin.y = origin.y; + + vec4 pEC1 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0), depthOrigin, vec2(0.0), pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); float globeDepth1 = getGlobeDepth(pEC1); if (globeDepth1 != 0.0 && pEC1.z + depthsilon < globeDepth1) { - vec4 pEC2 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0, 1.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); + vec4 pEC2 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0, 1.0), depthOrigin, vec2(0.0), pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); float globeDepth2 = getGlobeDepth(pEC2); if (globeDepth2 != 0.0 && pEC2.z + depthsilon < globeDepth2) { - vec4 pEC3 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(1.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); + vec4 pEC3 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(1.0), depthOrigin, vec2(0.0), pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); float globeDepth3 = getGlobeDepth(pEC3); if (globeDepth3 != 0.0 && pEC3.z + depthsilon < globeDepth3) { + // "Discard" this vertex, as three key points fail depth test. positionEC.xyz = vec3(0.0); } } } } #endif + // Write out the eyespace depth before applying the screen space offset, but after potentially "discarding" the vertex + // by setting its eyespace position to zero, via the three-point depth test above. + v_compressed.x = positionEC.z; positionEC = addScreenSpaceOffset(positionEC, imageSize, scale, direction, origin, translate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); gl_Position = czm_projection * positionEC; @@ -350,17 +368,14 @@ if (lengthSq < disableDepthTestDistance) { #endif #ifdef DISABLE_DEPTH_DISTANCE - if (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0) - { - disableDepthTestDistance = czm_minimumDisableDepthTestDistance; - } - if (disableDepthTestDistance != 0.0) + if (disableDepthTestDistanceSq != 0.0) { // Don't try to "multiply both sides" by w. Greater/less-than comparisons won't work for negative values of w. float zclip = gl_Position.z / gl_Position.w; bool clipped = (zclip < -1.0 || zclip > 1.0); - if (!clipped && (disableDepthTestDistance < 0.0 || (lengthSq > 0.0 && lengthSq < disableDepthTestDistance))) + // disableDepthTestDistanceSq can be less than zero if it's explicitly set to -1 in JS (as a sentinel value equivalent to infinity) + if (!clipped && (disableDepthTestDistanceSq < 0.0 || (lengthSq > 0.0 && lengthSq < disableDepthTestDistanceSq))) { // Position z on the near plane. gl_Position.z = -gl_Position.w; @@ -371,7 +386,7 @@ if (lengthSq < disableDepthTestDistance) { } #endif -#ifdef FRAGMENT_DEPTH_CHECK +#ifdef FS_THREE_POINT_DEPTH_CHECK if (sizeInMeters) { translate /= mpp; dimensions /= mpp; @@ -383,21 +398,13 @@ if (lengthSq < disableDepthTestDistance) { #else v_rotationMatrix = mat2(1.0, 0.0, 0.0, 1.0); #endif - - float enableDepthCheck = 0.0; - if (lengthSq < disableDepthTestDistance) - { - enableDepthCheck = 1.0; - } - float dw = floor(clamp(dimensions.x, 0.0, SHIFT_LEFT12)); float dh = floor(clamp(dimensions.y, 0.0, SHIFT_LEFT12)); float iw = floor(clamp(imageSize.x, 0.0, SHIFT_LEFT12)); float ih = floor(clamp(imageSize.y, 0.0, SHIFT_LEFT12)); - v_compressed.x = eyeDepth; - v_compressed.y = applyTranslate * SHIFT_LEFT1 + enableDepthCheck; + v_compressed.y += applyTranslate * SHIFT_LEFT1; v_compressed.z = dw * SHIFT_LEFT12 + dh; v_compressed.w = iw * SHIFT_LEFT12 + ih; v_originTextureCoordinateAndTranslate.xy = depthOrigin;