Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
25 changes: 14 additions & 11 deletions packages/engine/Source/Scene/BillboardCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
Copy link
Contributor Author

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 to disableDepthTestDistance was 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 disableDepthTestDistance value) is okay.

Copy link
Contributor

@lukemckinstry lukemckinstry Sep 18, 2025

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.

Copy link
Contributor Author

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 if disableDepthTestDistance is undefined, default to 5km). But this actually defeats the point ofdisableDepthTestDistance. disableDepthTestDistance is 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 disableDepthTestDistance now. Also importantly, the 3-point test still does what it was intended to do: preserve visibility of terrain-clamped billboards when viewed close up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense for these values be either 1) exposed in the API for tweaking, or 2) specified relative to the ellipsoid size?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, maybe just relative to the ellipsoid for now? If we get requests to expose these values in the API, easy enough to add later.


this._uniforms = {
u_atlas: () => {
Expand All @@ -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;
Expand Down Expand Up @@ -1365,9 +1376,6 @@ function writeCompressedAttribute3(
const clampToGround =
isHeightReferenceClamp(billboard.heightReference) &&
frameState.context.depthTexture;
if (!defined(disableDepthTestDistance)) {
disableDepthTestDistance = clampToGround ? 5000.0 : 0.0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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) {
Expand Down Expand Up @@ -2023,8 +2031,7 @@ BillboardCollection.prototype.update = function (frameState) {
) {
this._rsOpaque = RenderState.fromCache({
depthTest: {
enabled: true,
func: WebGLConstants.LESS,
enabled: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 LEQUAL check in the shaders, but it seems to work better this way (see test case in PR description)

Copy link
Contributor Author

@mzschwartz5 mzschwartz5 Sep 3, 2025

Choose a reason for hiding this comment

The 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,
});
Expand All @@ -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;

Expand All @@ -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,
Expand Down
126 changes: 83 additions & 43 deletions packages/engine/Source/Shaders/BillboardCollectionFS.glsl
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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;
Expand All @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 was defined, but now they're used all the time

#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
Copy link
Contributor Author

@mzschwartz5 mzschwartz5 Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a new function, really. It just breaks the old getGlobeDepth function into two pieces, so we can call this piece separately.


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);
Expand All @@ -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.
Expand Down Expand Up @@ -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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More moving of variables outside compiler macros... And now we check if enableDepthCheck is turned on outside of the macro. This used to just mean "is the 3-point depth check enabled," but I repurposed it to mean "is depth testing enabled at all".

If it is, we do all forms of depth testing below (3-point, and regular)


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;
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, the crux of this PR. This the manual depth testing that replaces automatic depth testing. Except, now, with manual control, we can depth test against a flat plane at global scales.


}
43 changes: 20 additions & 23 deletions packages/engine/Source/Shaders/BillboardCollectionVS.glsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
uniform float u_threePointDepthTestDistance;
#ifdef INSTANCED
in vec2 direction;
#endif
Expand All @@ -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;
Expand Down Expand Up @@ -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

positionEC = czm_eyeOffset(positionEC, eyeOffset.xyz);
positionEC.xyz *= show;

Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pedantic, but should disableDepthTestDistance actually be called disableDepthTestDistanceSquared then?

Copy link
Contributor Author

@mzschwartz5 mzschwartz5 Sep 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't call that pedantic... in fact, it may actually be a bug. I'd need to go see if compressedAttribute3.z is actually squared before being passed in. Either way, I agree that it should be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is squared before being sent to the GPU. So it's a misnomer of a variable, I'll change it.

{
enableDepthCheck = 0.0;
}
Comment on lines 311 to 322
Copy link
Contributor Author

@mzschwartz5 mzschwartz5 Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I repurposed enableDepthCheck - it used to mean "is the three-point depth check applied?" But now it just means what it sounds like "do we depth test at all?"

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 disableDepthTestDistance logic is together now.

#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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't know what the purpose of labelTranslate here was, but it had the (bad) effect of making 3-point testing not work until a label was wayyyy occluded by terrain. Separate from all other changes in this PR, removing labelTranslate and using vec2(0.0) looks way better.

Copy link
Contributor

Choose a reason for hiding this comment

The 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 pixelOffset, or maybe eyeOffset, label property.

If that is the case, we might need to factor that back in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I verified that both pixelOffset and eyeOffset are working just fine in this branch with both variants of the depth testing. No idea why labelTranslate was bing used then. 🤷‍♀️

This change should be OK as-is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, labelTranslate may be handling offsets from label alignments.

For example, this label is right-aligned and doesn't seem to be handled properly n three-point depth testing when goin behind terrain:

Image Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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:

  1. In fact, we do want labelTranslate to be (0, 0) here. That field is used by addScreenSpaceOffset to offset individual glyphs according to where they live in a text string. In this case, we're depth testing three key points of the whole label - we don't want or need any glyph-specific offsets. So the pre-existing use of labelTranslate is definitely a bug.
  2. The real issue is the value of origin being passed to addScreenSpaceOffset in the three-point test. The problem is that in rebindAllGlyphs, glyph billboards are always given a horizontal origin of LEFT.. This is purposeful, for glyph alignment, but it breaks the three-point test for anything other than LEFT. What we ought to be doing in the shader, is using a different vertex attribute altogether for labels. Not origin (which comes from compressedAttribute0) but labelHorizontalOrigin (which comes from compressedAttribute2). Making this change (and keeping the change where labelTranslate is always (0,0)), the behavior now works well for LEFT and RIGHT -aligned labels.

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)
{
Expand All @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down