mirror of https://github.com/CesiumGS/cesium.git
Compare commits
4 Commits
fac7924125
...
4f0e3706ce
| Author | SHA1 | Date |
|---|---|---|
|
|
4f0e3706ce | |
|
|
eecd3b43b1 | |
|
|
94e2932c09 | |
|
|
2f3a731840 |
|
|
@ -193,22 +193,21 @@ Object.defineProperties(TextureAtlas.prototype, {
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the texture coordinates for reading the associated image in shaders.
|
* TODO
|
||||||
* @param {number} index The index of the image region.
|
* @param {number} index The index of the image region.
|
||||||
* @param {BoundingRectangle} [result] The object into which to store the result.
|
* @param {BoundingRectangle} [result] The object into which to store the result.
|
||||||
* @return {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
* @return {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
* @private
|
* @private
|
||||||
* @example
|
* @example
|
||||||
* const index = await atlas.addImage("myImage", image);
|
* const index = await atlas.addImage("myImage", image);
|
||||||
* const rectangle = atlas.computeTextureCoordinates(index);
|
* const rectangle = atlas.computeImageCoordinates(index);
|
||||||
* BoundingRectangle.pack(rectangle, bufferView);
|
* BoundingRectangle.pack(rectangle, bufferView);
|
||||||
*/
|
*/
|
||||||
TextureAtlas.prototype.computeTextureCoordinates = function (index, result) {
|
TextureAtlas.prototype.computeImageCoordinates = function (index, result) {
|
||||||
//>>includeStart('debug', pragmas.debug);
|
//>>includeStart('debug', pragmas.debug);
|
||||||
Check.typeOf.number.greaterThanOrEquals("index", index, 0);
|
Check.typeOf.number.greaterThanOrEquals("index", index, 0);
|
||||||
//>>includeEnd('debug');
|
//>>includeEnd('debug');
|
||||||
|
|
||||||
const texture = this._texture;
|
|
||||||
const rectangle = this._rectangles[index];
|
const rectangle = this._rectangles[index];
|
||||||
|
|
||||||
if (!defined(result)) {
|
if (!defined(result)) {
|
||||||
|
|
@ -224,11 +223,6 @@ TextureAtlas.prototype.computeTextureCoordinates = function (index, result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const atlasWidth = texture.width;
|
|
||||||
const atlasHeight = texture.height;
|
|
||||||
|
|
||||||
const width = rectangle.width;
|
|
||||||
const height = rectangle.height;
|
|
||||||
let x = rectangle.x;
|
let x = rectangle.x;
|
||||||
let y = rectangle.y;
|
let y = rectangle.y;
|
||||||
|
|
||||||
|
|
@ -240,10 +234,36 @@ TextureAtlas.prototype.computeTextureCoordinates = function (index, result) {
|
||||||
y += parentRectangle.y;
|
y += parentRectangle.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.x = x / atlasWidth;
|
result.x = x;
|
||||||
result.y = y / atlasHeight;
|
result.y = y;
|
||||||
result.width = width / atlasWidth;
|
result.width = rectangle.width;
|
||||||
result.height = height / atlasHeight;
|
result.height = rectangle.height;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the texture coordinates for reading the associated image in shaders.
|
||||||
|
* @param {number} index The index of the image region.
|
||||||
|
* @param {BoundingRectangle} [result] The object into which to store the result.
|
||||||
|
* @return {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
|
* @private
|
||||||
|
* @example
|
||||||
|
* const index = await atlas.addImage("myImage", image);
|
||||||
|
* const rectangle = atlas.computeTextureCoordinates(index);
|
||||||
|
* BoundingRectangle.pack(rectangle, bufferView);
|
||||||
|
*/
|
||||||
|
TextureAtlas.prototype.computeTextureCoordinates = function (index, result) {
|
||||||
|
result = this.computeImageCoordinates(index, result);
|
||||||
|
|
||||||
|
const texture = this._texture;
|
||||||
|
const atlasWidth = texture.width;
|
||||||
|
const atlasHeight = texture.height;
|
||||||
|
|
||||||
|
result.x /= atlasWidth;
|
||||||
|
result.y /= atlasHeight;
|
||||||
|
result.width /= atlasWidth;
|
||||||
|
result.height /= atlasHeight;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1195,6 +1195,16 @@ Billboard._updateClamping = function (collection, owner) {
|
||||||
updateFunction(scratchCartographic);
|
updateFunction(scratchCartographic);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the image coordinates for reading the loaded texture in shaders.
|
||||||
|
* @param {BoundingRectangle} [result] The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
|
* @return {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
Billboard.prototype.computeImageCoordinates = function (result) {
|
||||||
|
return this._imageTexture.computeImageCoordinates(result);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the texture coordinates for reading the loaded texture in shaders.
|
* Get the texture coordinates for reading the loaded texture in shaders.
|
||||||
* @param {BoundingRectangle} [result] The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
* @param {BoundingRectangle} [result] The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,14 @@ const SDF_INDEX = Billboard.SDF_INDEX;
|
||||||
const SPLIT_DIRECTION_INDEX = Billboard.SPLIT_DIRECTION_INDEX;
|
const SPLIT_DIRECTION_INDEX = Billboard.SPLIT_DIRECTION_INDEX;
|
||||||
const NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;
|
const NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;
|
||||||
|
|
||||||
|
const scratchTextureSize = new Cartesian2();
|
||||||
|
|
||||||
let attributeLocations;
|
let attributeLocations;
|
||||||
|
|
||||||
const attributeLocationsBatched = {
|
const attributeLocationsBatched = {
|
||||||
positionHighAndScale: 0,
|
positionHighAndScale: 0,
|
||||||
positionLowAndRotation: 1,
|
positionLowAndRotation: 1,
|
||||||
compressedAttribute0: 2, // pixel offset, translate, horizontal origin, vertical origin, show, direction, texture coordinates
|
compressedAttribute0: 2, // pixel offset, translate, horizontal origin, vertical origin, show, direction, image coordinates (px)
|
||||||
compressedAttribute1: 3, // aligned axis, translucency by distance, image width
|
compressedAttribute1: 3, // aligned axis, translucency by distance, image width
|
||||||
compressedAttribute2: 4, // image height, color, pick color, size in meters, valid aligned axis, 13 bits free
|
compressedAttribute2: 4, // image height, color, pick color, size in meters, valid aligned axis, 13 bits free
|
||||||
eyeOffset: 5, // 4 bytes free
|
eyeOffset: 5, // 4 bytes free
|
||||||
|
|
@ -78,11 +80,11 @@ const attributeLocationsBatched = {
|
||||||
const attributeLocationsInstanced = {
|
const attributeLocationsInstanced = {
|
||||||
direction: 0,
|
direction: 0,
|
||||||
positionHighAndScale: 1,
|
positionHighAndScale: 1,
|
||||||
positionLowAndRotation: 2, // texture offset in w
|
positionLowAndRotation: 2,
|
||||||
compressedAttribute0: 3,
|
compressedAttribute0: 3, // image lower-left coordinates (px) in w
|
||||||
compressedAttribute1: 4,
|
compressedAttribute1: 4,
|
||||||
compressedAttribute2: 5,
|
compressedAttribute2: 5,
|
||||||
eyeOffset: 6, // texture range in w
|
eyeOffset: 6,
|
||||||
scaleByDistance: 7,
|
scaleByDistance: 7,
|
||||||
pixelOffsetScaleByDistance: 8,
|
pixelOffsetScaleByDistance: 8,
|
||||||
compressedAttribute3: 9,
|
compressedAttribute3: 9,
|
||||||
|
|
@ -322,6 +324,10 @@ function BillboardCollection(options) {
|
||||||
u_atlas: () => {
|
u_atlas: () => {
|
||||||
return this.textureAtlas.texture;
|
return this.textureAtlas.texture;
|
||||||
},
|
},
|
||||||
|
u_atlasSize: () => {
|
||||||
|
const { width, height } = this.textureAtlas.texture;
|
||||||
|
return Cartesian2.fromElements(width, height, scratchTextureSize);
|
||||||
|
},
|
||||||
u_highlightColor: () => {
|
u_highlightColor: () => {
|
||||||
return this._highlightColor;
|
return this._highlightColor;
|
||||||
},
|
},
|
||||||
|
|
@ -938,8 +944,6 @@ function writePositionScaleAndRotation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const scratchCartesian2 = new Cartesian2();
|
|
||||||
|
|
||||||
const UPPER_BOUND = 32768.0; // 2^15
|
const UPPER_BOUND = 32768.0; // 2^15
|
||||||
|
|
||||||
const LEFT_SHIFT16 = 65536.0; // 2^16
|
const LEFT_SHIFT16 = 65536.0; // 2^16
|
||||||
|
|
@ -1003,22 +1007,18 @@ function writeCompressedAttrib0(
|
||||||
billboardCollection._allVerticalCenter &&
|
billboardCollection._allVerticalCenter &&
|
||||||
verticalOrigin === VerticalOrigin.CENTER;
|
verticalOrigin === VerticalOrigin.CENTER;
|
||||||
|
|
||||||
let bottomLeftX = 0;
|
// Compute image coordinates and size, in pixels. Coordinates are from lower-left of texture atlas.Z
|
||||||
let bottomLeftY = 0;
|
let imageX = 0;
|
||||||
let width = 0;
|
let imageY = 0;
|
||||||
let height = 0;
|
let imageWidth = 0;
|
||||||
|
let imageHeight = 0;
|
||||||
if (billboard.ready) {
|
if (billboard.ready) {
|
||||||
const imageRectangle = billboard.computeTextureCoordinates(
|
billboard.computeImageCoordinates(scratchBoundingRectangle);
|
||||||
scratchBoundingRectangle,
|
imageX = scratchBoundingRectangle.x;
|
||||||
);
|
imageY = scratchBoundingRectangle.y;
|
||||||
|
imageWidth = scratchBoundingRectangle.width;
|
||||||
bottomLeftX = imageRectangle.x;
|
imageHeight = scratchBoundingRectangle.height;
|
||||||
bottomLeftY = imageRectangle.y;
|
|
||||||
width = imageRectangle.width;
|
|
||||||
height = imageRectangle.height;
|
|
||||||
}
|
}
|
||||||
const topRightX = bottomLeftX + width;
|
|
||||||
const topRightY = bottomLeftY + height;
|
|
||||||
|
|
||||||
let compressed0 =
|
let compressed0 =
|
||||||
Math.floor(
|
Math.floor(
|
||||||
|
|
@ -1055,23 +1055,17 @@ function writeCompressedAttrib0(
|
||||||
compressed1 += upperTranslateY;
|
compressed1 += upperTranslateY;
|
||||||
compressed2 += lowerTranslateY;
|
compressed2 += lowerTranslateY;
|
||||||
|
|
||||||
scratchCartesian2.x = bottomLeftX;
|
// Compress image coordinates (px), integers 0-2^12 from lower-left of atlas. Avoid
|
||||||
scratchCartesian2.y = bottomLeftY;
|
// `AttributeCompression.compressTextureCoordinates` for lossless pixel values.
|
||||||
const compressedTexCoordsLL =
|
const compressedImageLL = imageX * LEFT_SHIFT12 + imageY;
|
||||||
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
|
const compressedImageLR = (imageX + imageWidth) * LEFT_SHIFT12 + imageY;
|
||||||
scratchCartesian2.x = topRightX;
|
const compressedImageUR =
|
||||||
const compressedTexCoordsLR =
|
(imageX + imageWidth) * LEFT_SHIFT12 + imageY + imageHeight;
|
||||||
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
|
const compressedImageUL = imageX * LEFT_SHIFT12 + imageY + imageHeight;
|
||||||
scratchCartesian2.y = topRightY;
|
|
||||||
const compressedTexCoordsUR =
|
|
||||||
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
|
|
||||||
scratchCartesian2.x = bottomLeftX;
|
|
||||||
const compressedTexCoordsUL =
|
|
||||||
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
|
|
||||||
|
|
||||||
if (billboardCollection._instanced) {
|
if (billboardCollection._instanced) {
|
||||||
i = billboard._index;
|
i = billboard._index;
|
||||||
writer(i, compressed0, compressed1, compressed2, compressedTexCoordsLL);
|
writer(i, compressed0, compressed1, compressed2, compressedImageLL);
|
||||||
} else {
|
} else {
|
||||||
i = billboard._index * 4;
|
i = billboard._index * 4;
|
||||||
writer(
|
writer(
|
||||||
|
|
@ -1079,28 +1073,28 @@ function writeCompressedAttrib0(
|
||||||
compressed0 + LOWER_LEFT,
|
compressed0 + LOWER_LEFT,
|
||||||
compressed1,
|
compressed1,
|
||||||
compressed2,
|
compressed2,
|
||||||
compressedTexCoordsLL,
|
compressedImageLL,
|
||||||
);
|
);
|
||||||
writer(
|
writer(
|
||||||
i + 1,
|
i + 1,
|
||||||
compressed0 + LOWER_RIGHT,
|
compressed0 + LOWER_RIGHT,
|
||||||
compressed1,
|
compressed1,
|
||||||
compressed2,
|
compressed2,
|
||||||
compressedTexCoordsLR,
|
compressedImageLR,
|
||||||
);
|
);
|
||||||
writer(
|
writer(
|
||||||
i + 2,
|
i + 2,
|
||||||
compressed0 + UPPER_RIGHT,
|
compressed0 + UPPER_RIGHT,
|
||||||
compressed1,
|
compressed1,
|
||||||
compressed2,
|
compressed2,
|
||||||
compressedTexCoordsUR,
|
compressedImageUR,
|
||||||
);
|
);
|
||||||
writer(
|
writer(
|
||||||
i + 3,
|
i + 3,
|
||||||
compressed0 + UPPER_LEFT,
|
compressed0 + UPPER_LEFT,
|
||||||
compressed1,
|
compressed1,
|
||||||
compressed2,
|
compressed2,
|
||||||
compressedTexCoordsUL,
|
compressedImageUL,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1254,23 +1248,8 @@ function writeEyeOffset(
|
||||||
);
|
);
|
||||||
|
|
||||||
if (billboardCollection._instanced) {
|
if (billboardCollection._instanced) {
|
||||||
scratchCartesian2.x = 0;
|
|
||||||
scratchCartesian2.y = 0;
|
|
||||||
|
|
||||||
if (billboard.ready) {
|
|
||||||
const imageRectangle = billboard.computeTextureCoordinates(
|
|
||||||
scratchBoundingRectangle,
|
|
||||||
);
|
|
||||||
|
|
||||||
scratchCartesian2.x = imageRectangle.width;
|
|
||||||
scratchCartesian2.y = imageRectangle.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
const compressedTexCoordsRange =
|
|
||||||
AttributeCompression.compressTextureCoordinates(scratchCartesian2);
|
|
||||||
|
|
||||||
i = billboard._index;
|
i = billboard._index;
|
||||||
writer(i, eyeOffset.x, eyeOffset.y, eyeOffsetZ, compressedTexCoordsRange);
|
writer(i, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);
|
||||||
} else {
|
} else {
|
||||||
i = billboard._index * 4;
|
i = billboard._index * 4;
|
||||||
writer(i + 0, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);
|
writer(i + 0, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);
|
||||||
|
|
|
||||||
|
|
@ -334,6 +334,17 @@ BillboardTexture.prototype.setImageSubRegion = function (index, subRegion) {
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the image coordinates for reading the loaded texture in shaders.
|
||||||
|
* @private
|
||||||
|
* @param {BoundingRectangle} [result] The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
|
* @return {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.
|
||||||
|
*/
|
||||||
|
BillboardTexture.prototype.computeImageCoordinates = function (result) {
|
||||||
|
const atlas = this._billboardCollection.textureAtlas;
|
||||||
|
return atlas.computeImageCoordinates(this._index, result);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the texture coordinates for reading the loaded texture in shaders.
|
* Get the texture coordinates for reading the loaded texture in shaders.
|
||||||
* @private
|
* @private
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
uniform vec2 u_atlasSize;
|
||||||
uniform float u_threePointDepthTestDistance;
|
uniform float u_threePointDepthTestDistance;
|
||||||
#ifdef INSTANCED
|
#ifdef INSTANCED
|
||||||
in vec2 direction;
|
in vec2 direction;
|
||||||
|
|
@ -47,6 +48,7 @@ const float SHIFT_LEFT3 = 8.0;
|
||||||
const float SHIFT_LEFT2 = 4.0;
|
const float SHIFT_LEFT2 = 4.0;
|
||||||
const float SHIFT_LEFT1 = 2.0;
|
const float SHIFT_LEFT1 = 2.0;
|
||||||
|
|
||||||
|
const float SHIFT_RIGHT16 = 1.0 / 65536.0;
|
||||||
const float SHIFT_RIGHT12 = 1.0 / 4096.0;
|
const float SHIFT_RIGHT12 = 1.0 / 4096.0;
|
||||||
const float SHIFT_RIGHT8 = 1.0 / 256.0;
|
const float SHIFT_RIGHT8 = 1.0 / 256.0;
|
||||||
const float SHIFT_RIGHT7 = 1.0 / 128.0;
|
const float SHIFT_RIGHT7 = 1.0 / 128.0;
|
||||||
|
|
@ -146,16 +148,10 @@ void main()
|
||||||
float show = floor(compressed * SHIFT_RIGHT2);
|
float show = floor(compressed * SHIFT_RIGHT2);
|
||||||
compressed -= show * SHIFT_LEFT2;
|
compressed -= show * SHIFT_LEFT2;
|
||||||
|
|
||||||
#ifdef INSTANCED
|
#ifndef INSTANCED
|
||||||
vec2 textureCoordinatesBottomLeft = czm_decompressTextureCoordinates(compressedAttribute0.w);
|
|
||||||
vec2 textureCoordinatesRange = czm_decompressTextureCoordinates(eyeOffset.w);
|
|
||||||
vec2 textureCoordinates = textureCoordinatesBottomLeft + direction * textureCoordinatesRange;
|
|
||||||
#else
|
|
||||||
vec2 direction;
|
vec2 direction;
|
||||||
direction.x = floor(compressed * SHIFT_RIGHT1);
|
direction.x = floor(compressed * SHIFT_RIGHT1);
|
||||||
direction.y = compressed - direction.x * SHIFT_LEFT1;
|
direction.y = compressed - direction.x * SHIFT_LEFT1;
|
||||||
|
|
||||||
vec2 textureCoordinates = czm_decompressTextureCoordinates(compressedAttribute0.w);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float temp = compressedAttribute0.y * SHIFT_RIGHT8;
|
float temp = compressedAttribute0.y * SHIFT_RIGHT8;
|
||||||
|
|
@ -172,10 +168,19 @@ void main()
|
||||||
translate.y -= UPPER_BOUND;
|
translate.y -= UPPER_BOUND;
|
||||||
translate.y *= SHIFT_RIGHT2;
|
translate.y *= SHIFT_RIGHT2;
|
||||||
|
|
||||||
temp = compressedAttribute1.x * SHIFT_RIGHT8;
|
// TODO(donmccurdy): This is billboard size (px) on screen, not image size (px) in atlas?
|
||||||
float temp2 = floor(compressedAttribute2.w * SHIFT_RIGHT2);
|
float imageWidth = floor(compressedAttribute1.x * SHIFT_RIGHT8);
|
||||||
|
float imageHeight = floor(compressedAttribute2.w * SHIFT_RIGHT2);
|
||||||
|
vec2 imageSize = vec2(imageWidth, imageHeight);
|
||||||
|
|
||||||
vec2 imageSize = vec2(floor(temp), temp2);
|
float imageOffsetX = floor(compressedAttribute0.w * SHIFT_RIGHT12);
|
||||||
|
float imageOffsetY = compressedAttribute0.w - (imageOffsetX * SHIFT_LEFT12);
|
||||||
|
vec2 textureCoordinates = vec2(imageOffsetX + 0.5, imageOffsetY + 0.5) / u_atlasSize.xy;
|
||||||
|
|
||||||
|
#ifdef INSTANCED
|
||||||
|
vec2 textureCoordinatesRange = imageSize.xy / u_atlasSize.xy; // TODO(donmccurdy): Needs -1.0 offset?
|
||||||
|
textureCoordinates += direction * textureCoordinatesRange;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef FS_THREE_POINT_DEPTH_CHECK
|
#ifdef FS_THREE_POINT_DEPTH_CHECK
|
||||||
float labelHorizontalOrigin = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));
|
float labelHorizontalOrigin = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));
|
||||||
|
|
@ -328,7 +333,7 @@ void main()
|
||||||
if (lengthSq < (u_threePointDepthTestDistance * u_threePointDepthTestDistance) && (enableDepthCheck == 1.0)) {
|
if (lengthSq < (u_threePointDepthTestDistance * u_threePointDepthTestDistance) && (enableDepthCheck == 1.0)) {
|
||||||
float depthsilon = 10.0;
|
float depthsilon = 10.0;
|
||||||
vec2 depthOrigin;
|
vec2 depthOrigin;
|
||||||
// Horizontal origin for labels comes from a special attribute. If that value is 0, this is a billboard - use the regular origin.
|
// 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).
|
// Otherwise, transform the label origin to -1, 0, 1 (right, center, left).
|
||||||
depthOrigin.x = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));
|
depthOrigin.x = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));
|
||||||
depthOrigin.x = czm_branchFreeTernary(depthOrigin.x == 0.0, origin.x, depthOrigin.x - 2.0);
|
depthOrigin.x = czm_branchFreeTernary(depthOrigin.x == 0.0, origin.x, depthOrigin.x - 2.0);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue