@hztxi/cesium-engine 25.0.3 → 25.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Build/Workers/chunk-3B2TIEWW.js +73 -0
- package/Build/Workers/chunk-3HOOLJ6E.js +1483 -0
- package/Build/Workers/chunk-3MWOYCFC.js +511 -0
- package/Build/Workers/chunk-3Q52BERF.js +476 -0
- package/Build/Workers/chunk-4MHUA5ZK.js +163 -0
- package/Build/Workers/chunk-5BVKUNRB.js +368 -0
- package/Build/Workers/chunk-642GMGGP.js +162 -0
- package/Build/Workers/chunk-65LZTCWG.js +1344 -0
- package/Build/Workers/chunk-6PYOAYJD.js +1046 -0
- package/Build/Workers/chunk-AH6GJ5MT.js +754 -0
- package/Build/Workers/chunk-AM56LGEB.js +352 -0
- package/Build/Workers/chunk-CADDH6MK.js +140 -0
- package/Build/Workers/chunk-CEIY3YH2.js +57 -0
- package/Build/Workers/chunk-CJT3FTZK.js +58 -0
- package/Build/Workers/chunk-CV7K25H3.js +138 -0
- package/Build/Workers/chunk-DNEERCHO.js +171 -0
- package/Build/Workers/chunk-EHXAKTME.js +147 -0
- package/Build/Workers/chunk-FF6JKPLF.js +454 -0
- package/Build/Workers/chunk-FTRHXHI5.js +3794 -0
- package/Build/Workers/chunk-GH2D6MPO.js +497 -0
- package/Build/Workers/chunk-GHVEEVR7.js +778 -0
- package/Build/Workers/chunk-HUNCRVVV.js +1067 -0
- package/Build/Workers/chunk-IFSGYIDE.js +257 -0
- package/Build/Workers/chunk-ISRYZ3F4.js +414 -0
- package/Build/Workers/chunk-JBJ5PC2D.js +102 -0
- package/Build/Workers/chunk-JFPBQCDB.js +398 -0
- package/Build/Workers/chunk-JKPELBSI.js +682 -0
- package/Build/Workers/chunk-JLLWLD6O.js +973 -0
- package/Build/Workers/chunk-KCUS7QEU.js +387 -0
- package/Build/Workers/chunk-KFRKYG4B.js +288 -0
- package/Build/Workers/chunk-LERIK6IA.js +219 -0
- package/Build/Workers/chunk-LOVXQI64.js +2719 -0
- package/Build/Workers/chunk-MD7CEJO5.js +2342 -0
- package/Build/Workers/chunk-OKPQ3QBG.js +124 -0
- package/Build/Workers/chunk-PC7533X2.js +1800 -0
- package/Build/Workers/chunk-PCXE4XMI.js +82 -0
- package/Build/Workers/chunk-PXPUYOFJ.js +1287 -0
- package/Build/Workers/chunk-QX6AYJX2.js +455 -0
- package/Build/Workers/chunk-RSJUCJPN.js +241 -0
- package/Build/Workers/chunk-SPTT255E.js +301 -0
- package/Build/Workers/chunk-STXWAEVD.js +101 -0
- package/Build/Workers/chunk-SUG6ECWR.js +76 -0
- package/Build/Workers/chunk-TPT5IM72.js +280 -0
- package/Build/Workers/chunk-TTG2JNFN.js +198 -0
- package/Build/Workers/chunk-UDXUBVNR.js +1992 -0
- package/Build/Workers/chunk-UNXJWCXV.js +9230 -0
- package/Build/Workers/chunk-UTKCX3AS.js +352 -0
- package/Build/Workers/chunk-VL2WHGQI.js +305 -0
- package/Build/Workers/chunk-W37YFRTG.js +38 -0
- package/Build/Workers/chunk-W5AGSDWX.js +44 -0
- package/Build/Workers/chunk-WBQDTVCN.js +97 -0
- package/Build/Workers/chunk-WDSHSR57.js +837 -0
- package/Build/Workers/chunk-XPIDT6UT.js +1054 -0
- package/Build/Workers/chunk-XQETP7YD.js +3201 -0
- package/Build/Workers/chunk-Z3KHKVNA.js +56 -0
- package/Build/Workers/chunk-Z7XRKD6H.js +693 -0
- package/Build/Workers/chunk-ZQUSI7YK.js +630 -0
- package/Build/Workers/chunk-ZY4DTNR2.js +56 -0
- package/Build/Workers/combineGeometry.js +24 -24
- package/Build/Workers/createBoxGeometry.js +18 -18
- package/Build/Workers/createBoxOutlineGeometry.js +16 -16
- package/Build/Workers/createCircleGeometry.js +26 -26
- package/Build/Workers/createCircleOutlineGeometry.js +19 -19
- package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
- package/Build/Workers/createCorridorGeometry.js +29 -29
- package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
- package/Build/Workers/createCylinderGeometry.js +20 -20
- package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
- package/Build/Workers/createEllipseGeometry.js +26 -26
- package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
- package/Build/Workers/createEllipsoidGeometry.js +19 -19
- package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
- package/Build/Workers/createFrustumGeometry.js +18 -18
- package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
- package/Build/Workers/createGeometry.js +24 -24
- package/Build/Workers/createGroundPolylineGeometry.js +23 -23
- package/Build/Workers/createPlaneGeometry.js +16 -16
- package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
- package/Build/Workers/createPolygonGeometry.js +32 -32
- package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
- package/Build/Workers/createPolylineGeometry.js +25 -25
- package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
- package/Build/Workers/createRectangleGeometry.js +27 -27
- package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
- package/Build/Workers/createSimplePolylineGeometry.js +23 -23
- package/Build/Workers/createSphereGeometry.js +19 -19
- package/Build/Workers/createSphereOutlineGeometry.js +18 -18
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
- package/Build/Workers/createVectorTileGeometries.js +24 -24
- package/Build/Workers/createVectorTilePoints.js +13 -13
- package/Build/Workers/createVectorTilePolygons.js +22 -22
- package/Build/Workers/createVectorTilePolylines.js +14 -14
- package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -26
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +23 -23
- package/Build/Workers/createVerticesFromHeightmap.js +23 -23
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +21 -21
- package/Build/Workers/createWallGeometry.js +24 -24
- package/Build/Workers/createWallOutlineGeometry.js +23 -23
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
- package/Build/Workers/decodeI3S.js +10 -10
- package/Build/Workers/gaussianSplatSorter.js +4 -4
- package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
- package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
- package/Build/Workers/transcodeKTX2.js +6 -6
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +23 -23
- package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -26
- package/Source/Scene/Globe.js +55 -0
- package/Source/Scene/GlobeSurfaceShaderSet.js +132 -1
- package/Source/Scene/GlobeSurfaceTileProvider.js +378 -2
- package/Source/Scene/ImageryLayer.js +244 -10
- package/Source/Scene/QuadtreePrimitive.js +256 -2
- package/Source/Shaders/GlobeFS.glsl +43 -0
- package/Source/Shaders/GlobeFS.js +43 -0
- package/Source/ThirdParty/zip-module.wasm +0 -0
- package/index.js +371 -371
- package/package.json +10 -10
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Cartesian2 from "../Core/Cartesian2.js";
|
|
2
|
+
import Cartesian3 from "../Core/Cartesian3.js";
|
|
2
3
|
import Cartesian4 from "../Core/Cartesian4.js";
|
|
3
4
|
import Check from "../Core/Check.js";
|
|
4
5
|
import createWorldImageryAsync from "../Scene/createWorldImageryAsync.js";
|
|
@@ -171,12 +172,92 @@ import TileImagery from "./TileImagery.js";
|
|
|
171
172
|
* const imageryLayer = new ImageryLayer(imageryProvider);
|
|
172
173
|
* tileset.imageryLayers.add(imageryLayer);
|
|
173
174
|
*/
|
|
175
|
+
// Clamps chosen so a mistyped profile cannot wash out the imagery entirely.
|
|
176
|
+
const LEVEL_COLOR_MIN_SCALE = 0.5;
|
|
177
|
+
const LEVEL_COLOR_MAX_SCALE = 2.0;
|
|
178
|
+
const LEVEL_COLOR_MAX_OFFSET = 0.25;
|
|
179
|
+
|
|
180
|
+
function clampLevelColorValue(value, min, max) {
|
|
181
|
+
return Math.min(Math.max(value, min), max);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Converts a public levelColorProfile object into per-level gain/bias pairs
|
|
186
|
+
* with the correction strength already folded in:
|
|
187
|
+
* gain = 1 + strength * (scale - 1), bias = strength * offset.
|
|
188
|
+
*
|
|
189
|
+
* @param {object|undefined} profile The public profile object.
|
|
190
|
+
* @returns {object|undefined} Map of level to {gain, bias}, or undefined.
|
|
191
|
+
* @private
|
|
192
|
+
*/
|
|
193
|
+
function normalizeLevelColorProfile(profile) {
|
|
194
|
+
if (!defined(profile) || !defined(profile.levels)) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const strength = clampLevelColorValue(profile.strength ?? 1.0, 0.0, 1.0);
|
|
199
|
+
const entries = {};
|
|
200
|
+
for (const level of Object.keys(profile.levels)) {
|
|
201
|
+
const entry = profile.levels[level];
|
|
202
|
+
if (!defined(entry)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const scale = defined(entry.scale) ? entry.scale : [1, 1, 1];
|
|
206
|
+
const offset = defined(entry.offset) ? entry.offset : [0, 0, 0];
|
|
207
|
+
entries[level] = {
|
|
208
|
+
gain: new Cartesian3(
|
|
209
|
+
clampLevelColorValue(
|
|
210
|
+
1.0 + strength * (scale[0] - 1.0),
|
|
211
|
+
LEVEL_COLOR_MIN_SCALE,
|
|
212
|
+
LEVEL_COLOR_MAX_SCALE,
|
|
213
|
+
),
|
|
214
|
+
clampLevelColorValue(
|
|
215
|
+
1.0 + strength * (scale[1] - 1.0),
|
|
216
|
+
LEVEL_COLOR_MIN_SCALE,
|
|
217
|
+
LEVEL_COLOR_MAX_SCALE,
|
|
218
|
+
),
|
|
219
|
+
clampLevelColorValue(
|
|
220
|
+
1.0 + strength * (scale[2] - 1.0),
|
|
221
|
+
LEVEL_COLOR_MIN_SCALE,
|
|
222
|
+
LEVEL_COLOR_MAX_SCALE,
|
|
223
|
+
),
|
|
224
|
+
),
|
|
225
|
+
bias: new Cartesian3(
|
|
226
|
+
clampLevelColorValue(
|
|
227
|
+
strength * offset[0],
|
|
228
|
+
-LEVEL_COLOR_MAX_OFFSET,
|
|
229
|
+
LEVEL_COLOR_MAX_OFFSET,
|
|
230
|
+
),
|
|
231
|
+
clampLevelColorValue(
|
|
232
|
+
strength * offset[1],
|
|
233
|
+
-LEVEL_COLOR_MAX_OFFSET,
|
|
234
|
+
LEVEL_COLOR_MAX_OFFSET,
|
|
235
|
+
),
|
|
236
|
+
clampLevelColorValue(
|
|
237
|
+
strength * offset[2],
|
|
238
|
+
-LEVEL_COLOR_MAX_OFFSET,
|
|
239
|
+
LEVEL_COLOR_MAX_OFFSET,
|
|
240
|
+
),
|
|
241
|
+
),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return { entries };
|
|
245
|
+
}
|
|
246
|
+
|
|
174
247
|
function ImageryLayer(imageryProvider, options) {
|
|
175
248
|
this._imageryProvider = imageryProvider;
|
|
176
249
|
|
|
177
250
|
this._readyEvent = new Event();
|
|
178
251
|
this._errorEvent = new Event();
|
|
179
252
|
|
|
253
|
+
// Normalized form of the public levelColorProfile: per-level gain/bias
|
|
254
|
+
// Cartesian3 pairs with the correction strength already folded in.
|
|
255
|
+
this._levelColorProfile = undefined;
|
|
256
|
+
this._levelColorProfileInput = undefined;
|
|
257
|
+
|
|
258
|
+
this._levelColorEdgeBlend = 0.0;
|
|
259
|
+
this._levelColorEdgeCrossFade = true;
|
|
260
|
+
|
|
180
261
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
181
262
|
imageryProvider = imageryProvider ?? Frozen.EMPTY_OBJECT;
|
|
182
263
|
|
|
@@ -372,6 +453,116 @@ Object.defineProperties(ImageryLayer.prototype, {
|
|
|
372
453
|
},
|
|
373
454
|
},
|
|
374
455
|
|
|
456
|
+
/**
|
|
457
|
+
* Gets or sets a per-level color correction profile for this layer. Imagery
|
|
458
|
+
* pyramids from third-party providers are frequently assembled from different
|
|
459
|
+
* mosaic vintages per level, which shows up as a visible color seam wherever
|
|
460
|
+
* two levels are rendered next to each other (typically in tilted views).
|
|
461
|
+
* The profile applies one per-channel affine transform
|
|
462
|
+
* (<code>scale * color + offset</code>, normalized [0, 1] units) to every
|
|
463
|
+
* tile of a given level, which makes adjacent levels visually continuous.
|
|
464
|
+
* Levels not listed in the profile are left uncorrected.
|
|
465
|
+
*
|
|
466
|
+
* The profile is a plain object, typically generated by the
|
|
467
|
+
* <code>Apps/LevelColorCalibration.html</code> tool, of the form:
|
|
468
|
+
* <pre>{
|
|
469
|
+
* "strength": 0.8,
|
|
470
|
+
* "referenceLevel": 16,
|
|
471
|
+
* "levels": {
|
|
472
|
+
* "14": { "scale": [1.02, 1.01, 0.98], "offset": [-0.01, 0.0, 0.02] },
|
|
473
|
+
* "17": { "scale": [0.99, 1.0, 1.03], "offset": [0.0, -0.01, 0.03] }
|
|
474
|
+
* }
|
|
475
|
+
* }</pre>
|
|
476
|
+
* <code>strength</code> (default <code>1.0</code>) blends between the original
|
|
477
|
+
* and corrected color, <code>(1 - strength) * original + strength * (scale * original + offset)</code>,
|
|
478
|
+
* so values below 1 keep some of the original per-level character.
|
|
479
|
+
*
|
|
480
|
+
* Assigning a profile takes effect immediately, without reloading tiles;
|
|
481
|
+
* setting it to <code>undefined</code> disables the correction.
|
|
482
|
+
*
|
|
483
|
+
* @memberof ImageryLayer.prototype
|
|
484
|
+
* @type {object|undefined}
|
|
485
|
+
* @default undefined
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* const response = await fetch("level-color-profile.json");
|
|
489
|
+
* layer.levelColorProfile = await response.json();
|
|
490
|
+
*/
|
|
491
|
+
levelColorProfile: {
|
|
492
|
+
get: function () {
|
|
493
|
+
return this._levelColorProfileInput;
|
|
494
|
+
},
|
|
495
|
+
set: function (value) {
|
|
496
|
+
this._levelColorProfileInput = value;
|
|
497
|
+
this._levelColorProfile = normalizeLevelColorProfile(value);
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Gets or sets the width, as a fraction of the tile's extent, of an
|
|
503
|
+
* edge band where this tile's {@link ImageryLayer#levelColorProfile}
|
|
504
|
+
* correction is smoothly faded into the correction of the adjacent
|
|
505
|
+
* coarser tile's level. Residual color steps at imagery LOD boundaries
|
|
506
|
+
* (levels that cannot fully converge, or local deviations from the
|
|
507
|
+
* calibration statistics) become gradual ramps, which are far less
|
|
508
|
+
* visible than abrupt steps. The fade is one-sided: only the finer
|
|
509
|
+
* side of a boundary fades, so both sides apply the same correction
|
|
510
|
+
* exactly at the shared edge. Requires a levelColorProfile; edges
|
|
511
|
+
* facing same-level or finer neighbors are not blended.
|
|
512
|
+
*
|
|
513
|
+
* The value is clamped to [0.0, 0.45]; 0 disables the fade. Values
|
|
514
|
+
* between 0.15 and 0.25 are a good starting point. Takes effect
|
|
515
|
+
* immediately (uniform-only after the first enabling, which compiles
|
|
516
|
+
* one additional shader variant).
|
|
517
|
+
*
|
|
518
|
+
* @memberof ImageryLayer.prototype
|
|
519
|
+
* @type {number}
|
|
520
|
+
* @default 0.0
|
|
521
|
+
*/
|
|
522
|
+
levelColorEdgeBlend: {
|
|
523
|
+
get: function () {
|
|
524
|
+
return this._levelColorEdgeBlend;
|
|
525
|
+
},
|
|
526
|
+
set: function (value) {
|
|
527
|
+
//>>includeStart('debug', pragmas.debug);
|
|
528
|
+
if (defined(value) && typeof value !== "number") {
|
|
529
|
+
throw new DeveloperError("value must be a number.");
|
|
530
|
+
}
|
|
531
|
+
//>>includeEnd('debug');
|
|
532
|
+
this._levelColorEdgeBlend = defined(value)
|
|
533
|
+
? CesiumMath.clamp(value, 0.0, 0.45)
|
|
534
|
+
: 0.0;
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
/**
|
|
538
|
+
* Gets or sets whether the {@link ImageryLayer#levelColorEdgeBlend} band
|
|
539
|
+
* cross-fades the imagery CONTENT with the ancestor imagery at the
|
|
540
|
+
* adjacent coarser tile's level (the very texture the coarser side
|
|
541
|
+
* renders), instead of only fading the correction parameters. Content
|
|
542
|
+
* cross-fading makes both sides of a boundary pixel-identical at the
|
|
543
|
+
* shared edge, which also removes seams caused by content differences
|
|
544
|
+
* (mosaic vintage, local deviations from the calibration statistics)
|
|
545
|
+
* that a correction-parameter fade cannot touch. When the ancestor
|
|
546
|
+
* texture is unavailable, the parameter fade is used as a fallback.
|
|
547
|
+
* Requires a levelColorProfile and levelColorEdgeBlend > 0.
|
|
548
|
+
*
|
|
549
|
+
* @memberof ImageryLayer.prototype
|
|
550
|
+
* @type {boolean}
|
|
551
|
+
* @default true
|
|
552
|
+
*/
|
|
553
|
+
levelColorEdgeCrossFade: {
|
|
554
|
+
get: function () {
|
|
555
|
+
return this._levelColorEdgeCrossFade;
|
|
556
|
+
},
|
|
557
|
+
set: function (value) {
|
|
558
|
+
//>>includeStart('debug', pragmas.debug);
|
|
559
|
+
if (defined(value) && typeof value !== "boolean") {
|
|
560
|
+
throw new DeveloperError("value must be a boolean.");
|
|
561
|
+
}
|
|
562
|
+
//>>includeEnd('debug');
|
|
563
|
+
this._levelColorEdgeCrossFade = value ?? true;
|
|
564
|
+
},
|
|
565
|
+
},
|
|
375
566
|
/**
|
|
376
567
|
* Returns true when the terrain provider has been successfully created. Otherwise, returns false.
|
|
377
568
|
* @memberof ImageryLayer.prototype
|
|
@@ -1047,6 +1238,21 @@ ImageryLayer.prototype._createTileImagerySkeletons = function (
|
|
|
1047
1238
|
return true;
|
|
1048
1239
|
};
|
|
1049
1240
|
|
|
1241
|
+
/**
|
|
1242
|
+
* Returns the normalized color correction for tiles of the given imagery
|
|
1243
|
+
* level, or <code>undefined</code> if the level is not in this layer's
|
|
1244
|
+
* {@link ImageryLayer#levelColorProfile}.
|
|
1245
|
+
*
|
|
1246
|
+
* @param {number} level The imagery level.
|
|
1247
|
+
* @returns {object|undefined} An object with <code>gain</code> and
|
|
1248
|
+
* <code>bias</code> {@link Cartesian3} properties.
|
|
1249
|
+
*
|
|
1250
|
+
* @private
|
|
1251
|
+
*/
|
|
1252
|
+
ImageryLayer.prototype._getLevelColorCorrection = function (level) {
|
|
1253
|
+
return this._levelColorProfile?.entries[level];
|
|
1254
|
+
};
|
|
1255
|
+
|
|
1050
1256
|
/**
|
|
1051
1257
|
* Calculate the translation and scale for a particular {@link TileImagery} attached to a
|
|
1052
1258
|
* particular terrain tile.
|
|
@@ -1062,12 +1268,39 @@ ImageryLayer.prototype._calculateTextureTranslationAndScale = function (
|
|
|
1062
1268
|
tile,
|
|
1063
1269
|
tileImagery,
|
|
1064
1270
|
) {
|
|
1065
|
-
|
|
1271
|
+
return this._calculateImageryTranslationAndScale(
|
|
1272
|
+
tile,
|
|
1273
|
+
tileImagery.readyImagery,
|
|
1274
|
+
tileImagery.useWebMercatorT,
|
|
1275
|
+
new Cartesian4(),
|
|
1276
|
+
);
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1279
|
+
/**
|
|
1280
|
+
* Calculates the translation and scale mapping a terrain tile's 0..1 UV into the
|
|
1281
|
+
* UV space of an arbitrary {@link Imagery} of this layer covering the tile,
|
|
1282
|
+
* writing into {@link result}. Works for coarser ancestors as well: the math only
|
|
1283
|
+
* depends on the two rectangles.
|
|
1284
|
+
*
|
|
1285
|
+
* @private
|
|
1286
|
+
*
|
|
1287
|
+
* @param {Tile} tile The terrain tile.
|
|
1288
|
+
* @param {Imagery} imagery The imagery whose texture space to map into.
|
|
1289
|
+
* @param {boolean} useWebMercatorT Whether the sampling tile uses the Web Mercator T coordinate.
|
|
1290
|
+
* @param {Cartesian4} result The Cartesian4 (x/y translation, z/w scale) to fill.
|
|
1291
|
+
* @returns {Cartesian4} The result.
|
|
1292
|
+
*/
|
|
1293
|
+
ImageryLayer.prototype._calculateImageryTranslationAndScale = function (
|
|
1294
|
+
tile,
|
|
1295
|
+
imagery,
|
|
1296
|
+
useWebMercatorT,
|
|
1297
|
+
result,
|
|
1298
|
+
) {
|
|
1299
|
+
let imageryRectangle = imagery.rectangle;
|
|
1066
1300
|
let terrainRectangle = tile.rectangle;
|
|
1067
1301
|
|
|
1068
|
-
if (
|
|
1069
|
-
const tilingScheme =
|
|
1070
|
-
tileImagery.readyImagery.imageryLayer.imageryProvider.tilingScheme;
|
|
1302
|
+
if (useWebMercatorT) {
|
|
1303
|
+
const tilingScheme = this.imageryProvider.tilingScheme;
|
|
1071
1304
|
imageryRectangle = tilingScheme.rectangleToNativeRectangle(
|
|
1072
1305
|
imageryRectangle,
|
|
1073
1306
|
imageryBoundsScratch,
|
|
@@ -1083,13 +1316,14 @@ ImageryLayer.prototype._calculateTextureTranslationAndScale = function (
|
|
|
1083
1316
|
|
|
1084
1317
|
const scaleX = terrainWidth / imageryRectangle.width;
|
|
1085
1318
|
const scaleY = terrainHeight / imageryRectangle.height;
|
|
1086
|
-
|
|
1087
|
-
(scaleX * (terrainRectangle.west - imageryRectangle.west)) / terrainWidth
|
|
1319
|
+
result.x =
|
|
1320
|
+
(scaleX * (terrainRectangle.west - imageryRectangle.west)) / terrainWidth;
|
|
1321
|
+
result.y =
|
|
1088
1322
|
(scaleY * (terrainRectangle.south - imageryRectangle.south)) /
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1323
|
+
terrainHeight;
|
|
1324
|
+
result.z = scaleX;
|
|
1325
|
+
result.w = scaleY;
|
|
1326
|
+
return result;
|
|
1093
1327
|
};
|
|
1094
1328
|
|
|
1095
1329
|
/**
|
|
@@ -4,6 +4,7 @@ import defined from "../Core/defined.js";
|
|
|
4
4
|
import DeveloperError from "../Core/DeveloperError.js";
|
|
5
5
|
import Event from "../Core/Event.js";
|
|
6
6
|
import getTimestamp from "../Core/getTimestamp.js";
|
|
7
|
+
import IntersectionTests from "../Core/IntersectionTests.js";
|
|
7
8
|
import CesiumMath from "../Core/Math.js";
|
|
8
9
|
import Matrix4 from "../Core/Matrix4.js";
|
|
9
10
|
import OrthographicFrustum from "../Core/OrthographicFrustum.js";
|
|
@@ -109,6 +110,36 @@ function QuadtreePrimitive(options) {
|
|
|
109
110
|
*/
|
|
110
111
|
this.maximumScreenSpaceError = options.maximumScreenSpaceError ?? 2;
|
|
111
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Gets or sets the uniform level-of-detail mode configuration, pushed down
|
|
115
|
+
* from {@link Globe#uniformLevelMode} every frame. When enabled, tile
|
|
116
|
+
* refinement is evaluated against a single per-frame reference distance
|
|
117
|
+
* instead of each tile's own distance, so visible tiles converge on one
|
|
118
|
+
* level instead of a distance-dependent mix. See updateUniformLevelState
|
|
119
|
+
* for the recognized fields.
|
|
120
|
+
*
|
|
121
|
+
* @type {object|undefined}
|
|
122
|
+
* @default undefined
|
|
123
|
+
*/
|
|
124
|
+
this.uniformLevelMode = undefined;
|
|
125
|
+
|
|
126
|
+
// Per-frame uniform-level state, recomputed in beginFrame and consumed by
|
|
127
|
+
// screenSpaceError. version marks the uniformLevelMode implementation
|
|
128
|
+
// revision (1: initial, 2: nearest-fallback + clamp for Columbus,
|
|
129
|
+
// 3: maxCoarsenLevels near-side clamp); it lets callers detect which
|
|
130
|
+
// engine build they are actually running against.
|
|
131
|
+
this._uniformLevelState = {
|
|
132
|
+
version: 3,
|
|
133
|
+
active: false,
|
|
134
|
+
engage: 0.0,
|
|
135
|
+
referenceDistance: undefined,
|
|
136
|
+
deviationFactor: 8.0,
|
|
137
|
+
coarsenFactor: 2.0,
|
|
138
|
+
};
|
|
139
|
+
this._nearestTileDistanceThisFrame = undefined;
|
|
140
|
+
this._nearestTileDistanceLastFrame = undefined;
|
|
141
|
+
this._uniformLevelFrameNumber = -1;
|
|
142
|
+
|
|
112
143
|
/**
|
|
113
144
|
* Gets or sets the maximum number of tiles that will be retained in the tile cache.
|
|
114
145
|
* Note that tiles will never be unloaded if they were used for rendering the last
|
|
@@ -343,6 +374,8 @@ QuadtreePrimitive.prototype.beginFrame = function (frameState) {
|
|
|
343
374
|
|
|
344
375
|
clearTileLoadQueue(this);
|
|
345
376
|
|
|
377
|
+
updateUniformLevelState(this, frameState);
|
|
378
|
+
|
|
346
379
|
if (this._debug.suspendLodUpdate) {
|
|
347
380
|
return;
|
|
348
381
|
}
|
|
@@ -722,6 +755,20 @@ function visitTile(
|
|
|
722
755
|
|
|
723
756
|
++debug.tilesVisited;
|
|
724
757
|
|
|
758
|
+
// Track the nearest visible tile distance for uniform-level mode's
|
|
759
|
+
// "nearest" reference. computeTileVisibility has already refreshed
|
|
760
|
+
// tile._distance for this frame by the time a tile is visited.
|
|
761
|
+
const uniformMode = primitive.uniformLevelMode;
|
|
762
|
+
if (defined(uniformMode) && uniformMode.enabled === true) {
|
|
763
|
+
const tileDistance = tile._distance;
|
|
764
|
+
if (defined(tileDistance)) {
|
|
765
|
+
const nearest = primitive._nearestTileDistanceThisFrame;
|
|
766
|
+
if (!defined(nearest) || tileDistance < nearest) {
|
|
767
|
+
primitive._nearestTileDistanceThisFrame = tileDistance;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
725
772
|
primitive._tileReplacementQueue.markTileRendered(tile);
|
|
726
773
|
tile.updateCustomData();
|
|
727
774
|
|
|
@@ -1245,6 +1292,176 @@ function visitIfVisible(
|
|
|
1245
1292
|
tile._lastSelectionResultFrame = frameState.frameNumber;
|
|
1246
1293
|
}
|
|
1247
1294
|
|
|
1295
|
+
const uniformLevelScratchUp = new Cartesian3();
|
|
1296
|
+
const uniformLevelScratchRay = new Ray();
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* Recomputes the per-frame uniform-level state consumed by screenSpaceError.
|
|
1300
|
+
*
|
|
1301
|
+
* Uniform-level mode makes tiles in view converge on one LOD level by
|
|
1302
|
+
* evaluating refinement against a single per-frame reference distance instead
|
|
1303
|
+
* of each tile's own distance:
|
|
1304
|
+
*
|
|
1305
|
+
* reference: "center" (default) uses the camera-to-globe-center distance
|
|
1306
|
+
* along the view ray; "nearest" uses the distance of the nearest
|
|
1307
|
+
* visible tile from the previous frame.
|
|
1308
|
+
* maxDeviationLevels (default 3) caps how many levels above the natural LOD
|
|
1309
|
+
* far tiles may be forced to refine, bounding the tile-count
|
|
1310
|
+
* increase toward the horizon.
|
|
1311
|
+
* maxCoarsenLevels (default 1, clamped to [0, 10]) caps how many levels
|
|
1312
|
+
* below the natural LOD near (foreground) tiles may be held
|
|
1313
|
+
* back. Uncapped, the foreground of a tilted far view lands
|
|
1314
|
+
* 2+ levels coarser than natural, and verticalExaggeration > 1
|
|
1315
|
+
* multiplies the interpolation error of coarse terrain
|
|
1316
|
+
* (1 level = 4x, 2 levels = 16x) into visible tearing. 1
|
|
1317
|
+
* measures +0~4% tile requests; 0 makes the foreground fully
|
|
1318
|
+
* natural (+5~69% requests) but mixes near/far levels again,
|
|
1319
|
+
* bringing back the dataset's cross-level color bands.
|
|
1320
|
+
* pitchRangeDegrees (default undefined = always engaged) is a [full, none]
|
|
1321
|
+
* pair of pitch angles; the effect fades out between them as the
|
|
1322
|
+
* view approaches the horizon. Pass null or leave undefined to
|
|
1323
|
+
* keep it fully engaged (e.g. for offline export).
|
|
1324
|
+
*
|
|
1325
|
+
* The effect is blended in by an engage factor, and the reference distance is
|
|
1326
|
+
* EMA-smoothed (snapping across large jumps, e.g. camera cuts during export)
|
|
1327
|
+
* so the selected level does not flap frame to frame.
|
|
1328
|
+
*
|
|
1329
|
+
* @private
|
|
1330
|
+
*/
|
|
1331
|
+
function updateUniformLevelState(primitive, frameState) {
|
|
1332
|
+
const state = primitive._uniformLevelState;
|
|
1333
|
+
state.active = false;
|
|
1334
|
+
state.engage = 0.0;
|
|
1335
|
+
|
|
1336
|
+
// Roll over nearest-tile-distance tracking once per frame. Multiple render
|
|
1337
|
+
// passes can occur within one frame (as in 2D), so key on frame number.
|
|
1338
|
+
if (primitive._uniformLevelFrameNumber !== frameState.frameNumber) {
|
|
1339
|
+
primitive._uniformLevelFrameNumber = frameState.frameNumber;
|
|
1340
|
+
primitive._nearestTileDistanceLastFrame =
|
|
1341
|
+
primitive._nearestTileDistanceThisFrame;
|
|
1342
|
+
primitive._nearestTileDistanceThisFrame = undefined;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
const mode = primitive.uniformLevelMode;
|
|
1346
|
+
if (!defined(mode) || mode.enabled !== true) {
|
|
1347
|
+
// Drop stale smoothing state so re-enabling starts fresh.
|
|
1348
|
+
state.referenceDistance = undefined;
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
// The 3D SSE path (perspective frustum) is the distance-dependent one, and
|
|
1353
|
+
// it is used in both SCENE3D and Columbus view, so both need the mode.
|
|
1354
|
+
// True 2D (SCENE2D) SSE is already distance-independent.
|
|
1355
|
+
const isColumbusView = frameState.mode === SceneMode.COLUMBUS_VIEW;
|
|
1356
|
+
if (frameState.mode !== SceneMode.SCENE3D && !isColumbusView) {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
const camera = frameState.camera;
|
|
1361
|
+
const alignment = CesiumMath.clamp(
|
|
1362
|
+
-Cartesian3.dot(
|
|
1363
|
+
Cartesian3.normalize(camera.positionWC, uniformLevelScratchUp),
|
|
1364
|
+
camera.directionWC,
|
|
1365
|
+
),
|
|
1366
|
+
0.0,
|
|
1367
|
+
1.0,
|
|
1368
|
+
);
|
|
1369
|
+
// alignment is 1.0 looking straight down and 0.0 at or above the horizon.
|
|
1370
|
+
|
|
1371
|
+
let engage = 1.0;
|
|
1372
|
+
const pitchRange = mode.pitchRangeDegrees;
|
|
1373
|
+
if (defined(pitchRange) && pitchRange !== null) {
|
|
1374
|
+
const fullAlignment = Math.sin(
|
|
1375
|
+
CesiumMath.toRadians(Math.abs(pitchRange[0])),
|
|
1376
|
+
);
|
|
1377
|
+
const noneAlignment = Math.sin(
|
|
1378
|
+
CesiumMath.toRadians(Math.abs(pitchRange[1])),
|
|
1379
|
+
);
|
|
1380
|
+
const alignmentRange = Math.max(fullAlignment - noneAlignment, 1e-6);
|
|
1381
|
+
let t = (alignment - noneAlignment) / alignmentRange;
|
|
1382
|
+
t = CesiumMath.clamp(t, 0.0, 1.0);
|
|
1383
|
+
engage = t * t * (3.0 - 2.0 * t);
|
|
1384
|
+
}
|
|
1385
|
+
if (engage <= 0.0) {
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
let referenceDistance;
|
|
1390
|
+
const nearestDistance = primitive._nearestTileDistanceLastFrame;
|
|
1391
|
+
if (mode.reference === "nearest") {
|
|
1392
|
+
referenceDistance = nearestDistance;
|
|
1393
|
+
} else if (isColumbusView) {
|
|
1394
|
+
// In Columbus view the flattened map is the x = 0 plane in world
|
|
1395
|
+
// coordinates (see pickMapColumbusView): the center-of-view distance is
|
|
1396
|
+
// the view ray parameter where it crosses that plane.
|
|
1397
|
+
const directionX = camera.directionWC.x;
|
|
1398
|
+
if (directionX !== 0.0) {
|
|
1399
|
+
const scalar = -camera.positionWC.x / directionX;
|
|
1400
|
+
referenceDistance = scalar > 0.0 ? scalar : undefined;
|
|
1401
|
+
}
|
|
1402
|
+
// The plane math assumes the default Columbus embedding; a camera
|
|
1403
|
+
// reference transform (lookAt etc.) or animation-driven position can
|
|
1404
|
+
// break the sign assumptions. Fall back to the tracked nearest tile
|
|
1405
|
+
// distance, which is frame-consistent no matter how the camera got
|
|
1406
|
+
// there.
|
|
1407
|
+
if (!defined(referenceDistance)) {
|
|
1408
|
+
referenceDistance = nearestDistance;
|
|
1409
|
+
}
|
|
1410
|
+
} else {
|
|
1411
|
+
const ray = uniformLevelScratchRay;
|
|
1412
|
+
Cartesian3.clone(camera.positionWC, ray.origin);
|
|
1413
|
+
Cartesian3.clone(camera.directionWC, ray.direction);
|
|
1414
|
+
const intersection = IntersectionTests.rayEllipsoid(
|
|
1415
|
+
ray,
|
|
1416
|
+
primitive._tileProvider.tilingScheme.ellipsoid,
|
|
1417
|
+
);
|
|
1418
|
+
referenceDistance = defined(intersection) ? intersection.start : undefined;
|
|
1419
|
+
}
|
|
1420
|
+
// Horizon-looking views miss the ground entirely; fall back to the nearest
|
|
1421
|
+
// tracked distance there too so the mode stays engaged.
|
|
1422
|
+
if (!defined(referenceDistance)) {
|
|
1423
|
+
referenceDistance = nearestDistance;
|
|
1424
|
+
}
|
|
1425
|
+
// Sanity clamp: keep the reference within an order of magnitude of the
|
|
1426
|
+
// nearest visible tile distance, so a degenerate camera frame cannot
|
|
1427
|
+
// demand levels far outside what visible tiles can plausibly load.
|
|
1428
|
+
if (
|
|
1429
|
+
defined(referenceDistance) &&
|
|
1430
|
+
defined(nearestDistance) &&
|
|
1431
|
+
nearestDistance > 0.0
|
|
1432
|
+
) {
|
|
1433
|
+
referenceDistance = Math.min(referenceDistance, 8.0 * nearestDistance);
|
|
1434
|
+
}
|
|
1435
|
+
if (!defined(referenceDistance) || referenceDistance <= 0.0) {
|
|
1436
|
+
// No ground along the view ray (or no tracking yet): leave inactive.
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// Smooth the reference distance to avoid level flapping, but snap across
|
|
1441
|
+
// large discontinuities (camera cuts, e.g. per-frame seeks in export).
|
|
1442
|
+
const previous = state.referenceDistance;
|
|
1443
|
+
if (defined(previous) && previous > 0.0) {
|
|
1444
|
+
const ratio = referenceDistance / previous;
|
|
1445
|
+
referenceDistance =
|
|
1446
|
+
ratio < 0.5 || ratio > 2.0
|
|
1447
|
+
? referenceDistance
|
|
1448
|
+
: previous + 0.25 * (referenceDistance - previous);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
const maxDeviationLevels = CesiumMath.clamp(
|
|
1452
|
+
mode.maxDeviationLevels ?? 3,
|
|
1453
|
+
0,
|
|
1454
|
+
10,
|
|
1455
|
+
);
|
|
1456
|
+
const maxCoarsenLevels = CesiumMath.clamp(mode.maxCoarsenLevels ?? 1, 0, 10);
|
|
1457
|
+
|
|
1458
|
+
state.referenceDistance = referenceDistance;
|
|
1459
|
+
state.engage = engage;
|
|
1460
|
+
state.deviationFactor = Math.pow(2.0, maxDeviationLevels);
|
|
1461
|
+
state.coarsenFactor = Math.pow(2.0, maxCoarsenLevels);
|
|
1462
|
+
state.active = true;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1248
1465
|
function screenSpaceError(primitive, frameState, tile) {
|
|
1249
1466
|
if (
|
|
1250
1467
|
frameState.mode === SceneMode.SCENE2D ||
|
|
@@ -1263,9 +1480,46 @@ function screenSpaceError(primitive, frameState, tile) {
|
|
|
1263
1480
|
|
|
1264
1481
|
let error = (maxGeometricError * height) / (distance * sseDenominator);
|
|
1265
1482
|
|
|
1483
|
+
const uniformLevel = primitive._uniformLevelState;
|
|
1484
|
+
if (uniformLevel.active) {
|
|
1485
|
+
// Uniform-level mode: evaluate this tile as if it sat at the reference
|
|
1486
|
+
// distance, so every tile refines to the level appropriate for one
|
|
1487
|
+
// representative distance instead of its own. The clamp bounds how far
|
|
1488
|
+
// the selection may drift from natural in either direction (each level
|
|
1489
|
+
// is a factor of two in error): far tiles may be pushed at most
|
|
1490
|
+
// maxDeviationLevels levels finer (bounding tile-count growth toward the
|
|
1491
|
+
// horizon), and near tiles held at most maxCoarsenLevels levels coarser.
|
|
1492
|
+
// Without the near-side clamp, the foreground of a tilted far view lands
|
|
1493
|
+
// 2+ levels coarse, and terrain exaggeration (verticalExaggeration > 1)
|
|
1494
|
+
// amplifies coarse-terrain interpolation error (4x per level) into
|
|
1495
|
+
// visible tearing. engage blends between natural and uniform selection.
|
|
1496
|
+
const uniformError =
|
|
1497
|
+
(maxGeometricError * height) /
|
|
1498
|
+
(uniformLevel.referenceDistance * sseDenominator);
|
|
1499
|
+
const cappedUniformError = CesiumMath.clamp(
|
|
1500
|
+
uniformError,
|
|
1501
|
+
error / uniformLevel.coarsenFactor,
|
|
1502
|
+
error * uniformLevel.deviationFactor,
|
|
1503
|
+
);
|
|
1504
|
+
error += (cappedUniformError - error) * uniformLevel.engage;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1266
1507
|
if (frameState.fog.enabled) {
|
|
1267
|
-
|
|
1268
|
-
|
|
1508
|
+
let fogAmount = CesiumMath.fog(distance, frameState.fog.density);
|
|
1509
|
+
if (uniformLevel.active) {
|
|
1510
|
+
// Blend the fog SSE relief toward the relief at the reference distance
|
|
1511
|
+
// so every tile gets the same effective threshold. Subtracting each
|
|
1512
|
+
// tile's own (larger, distance-dependent) relief instead would satisfy
|
|
1513
|
+
// the SSE for far tiles on fog alone, vetoing the uniform refinement
|
|
1514
|
+
// and reintroducing cross-level boundaries beyond the fog onset
|
|
1515
|
+
// distance. Fog shading itself is unaffected; only LOD selection.
|
|
1516
|
+
const uniformFogAmount = CesiumMath.fog(
|
|
1517
|
+
uniformLevel.referenceDistance,
|
|
1518
|
+
frameState.fog.density,
|
|
1519
|
+
);
|
|
1520
|
+
fogAmount += (uniformFogAmount - fogAmount) * uniformLevel.engage;
|
|
1521
|
+
}
|
|
1522
|
+
error -= fogAmount * frameState.fog.sse;
|
|
1269
1523
|
}
|
|
1270
1524
|
|
|
1271
1525
|
error /= frameState.pixelRatio;
|
|
@@ -26,6 +26,39 @@ uniform float u_dayTextureBrightness[TEXTURE_UNITS];
|
|
|
26
26
|
uniform float u_dayTextureContrast[TEXTURE_UNITS];
|
|
27
27
|
#endif
|
|
28
28
|
|
|
29
|
+
#ifdef APPLY_TONE_MATCH
|
|
30
|
+
uniform vec3 u_dayTextureToneGain[TEXTURE_UNITS];
|
|
31
|
+
uniform vec3 u_dayTextureToneBias[TEXTURE_UNITS];
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
#ifdef APPLY_TONE_MATCH_EDGE
|
|
35
|
+
// Per-texture fade targets at the four geographic edges of the surface tile
|
|
36
|
+
// (index order: 0 = south, 1 = east, 2 = north, 3 = west).
|
|
37
|
+
// u_dayTextureToneEdgeBlend holds one band width per geographic edge as a
|
|
38
|
+
// fraction of the tile extent; only edges with a coarser neighbor get a
|
|
39
|
+
// positive width, so same-level/finer edges never participate in the fade
|
|
40
|
+
// (an edge that faded toward the texture's own correction would reset the
|
|
41
|
+
// fade contributed by another edge near their corner).
|
|
42
|
+
uniform vec3 u_dayTextureToneEdgeGain[TEXTURE_UNITS * 4];
|
|
43
|
+
uniform vec3 u_dayTextureToneEdgeBias[TEXTURE_UNITS * 4];
|
|
44
|
+
uniform float u_dayTextureToneEdgeBlend[TEXTURE_UNITS * 4];
|
|
45
|
+
#endif
|
|
46
|
+
|
|
47
|
+
#ifdef APPLY_TONE_MATCH_CROSS
|
|
48
|
+
// Per-texture ancestor imagery for content cross-fading at edges facing a
|
|
49
|
+
// coarser neighbor: near such an edge the tile blends its full rendered result
|
|
50
|
+
// with the ancestor's rendering (ancestor texture sampled with the ancestor
|
|
51
|
+
// level's correction), making both sides of the boundary identical at the
|
|
52
|
+
// shared edge. u_dayTextureCrossBlend holds one band width per geographic edge
|
|
53
|
+
// (0 = south, 1 = east, 2 = north, 3 = west); an edge only fades when its
|
|
54
|
+
// neighbor's imagery level matches the bound ancestor's level.
|
|
55
|
+
uniform sampler2D u_dayTextureCrossTexture[TEXTURE_UNITS];
|
|
56
|
+
uniform vec4 u_dayTextureCrossTranslationAndScale[TEXTURE_UNITS];
|
|
57
|
+
uniform vec3 u_dayTextureCrossGain[TEXTURE_UNITS];
|
|
58
|
+
uniform vec3 u_dayTextureCrossBias[TEXTURE_UNITS];
|
|
59
|
+
uniform float u_dayTextureCrossBlend[TEXTURE_UNITS * 4];
|
|
60
|
+
#endif
|
|
61
|
+
|
|
29
62
|
#ifdef APPLY_HUE
|
|
30
63
|
uniform float u_dayTextureHue[TEXTURE_UNITS];
|
|
31
64
|
#endif
|
|
@@ -199,6 +232,8 @@ vec4 sampleAndBlend(
|
|
|
199
232
|
float textureHue,
|
|
200
233
|
float textureSaturation,
|
|
201
234
|
float textureOneOverGamma,
|
|
235
|
+
vec3 textureToneGain,
|
|
236
|
+
vec3 textureToneBias,
|
|
202
237
|
float split,
|
|
203
238
|
vec4 colorToAlpha,
|
|
204
239
|
float nightBlend)
|
|
@@ -227,6 +262,13 @@ vec4 sampleAndBlend(
|
|
|
227
262
|
vec3 color = value.rgb;
|
|
228
263
|
float alpha = value.a;
|
|
229
264
|
|
|
265
|
+
#ifdef APPLY_TONE_MATCH
|
|
266
|
+
// Applied directly after sampling so the affine correction, which is fitted
|
|
267
|
+
// in source-image color space, commutes with the identical transforms that
|
|
268
|
+
// follow for both the tile and the imagery it replaces.
|
|
269
|
+
color = color * textureToneGain + textureToneBias;
|
|
270
|
+
#endif
|
|
271
|
+
|
|
230
272
|
#ifdef APPLY_COLOR_TO_ALPHA
|
|
231
273
|
vec3 colorDiff = abs(color.rgb - colorToAlpha.rgb);
|
|
232
274
|
colorDiff.r = czm_maximumComponent(colorDiff);
|
|
@@ -690,3 +732,4 @@ vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat
|
|
|
690
732
|
}
|
|
691
733
|
|
|
692
734
|
#endif // #ifdef SHOW_REFLECTIVE_OCEAN
|
|
735
|
+
|