- 
                Notifications
    
You must be signed in to change notification settings  - Fork 3.7k
 
Switch from automatic to manual depth testing for billboards #12821
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
Changes from 3 commits
4c186a2
              a3de865
              234a4a3
              dda4aa8
              3d51a6e
              7948447
              2ddb704
              6a5a0c4
              9c9705c
              2966aa7
              4c5b2d5
              3592513
              008ff68
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -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"; | ||
| 
          
            
          
           | 
    @@ -315,6 +314,8 @@ function BillboardCollection(options) { | |
| ]; | ||
| 
     | 
||
| this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints | ||
| this._coarseDepthTestDistance = 50000.0; | ||
| this._threePointDepthTestDistance = 5000.0; | ||
                
       | 
||
| 
     | 
||
| this._uniforms = { | ||
| u_atlas: () => { | ||
| 
        
          
        
         | 
    @@ -323,6 +324,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; | ||
| 
          
            
          
           | 
    @@ -1365,9 +1376,6 @@ function writeCompressedAttribute3( | |
| const clampToGround = | ||
| isHeightReferenceClamp(billboard.heightReference) && | ||
| frameState.context.depthTexture; | ||
| if (!defined(disableDepthTestDistance)) { | ||
| disableDepthTestDistance = clampToGround ? 5000.0 : 0.0; | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I mentioned above. Removing in favor of always using a 5km distance.  | 
||
| } | ||
| 
     | 
||
| disableDepthTestDistance *= disableDepthTestDistance; | ||
| if (clampToGround || disableDepthTestDistance > 0.0) { | ||
| 
          
            
          
           | 
    @@ -2023,8 +2031,7 @@ BillboardCollection.prototype.update = function (frameState) { | |
| ) { | ||
| this._rsOpaque = RenderState.fromCache({ | ||
| depthTest: { | ||
| enabled: true, | ||
| func: WebGLConstants.LESS, | ||
| enabled: false, | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The crux of this PR's change. Disable automatic depth testing and do it manually in the shaders so we have more control of how it happens. Note: Given the comment below about translucency, I'm a little wary I may have introduced regressions, as I don't do a  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also note- we still leave automatic write to the depth buffer enabled, we just don't test against it automatically.  | 
||
| }, | ||
| depthMask: true, | ||
| }); | ||
| 
        
          
        
         | 
    @@ -2035,7 +2042,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; | ||
| 
     | 
||
| 
        
          
        
         | 
    @@ -2045,10 +2051,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, | ||
| 
          
            
          
           | 
    ||
| 
                       There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would recommend reviewing the VS before the FS.  | 
            
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -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 | ||
| 
     | 
||
| 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; | ||
| 
     | 
||
| 
         
      Comment on lines
    
      +19
     to 
      +22
    
   
  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These changes, among several others in this PR, are just moving variables outside of macro checks. These used to be only used if   | 
||
| #ifdef FRAGMENT_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 | ||
| } | ||
| 
         
      Comment on lines
    
      +33
     to 
      +39
    
   
  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't a new function, really. It just breaks the old   | 
||
| 
     | 
||
| vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth); | ||
| return eyeCoordinate.z / eyeCoordinate.w; | ||
| } | ||
| 
     | 
||
| #ifdef FRAGMENT_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. | ||
| 
          
            
          
           | 
    @@ -159,50 +167,82 @@ void main() | |
| czm_writeLogDepth(); | ||
| #endif | ||
| 
     | 
||
| #ifdef FRAGMENT_DEPTH_CHECK | ||
| float temp = v_compressed.y; | ||
| float temp = v_compressed.y; | ||
| 
     | 
||
| temp = temp * SHIFT_RIGHT1; | ||
| 
     | 
||
| temp = temp * SHIFT_RIGHT1; | ||
| float temp2 = (temp - floor(temp)) * SHIFT_LEFT1; | ||
| bool enableDepthCheck = temp2 != 0.0; | ||
| 
     | 
||
| float temp2 = (temp - floor(temp)) * SHIFT_LEFT1; | ||
| bool enableDepthTest = temp2 != 0.0; | ||
| bool applyTranslate = floor(temp) != 0.0; | ||
| if (!enableDepthCheck) return; | ||
                
       | 
||
| 
     | 
||
| if (enableDepthTest) { | ||
| temp = v_compressed.z; | ||
| temp = temp * SHIFT_RIGHT12; | ||
| float eyeDepth = v_compressed.x; | ||
| bool applyTranslate = floor(temp) != 0.0; | ||
| 
     | 
||
| // 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. | ||
| #ifdef FRAGMENT_DEPTH_CHECK | ||
| if (eyeDepth > -u_threePointDepthTestDistance) { | ||
| temp = v_compressed.z; | ||
| temp = temp * SHIFT_RIGHT12; | ||
| 
     | 
||
| vec2 dimensions; | ||
| dimensions.y = (temp - floor(temp)) * SHIFT_LEFT12; | ||
| dimensions.x = floor(temp); | ||
| vec2 dimensions; | ||
| dimensions.y = (temp - floor(temp)) * SHIFT_LEFT12; | ||
| dimensions.x = floor(temp); | ||
| 
     | 
||
| temp = v_compressed.w; | ||
| temp = temp * SHIFT_RIGHT12; | ||
| temp = v_compressed.w; | ||
| temp = temp * SHIFT_RIGHT12; | ||
| 
     | 
||
| vec2 imageSize; | ||
| imageSize.y = (temp - floor(temp)) * SHIFT_LEFT12; | ||
| imageSize.x = floor(temp); | ||
| 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); | ||
| 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); | ||
| 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) | ||
| // 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 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) | ||
| { | ||
| float globeDepth3 = getGlobeDepth(adjustedST, vec2(1.0, 1.0), applyTranslate, dimensions, imageSize); // top right corner | ||
| if (globeDepth3 != 0.0 && globeDepth3 > epsilonEyeDepth) | ||
| { | ||
| discard; | ||
| } | ||
| discard; | ||
| } | ||
| } | ||
| } | ||
| return; | ||
| } | ||
| #endif | ||
| 
     | 
||
| // If the billboard is clamped to the ground and within a given distance, we do a 3-point depth test. If vertex texture sampling is supported, this has already been performed. | ||
| // Since discarding vertices is not possible, the vertex shader sets eyeDepth to 0 to indicate the depth test failed. Apply the discard here. | ||
| #ifdef VERTEX_DEPTH_CHECK | ||
| 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 (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) { | ||
| float distanceToEllipsoidCenter = -length(czm_viewerPositionWC); // depth is negative by convention | ||
| float testDistance = (eyeDepth > -u_coarseDepthTestDistance) ? globeDepth : distanceToEllipsoidCenter; | ||
| if (eyeDepth < testDistance) { | ||
| discard; | ||
| } | ||
| } | ||
                
       | 
||
| 
     | 
||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| uniform float u_threePointDepthTestDistance; | ||
| #ifdef INSTANCED | ||
| in vec2 direction; | ||
| #endif | ||
| 
        
          
        
         | 
    @@ -23,9 +24,9 @@ out vec2 v_textureCoordinates; | |
| #ifdef FRAGMENT_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; | ||
| 
          
            
          
           | 
    @@ -248,10 +249,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 | ||
| 
     | 
||
                
      
                  mzschwartz5 marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| positionEC = czm_eyeOffset(positionEC, eyeOffset.xyz); | ||
| positionEC.xyz *= show; | ||
| 
     | 
||
| 
          
            
          
           | 
    @@ -309,26 +306,37 @@ void main() | |
| mat2 rotationMatrix; | ||
| float mpp; | ||
| 
     | 
||
| float enableDepthCheck = 1.0; | ||
| #ifdef DISABLE_DEPTH_DISTANCE | ||
| float disableDepthTestDistance = compressedAttribute3.z; | ||
| if (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0) | ||
| { | ||
| disableDepthTestDistance = czm_minimumDisableDepthTestDistance; | ||
| } | ||
| 
     | 
||
| if (lengthSq < disableDepthTestDistance || disableDepthTestDistance < 0.0) | ||
                
       | 
||
| { | ||
| enableDepthCheck = 0.0; | ||
| } | ||
| 
         
      Comment on lines
    
      311
     to 
      322
    
   
  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I repurposed  To accommodate this change, I had to move some chunks upwards in the vert shader. But it's actually more appropriate in this location anyway; i.e. all the   | 
