Skip to content

Commit 6dd9ca1

Browse files
committed
fix(BillboardCollection): Fix precision loss in billboard image texcoords
1 parent 3849eb6 commit 6dd9ca1

File tree

2 files changed

+25
-33
lines changed

2 files changed

+25
-33
lines changed

packages/engine/Source/Scene/BillboardCollection.js

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,16 @@ const SDF_INDEX = Billboard.SDF_INDEX;
5757
const SPLIT_DIRECTION_INDEX = Billboard.SPLIT_DIRECTION_INDEX;
5858
const NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;
5959

60+
const scratchTextureSize = new Cartesian2();
61+
6062
const attributeLocations = {
6163
direction: 0,
6264
positionHighAndScale: 1,
6365
positionLowAndRotation: 2, // texture offset in w
6466
compressedAttribute0: 3,
6567
compressedAttribute1: 4,
6668
compressedAttribute2: 5,
67-
eyeOffset: 6, // texture range in w
69+
eyeOffset: 6,
6870
scaleByDistance: 7,
6971
pixelOffsetScaleByDistance: 8,
7072
compressedAttribute3: 9,
@@ -304,6 +306,10 @@ function BillboardCollection(options) {
304306
u_atlas: () => {
305307
return this.textureAtlas.texture;
306308
},
309+
u_atlasSize: () => {
310+
const { width, height } = this.textureAtlas.texture;
311+
return Cartesian2.fromElements(width, height, scratchTextureSize);
312+
},
307313
u_highlightColor: () => {
308314
return this._highlightColor;
309315
},
@@ -858,8 +864,6 @@ function writePositionScaleAndRotation(
858864
positionLowWriter(i, low.x, low.y, low.z, rotation);
859865
}
860866

861-
const scratchCartesian2 = new Cartesian2();
862-
863867
const UPPER_BOUND = 32768.0; // 2^15
864868

865869
const LEFT_SHIFT16 = 65536.0; // 2^16
@@ -917,15 +921,17 @@ function writeCompressedAttrib0(
917921
billboardCollection._allVerticalCenter &&
918922
verticalOrigin === VerticalOrigin.CENTER;
919923

920-
let bottomLeftX = 0;
921-
let bottomLeftY = 0;
924+
// Compute offset (in pixels) from lower-left of the texture atlas.
925+
let imageOffsetX = 0;
926+
let imageOffsetY = 0;
922927
if (billboard.ready) {
923928
const imageRectangle = billboard.computeTextureCoordinates(
924929
scratchBoundingRectangle,
925930
);
926-
927-
bottomLeftX = imageRectangle.x;
928-
bottomLeftY = imageRectangle.y;
931+
const { width: atlasWidth, height: atlasHeight } =
932+
billboardCollection.textureAtlas.texture;
933+
imageOffsetX = imageRectangle.x * atlasWidth;
934+
imageOffsetY = imageRectangle.y * atlasHeight;
929935
}
930936

931937
let compressed0 =
@@ -963,13 +969,10 @@ function writeCompressedAttrib0(
963969
compressed1 += upperTranslateY;
964970
compressed2 += lowerTranslateY;
965971

966-
scratchCartesian2.x = bottomLeftX;
967-
scratchCartesian2.y = bottomLeftY;
968-
const compressedTexCoordsLL =
969-
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
972+
const compressedImageOffsetLL = imageOffsetX * LEFT_SHIFT16 + imageOffsetY;
970973

971974
const i = billboard._index;
972-
writer(i, compressed0, compressed1, compressed2, compressedTexCoordsLL);
975+
writer(i, compressed0, compressed1, compressed2, compressedImageOffsetLL);
973976
}
974977

975978
function writeCompressedAttrib1(
@@ -1101,23 +1104,8 @@ function writeEyeOffset(
11011104
Math.abs(eyeOffsetZ),
11021105
);
11031106

1104-
scratchCartesian2.x = 0;
1105-
scratchCartesian2.y = 0;
1106-
1107-
if (billboard.ready) {
1108-
const imageRectangle = billboard.computeTextureCoordinates(
1109-
scratchBoundingRectangle,
1110-
);
1111-
1112-
scratchCartesian2.x = imageRectangle.width;
1113-
scratchCartesian2.y = imageRectangle.height;
1114-
}
1115-
1116-
const compressedTexCoordsRange =
1117-
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
1118-
11191107
const i = billboard._index;
1120-
writer(i, eyeOffset.x, eyeOffset.y, eyeOffsetZ, compressedTexCoordsRange);
1108+
writer(i, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);
11211109
}
11221110

11231111
function writeScaleByDistance(

packages/engine/Source/Shaders/BillboardCollectionVS.glsl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
uniform vec2 u_atlasSize;
12
uniform float u_threePointDepthTestDistance;
23
in vec2 direction;
34
in vec4 positionHighAndScale;
@@ -45,6 +46,7 @@ const float SHIFT_LEFT3 = 8.0;
4546
const float SHIFT_LEFT2 = 4.0;
4647
const float SHIFT_LEFT1 = 2.0;
4748

49+
const float SHIFT_RIGHT16 = 1.0 / 65536.0;
4850
const float SHIFT_RIGHT12 = 1.0 / 4096.0;
4951
const float SHIFT_RIGHT8 = 1.0 / 256.0;
5052
const float SHIFT_RIGHT7 = 1.0 / 128.0;
@@ -144,10 +146,6 @@ void main()
144146
float show = floor(compressed * SHIFT_RIGHT2);
145147
compressed -= show * SHIFT_LEFT2;
146148

147-
vec2 textureCoordinatesBottomLeft = czm_decompressTextureCoordinates(compressedAttribute0.w);
148-
vec2 textureCoordinatesRange = czm_decompressTextureCoordinates(eyeOffset.w);
149-
vec2 textureCoordinates = textureCoordinatesBottomLeft + direction * textureCoordinatesRange;
150-
151149
float temp = compressedAttribute0.y * SHIFT_RIGHT8;
152150
pixelOffset.y = -(floor(temp) - UPPER_BOUND);
153151

@@ -167,6 +165,12 @@ void main()
167165

168166
vec2 imageSize = vec2(floor(temp), temp2);
169167

168+
float imageOffsetX = floor(compressedAttribute0.w * SHIFT_RIGHT16);
169+
float imageOffsetY = compressedAttribute0.w - (imageOffsetX * SHIFT_LEFT16);
170+
vec2 textureCoordinatesBottomLeft = vec2(imageOffsetX, imageOffsetY) / u_atlasSize.xy;
171+
vec2 textureCoordinatesRange = imageSize.xy / u_atlasSize.xy;
172+
vec2 textureCoordinates = textureCoordinatesBottomLeft + direction * textureCoordinatesRange;
173+
170174
#ifdef FS_THREE_POINT_DEPTH_CHECK
171175
float labelHorizontalOrigin = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));
172176
float applyTranslate = 0.0;

0 commit comments

Comments
 (0)