||
| #endif | ||
| 
     | 
||
| v_compressed.y = enableDepthCheck; | ||
| 
     | 
||
| #ifdef VERTEX_DEPTH_CHECK | ||
| if (lengthSq < disableDepthTestDistance) { | ||
| if (lengthSq < (u_threePointDepthTestDistance * u_threePointDepthTestDistance) && (enableDepthCheck == 1.0)) { | ||
| float depthsilon = 10.0; | ||
| 
     | 
||
| vec2 labelTranslate = textureCoordinateBoundsOrLabelTranslate.xy; | ||
| 
         There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I honestly don't know what the purpose of  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll need to verify but I'd expect labelTranslate is the value of the  If that is the case, we might need to factor that back in. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I verified that both  This change should be OK as-is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually,  For example, this label is right-aligned and doesn't seem to be handled properly n three-point depth testing when goin behind terrain:  
 
    There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ooh interesting... that's basically the same problem that was occurring with label translate when left-aligned. So I'm not sure what the solution is here, but maybe I just keep it as it was so at least the behavior is the same? I might spend a little time seeing if there's a complete solution. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pushed a commit to address this issue - it's not what we thought was going on: 
  | 
||
| vec4 pEC1 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); | ||
| vec4 pEC1 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0), origin, 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), origin, 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), origin, vec2(0.0), pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp); | ||
| float globeDepth3 = getGlobeDepth(pEC3); | ||
| if (globeDepth3 != 0.0 && pEC3.z + depthsilon < globeDepth3) | ||
| { | ||
| 
        
          
        
         | 
    @@ -338,6 +346,7 @@ if (lengthSq < disableDepthTestDistance) { | |
| } | ||
| } | ||
| #endif | ||
| 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; | ||
| 
        
          
        
         | 
    @@ -348,10 +357,6 @@ if (lengthSq < disableDepthTestDistance) { | |
| #endif | ||
| 
     | 
||
| #ifdef DISABLE_DEPTH_DISTANCE | ||
| if (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0) | ||
| { | ||
| disableDepthTestDistance = czm_minimumDisableDepthTestDistance; | ||
| } | ||
| 
     | 
||
| if (disableDepthTestDistance != 0.0) | ||
| { | ||
| 
          
            
          
           | 
    @@ -381,21 +386,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; | ||
| 
          
            
          
           | 
    ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, the distance at which the three-point depth testing technique occurred was set to the
disableDepthTestDistance, or 5km by default if not set. Setting it todisableDepthTestDistancewas a strange and buggy choice, though, because the original author misinterpreted the setting. They reversed the meaning to only 3-point depth test within that distance.Since the original intent was to make close up viewing of billboards clamped to terrain better, I think always having it be 5km (while respecting the
disableDepthTestDistancevalue) is okay.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain this part (3 point depth test and the bug around misuse of
disableDepthTestDistance) again more thoroughly, or point to where it is already written up? I remember talking about this in-person, but I want to make sure I (and others) can understand it clearly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'll try my best - it's a little hard to wrap one's head around. First of all, this blog describes the qualitative behavior of billboards clamped to terrain, before this PR. tl;dr - in order to improve billboard visibility, a special 3-point test is performed. The idea is: if any of 3 key points on a billboard is visible, the whole billboard should be visible. If all are occluded, the whole billboard gets occluded.
This special 3-point test was (before this PR) applied only if the camera was within a certain distance of the billboard. The way this distance was determined is what was buggy. The logic was, "if the camera is closer than
disableDepthTestDistance, do this 3-point test." (And ifdisableDepthTestDistanceis undefined, default to 5km). But this actually defeats the point ofdisableDepthTestDistance.disableDepthTestDistanceis supposed to disable occlusion within a given distance, but this 3-point test was actually fully occluding the billboard within that distance, if all 3 key points were occluded.With this PR, I just hardcoded the distance to 5km - but, importantly, it should also respect
disableDepthTestDistancenow. Also importantly, the 3-point test still does what it was intended to do: preserve visibility of terrain-clamped billboards when viewed close up.