@cesium/engine 6.2.0 → 7.0.0

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.
Files changed (210) hide show
  1. package/Build/ThirdParty/Workers/z-worker-pako.js +568 -407
  2. package/Build/Workers/{chunk-QRBRVGZC.js → chunk-2HJWSU7B.js} +4 -4
  3. package/Build/Workers/{chunk-ZQRZBHYI.js → chunk-46UD5ABS.js} +4 -4
  4. package/Build/Workers/{chunk-GVL5I7TC.js → chunk-4EBHOMFX.js} +17 -17
  5. package/Build/Workers/{chunk-CDGHUKQ4.js → chunk-5HDYHG3F.js} +13 -13
  6. package/Build/Workers/{chunk-CWJQGBWT.js → chunk-5M3U6ZMA.js} +1 -1
  7. package/Build/Workers/{chunk-Y4OJ4B23.js → chunk-5WQ523AW.js} +5 -5
  8. package/Build/Workers/{chunk-NE4JNU6H.js → chunk-5YLJ77FF.js} +10 -10
  9. package/Build/Workers/{chunk-SV7DDPAC.js → chunk-6HZQPRUS.js} +1 -1
  10. package/Build/Workers/{chunk-434ZTTFX.js → chunk-6VJVYK2V.js} +2 -2
  11. package/Build/Workers/{chunk-LGJUI2CE.js → chunk-72SANQJV.js} +5 -5
  12. package/Build/Workers/{chunk-QTZQZY2C.js → chunk-7XEAYGZK.js} +34 -10
  13. package/Build/Workers/{chunk-Z4JUBRHP.js → chunk-AIPU2VSX.js} +6 -6
  14. package/Build/Workers/{chunk-PZ2WJWUG.js → chunk-AR5DNBJ4.js} +6 -6
  15. package/Build/Workers/{chunk-BUZDZBUH.js → chunk-BZP4T2JJ.js} +10 -10
  16. package/Build/Workers/{chunk-Z2SIPUKB.js → chunk-DTAIXKTO.js} +6 -6
  17. package/Build/Workers/{chunk-HOT2SNXP.js → chunk-F6SE42BK.js} +127 -90
  18. package/Build/Workers/{chunk-TIXXVKUY.js → chunk-FP6GYBFX.js} +10 -10
  19. package/Build/Workers/{chunk-ARPTYYKS.js → chunk-GEJTYLCO.js} +5 -5
  20. package/Build/Workers/{chunk-XUTVA4K5.js → chunk-GV56Q4LU.js} +11 -11
  21. package/Build/Workers/{chunk-HPP4JLNH.js → chunk-IQBYFRVW.js} +7 -7
  22. package/Build/Workers/{chunk-O43GWBSF.js → chunk-IX2JCCNM.js} +1 -1
  23. package/Build/Workers/{chunk-H5DUXHCV.js → chunk-JCNXK6EL.js} +11 -11
  24. package/Build/Workers/{chunk-SQVTYRZY.js → chunk-JJ4VBOQ3.js} +4 -4
  25. package/Build/Workers/{chunk-RIDPF7PO.js → chunk-JXDC723O.js} +2 -2
  26. package/Build/Workers/{chunk-R3HUGXBH.js → chunk-JY5YEZFA.js} +8 -8
  27. package/Build/Workers/{chunk-GF5TNNKP.js → chunk-L2ZN645J.js} +6 -6
  28. package/Build/Workers/{chunk-5GDBZTHX.js → chunk-LZ7JIV3K.js} +17 -17
  29. package/Build/Workers/{chunk-52VSIKEA.js → chunk-LZGHD6NY.js} +15 -15
  30. package/Build/Workers/{chunk-RH4N2ONY.js → chunk-MY3VNFGQ.js} +7 -7
  31. package/Build/Workers/{chunk-MN34FIF5.js → chunk-NKPBIX7F.js} +1 -1
  32. package/Build/Workers/{chunk-AXFRNOVC.js → chunk-NY3K4IM3.js} +12 -12
  33. package/Build/Workers/{chunk-MW3CJYLX.js → chunk-ODW7WYM4.js} +2 -2
  34. package/Build/Workers/{chunk-R4OZKBXH.js → chunk-OVLG3FRS.js} +6 -6
  35. package/Build/Workers/{chunk-TMPVBFJQ.js → chunk-PNBGBETF.js} +10 -10
  36. package/Build/Workers/{chunk-DR5XZ6K5.js → chunk-PTQQUQC3.js} +13 -13
  37. package/Build/Workers/{chunk-3PW6ZBN4.js → chunk-QZAD5O7I.js} +7 -7
  38. package/Build/Workers/{chunk-5SK36PU4.js → chunk-R5X4OQT4.js} +7 -7
  39. package/Build/Workers/{chunk-DMCSY5BU.js → chunk-RAEV7K66.js} +5 -5
  40. package/Build/Workers/{chunk-BP467WX3.js → chunk-RV7ZYPFT.js} +4 -4
  41. package/Build/Workers/{chunk-5HLGKKG3.js → chunk-S4MAZ3SS.js} +2 -2
  42. package/Build/Workers/{chunk-LX6XV4DK.js → chunk-S6SKF6DT.js} +5 -5
  43. package/Build/Workers/{chunk-HUPNRBWW.js → chunk-U2VCRRQW.js} +6 -6
  44. package/Build/Workers/{chunk-SNN7WOC2.js → chunk-UAEW6HKG.js} +13 -13
  45. package/Build/Workers/{chunk-HFKSAB5K.js → chunk-UDO6BFSF.js} +13 -13
  46. package/Build/Workers/{chunk-YBKFS53K.js → chunk-UGK3FCDY.js} +1 -1
  47. package/Build/Workers/{chunk-PIXK6KHB.js → chunk-VK3EJHWI.js} +2 -2
  48. package/Build/Workers/{chunk-5IRLXUTA.js → chunk-VRGFV2UO.js} +7 -7
  49. package/Build/Workers/{chunk-JGG36SQV.js → chunk-WBQCVXR3.js} +4 -4
  50. package/Build/Workers/{chunk-4KP73B43.js → chunk-WZU2YLWG.js} +3 -3
  51. package/Build/Workers/{chunk-LGL4P5KL.js → chunk-XWXM2O2R.js} +6 -6
  52. package/Build/Workers/{chunk-FWGNCYP6.js → chunk-YUCVWAY6.js} +7 -7
  53. package/Build/Workers/{chunk-CSIZ3BGT.js → chunk-ZK5JOS3D.js} +14 -14
  54. package/Build/Workers/{chunk-HPH5HSFE.js → chunk-ZUA2UUNV.js} +2 -2
  55. package/Build/Workers/combineGeometry.js +23 -23
  56. package/Build/Workers/createBoxGeometry.js +17 -17
  57. package/Build/Workers/createBoxOutlineGeometry.js +15 -15
  58. package/Build/Workers/createCircleGeometry.js +25 -25
  59. package/Build/Workers/createCircleOutlineGeometry.js +18 -18
  60. package/Build/Workers/createCoplanarPolygonGeometry.js +32 -32
  61. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +30 -30
  62. package/Build/Workers/createCorridorGeometry.js +28 -29
  63. package/Build/Workers/createCorridorOutlineGeometry.js +27 -28
  64. package/Build/Workers/createCylinderGeometry.js +19 -19
  65. package/Build/Workers/createCylinderOutlineGeometry.js +17 -17
  66. package/Build/Workers/createEllipseGeometry.js +25 -25
  67. package/Build/Workers/createEllipseOutlineGeometry.js +18 -18
  68. package/Build/Workers/createEllipsoidGeometry.js +18 -18
  69. package/Build/Workers/createEllipsoidOutlineGeometry.js +17 -17
  70. package/Build/Workers/createFrustumGeometry.js +17 -17
  71. package/Build/Workers/createFrustumOutlineGeometry.js +17 -17
  72. package/Build/Workers/createGeometry.js +23 -23
  73. package/Build/Workers/createGroundPolylineGeometry.js +21 -21
  74. package/Build/Workers/createPlaneGeometry.js +15 -15
  75. package/Build/Workers/createPlaneOutlineGeometry.js +14 -14
  76. package/Build/Workers/createPolygonGeometry.js +31 -166
  77. package/Build/Workers/createPolygonOutlineGeometry.js +29 -29
  78. package/Build/Workers/createPolylineGeometry.js +24 -24
  79. package/Build/Workers/createPolylineVolumeGeometry.js +31 -33
  80. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +26 -27
  81. package/Build/Workers/createRectangleGeometry.js +26 -26
  82. package/Build/Workers/createRectangleOutlineGeometry.js +19 -19
  83. package/Build/Workers/createSimplePolylineGeometry.js +22 -22
  84. package/Build/Workers/createSphereGeometry.js +18 -18
  85. package/Build/Workers/createSphereOutlineGeometry.js +17 -17
  86. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  87. package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
  88. package/Build/Workers/createVectorTileGeometries.js +23 -23
  89. package/Build/Workers/createVectorTilePoints.js +12 -12
  90. package/Build/Workers/createVectorTilePolygons.js +21 -21
  91. package/Build/Workers/createVectorTilePolylines.js +14 -14
  92. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +21 -21
  93. package/Build/Workers/createVerticesFromHeightmap.js +21 -21
  94. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +18 -18
  95. package/Build/Workers/createWallGeometry.js +23 -23
  96. package/Build/Workers/createWallOutlineGeometry.js +22 -22
  97. package/Build/Workers/decodeDraco.js +11 -11
  98. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  99. package/Build/Workers/decodeI3S.js +9 -9
  100. package/Build/Workers/transcodeKTX2.js +7 -7
  101. package/Build/Workers/transferTypedArrayTest.js +1 -1
  102. package/Build/Workers/upsampleQuantizedTerrainMesh.js +21 -21
  103. package/LICENSE.md +1 -1
  104. package/Source/Assets/approximateTerrainHeights.json +1 -1
  105. package/Source/Core/GregorianDate.js +85 -0
  106. package/Source/Core/HeadingPitchRange.js +2 -2
  107. package/Source/Core/Ion.js +1 -1
  108. package/Source/Core/PolygonGeometry.js +0 -169
  109. package/Source/Core/Resource.js +30 -69
  110. package/Source/Core/Transforms.js +27 -18
  111. package/Source/Core/createWorldBathymetryAsync.js +45 -0
  112. package/Source/DataSources/EllipsoidGeometryUpdater.js +3 -4
  113. package/Source/DataSources/Entity.js +8 -5
  114. package/Source/DataSources/EntityCollection.js +1 -2
  115. package/Source/DataSources/GeometryUpdater.js +1 -2
  116. package/Source/DataSources/GroundGeometryUpdater.js +6 -3
  117. package/Source/DataSources/ModelVisualizer.js +19 -98
  118. package/Source/DataSources/PolygonGeometryUpdater.js +14 -2
  119. package/Source/DataSources/PolylineGeometryUpdater.js +9 -8
  120. package/Source/DataSources/TerrainOffsetProperty.js +15 -23
  121. package/Source/Renderer/AutomaticUniforms.js +121 -1
  122. package/Source/Renderer/UniformState.js +127 -0
  123. package/Source/Scene/ArcGisMapService.js +1 -1
  124. package/Source/Scene/Atmosphere.js +127 -0
  125. package/Source/Scene/Billboard.js +29 -26
  126. package/Source/Scene/BillboardCollection.js +3 -3
  127. package/Source/Scene/Camera.js +1 -1
  128. package/Source/Scene/Cesium3DTile.js +1 -0
  129. package/Source/Scene/Cesium3DTileContent.js +14 -0
  130. package/Source/Scene/Cesium3DTileset.js +326 -45
  131. package/Source/Scene/Cesium3DTilesetTraversal.js +4 -0
  132. package/Source/Scene/Composite3DTileContent.js +42 -0
  133. package/Source/Scene/DynamicAtmosphereLightingType.js +56 -0
  134. package/Source/Scene/Empty3DTileContent.js +4 -0
  135. package/Source/Scene/Fog.js +1 -0
  136. package/Source/Scene/FrameState.js +9 -1
  137. package/Source/Scene/Geometry3DTileContent.js +4 -0
  138. package/Source/Scene/Globe.js +3 -2
  139. package/Source/Scene/GlobeSurfaceTileProvider.js +3 -1
  140. package/Source/Scene/GltfLoader.js +15 -5
  141. package/Source/Scene/HeightReference.js +59 -2
  142. package/Source/Scene/Implicit3DTileContent.js +4 -0
  143. package/Source/Scene/LabelCollection.js +2 -2
  144. package/Source/Scene/Model/AtmospherePipelineStage.js +59 -0
  145. package/Source/Scene/Model/B3dmLoader.js +4 -0
  146. package/Source/Scene/Model/FeatureIdPipelineStage.js +25 -2
  147. package/Source/Scene/Model/I3dmLoader.js +4 -0
  148. package/Source/Scene/Model/InstancingPipelineStage.js +24 -6
  149. package/Source/Scene/Model/MetadataPipelineStage.js +31 -3
  150. package/Source/Scene/Model/Model.js +82 -32
  151. package/Source/Scene/Model/Model3DTileContent.js +31 -0
  152. package/Source/Scene/Model/ModelAnimationChannel.js +16 -15
  153. package/Source/Scene/Model/ModelSceneGraph.js +6 -0
  154. package/Source/Scene/Model/pickModel.js +408 -0
  155. package/Source/Scene/Multiple3DTileContent.js +42 -0
  156. package/Source/Scene/QuadtreePrimitive.js +1 -1
  157. package/Source/Scene/Scene.js +198 -16
  158. package/Source/Scene/ScreenSpaceCameraController.js +2 -6
  159. package/Source/Scene/SkyAtmosphere.js +5 -6
  160. package/Source/Scene/Terrain.js +49 -0
  161. package/Source/Scene/TileBoundingS2Cell.js +2 -2
  162. package/Source/Scene/Tileset3DTileContent.js +4 -0
  163. package/Source/Scene/Vector3DTileContent.js +4 -0
  164. package/Source/Shaders/AtmosphereCommon.glsl +3 -11
  165. package/Source/Shaders/AtmosphereCommon.js +3 -11
  166. package/Source/Shaders/Builtin/CzmBuiltins.js +12 -0
  167. package/Source/Shaders/Builtin/Functions/applyHSBShift.glsl +32 -0
  168. package/Source/Shaders/Builtin/Functions/applyHSBShift.js +34 -0
  169. package/Source/Shaders/Builtin/Functions/approximateTanh.glsl +10 -0
  170. package/Source/Shaders/Builtin/Functions/approximateTanh.js +12 -0
  171. package/Source/Shaders/Builtin/Functions/computeAtmosphereColor.glsl +44 -0
  172. package/Source/Shaders/Builtin/Functions/computeAtmosphereColor.js +46 -0
  173. package/Source/Shaders/Builtin/Functions/computeGroundAtmosphereScattering.glsl +30 -0
  174. package/Source/Shaders/Builtin/Functions/computeGroundAtmosphereScattering.js +32 -0
  175. package/Source/Shaders/Builtin/Functions/computeScattering.glsl +150 -0
  176. package/Source/Shaders/Builtin/Functions/computeScattering.js +152 -0
  177. package/Source/Shaders/Builtin/Functions/getDynamicAtmosphereLightDirection.glsl +22 -0
  178. package/Source/Shaders/Builtin/Functions/getDynamicAtmosphereLightDirection.js +24 -0
  179. package/Source/Shaders/Builtin/Functions/translateRelativeToEye.glsl +5 -0
  180. package/Source/Shaders/Builtin/Functions/translateRelativeToEye.js +5 -0
  181. package/Source/Shaders/GlobeFS.glsl +16 -25
  182. package/Source/Shaders/GlobeFS.js +16 -25
  183. package/Source/Shaders/GlobeVS.glsl +1 -1
  184. package/Source/Shaders/GlobeVS.js +1 -1
  185. package/Source/Shaders/Model/AtmosphereStageFS.glsl +111 -0
  186. package/Source/Shaders/Model/AtmosphereStageFS.js +113 -0
  187. package/Source/Shaders/Model/AtmosphereStageVS.glsl +12 -0
  188. package/Source/Shaders/Model/AtmosphereStageVS.js +14 -0
  189. package/Source/Shaders/Model/GeometryStageFS.glsl +1 -1
  190. package/Source/Shaders/Model/GeometryStageFS.js +1 -1
  191. package/Source/Shaders/Model/GeometryStageVS.glsl +4 -4
  192. package/Source/Shaders/Model/GeometryStageVS.js +4 -4
  193. package/Source/Shaders/Model/ModelColorStageFS.glsl +1 -1
  194. package/Source/Shaders/Model/ModelColorStageFS.js +2 -1
  195. package/Source/Shaders/Model/ModelFS.glsl +4 -0
  196. package/Source/Shaders/Model/ModelFS.js +4 -0
  197. package/Source/Shaders/Model/ModelVS.glsl +9 -4
  198. package/Source/Shaders/Model/ModelVS.js +9 -4
  199. package/Source/Shaders/SkyAtmosphereCommon.glsl +3 -13
  200. package/Source/Shaders/SkyAtmosphereCommon.js +3 -13
  201. package/Source/Shaders/SkyAtmosphereFS.glsl +5 -10
  202. package/Source/Shaders/SkyAtmosphereFS.js +5 -10
  203. package/Source/Shaders/SkyAtmosphereVS.glsl +3 -2
  204. package/Source/Shaders/SkyAtmosphereVS.js +3 -2
  205. package/Source/ThirdParty/Workers/z-worker-pako.js +1 -1
  206. package/Source/ThirdParty/draco_decoder.wasm +0 -0
  207. package/index.d.ts +283 -65
  208. package/index.js +260 -247
  209. package/package.json +3 -3
  210. package/Build/Workers/chunk-ATB2I7OS.js +0 -55
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Atmosphere lighting effects (sky atmosphere, ground atmosphere, fog) can be
3
+ * further modified with dynamic lighting from the sun or other light source
4
+ * that changes over time. This enum determines which light source to use.
5
+ *
6
+ * @enum {number}
7
+ */
8
+ const DynamicAtmosphereLightingType = {
9
+ /**
10
+ * Do not use dynamic atmosphere lighting. Atmosphere lighting effects will
11
+ * be lit from directly above rather than using the scene's light source.
12
+ *
13
+ * @type {number}
14
+ * @constant
15
+ */
16
+ NONE: 0,
17
+ /**
18
+ * Use the scene's current light source for dynamic atmosphere lighting.
19
+ *
20
+ * @type {number}
21
+ * @constant
22
+ */
23
+ SCENE_LIGHT: 1,
24
+ /**
25
+ * Force the dynamic atmosphere lighting to always use the sunlight direction,
26
+ * even if the scene uses a different light source.
27
+ *
28
+ * @type {number}
29
+ * @constant
30
+ */
31
+ SUNLIGHT: 2,
32
+ };
33
+
34
+ /**
35
+ * Get the lighting enum from the older globe flags
36
+ *
37
+ * @param {Globe} globe The globe
38
+ * @return {DynamicAtmosphereLightingType} The corresponding enum value
39
+ *
40
+ * @private
41
+ */
42
+ DynamicAtmosphereLightingType.fromGlobeFlags = function (globe) {
43
+ const lightingOn = globe.enableLighting && globe.dynamicAtmosphereLighting;
44
+ if (!lightingOn) {
45
+ return DynamicAtmosphereLightingType.NONE;
46
+ }
47
+
48
+ // Force sunlight
49
+ if (globe.dynamicAtmosphereLightingFromSun) {
50
+ return DynamicAtmosphereLightingType.SUNLIGHT;
51
+ }
52
+
53
+ return DynamicAtmosphereLightingType.SCENE_LIGHT;
54
+ };
55
+
56
+ export default Object.freeze(DynamicAtmosphereLightingType);
@@ -150,6 +150,10 @@ Empty3DTileContent.prototype.applyStyle = function (style) {};
150
150
 
151
151
  Empty3DTileContent.prototype.update = function (tileset, frameState) {};
152
152
 
153
+ Empty3DTileContent.prototype.pick = function (ray, frameState, result) {
154
+ return undefined;
155
+ };
156
+
153
157
  Empty3DTileContent.prototype.isDestroyed = function () {
154
158
  return false;
155
159
  };
@@ -173,6 +173,7 @@ Fog.prototype.update = function (frameState) {
173
173
  frameState.mode !== SceneMode.SCENE3D
174
174
  ) {
175
175
  frameState.fog.enabled = false;
176
+ frameState.fog.density = 0;
176
177
  return;
177
178
  }
178
179
 
@@ -254,7 +254,8 @@ function FrameState(context, creditDisplay, jobScheduler) {
254
254
  /**
255
255
  * @typedef FrameState.Fog
256
256
  * @type {object}
257
- * @property {boolean} enabled <code>true</code> if fog is enabled, <code>false</code> otherwise.
257
+ * @property {boolean} enabled <code>true</code> if fog is enabled, <code>false</code> otherwise. This affects both fog culling and rendering.
258
+ * @property {boolean} renderable <code>true</code> if fog should be rendered, <code>false</code> if not. This flag should be checked in combination with fog.enabled.
258
259
  * @property {number} density A positive number used to mix the color and fog color based on camera distance.
259
260
  * @property {number} sse A scalar used to modify the screen space error of geometry partially in fog.
260
261
  * @property {number} minimumBrightness The minimum brightness of terrain with fog applied.
@@ -269,11 +270,18 @@ function FrameState(context, creditDisplay, jobScheduler) {
269
270
  * @default false
270
271
  */
271
272
  enabled: false,
273
+ renderable: false,
272
274
  density: undefined,
273
275
  sse: undefined,
274
276
  minimumBrightness: undefined,
275
277
  };
276
278
 
279
+ /**
280
+ * The current Atmosphere
281
+ * @type {Atmosphere}
282
+ */
283
+ this.atmosphere = undefined;
284
+
277
285
  /**
278
286
  * A scalar used to vertically exaggerate the scene
279
287
  * @type {number}
@@ -525,6 +525,10 @@ Geometry3DTileContent.prototype.update = function (tileset, frameState) {
525
525
  }
526
526
  };
527
527
 
528
+ Geometry3DTileContent.prototype.pick = function (ray, frameState, result) {
529
+ return undefined;
530
+ };
531
+
528
532
  Geometry3DTileContent.prototype.isDestroyed = function () {
529
533
  return false;
530
534
  };
@@ -691,8 +691,8 @@ function makeShadersDirty(globe) {
691
691
 
692
692
  const requireNormals =
693
693
  defined(globe._material) &&
694
- (globe._material.shaderSource.match(/slope/) ||
695
- globe._material.shaderSource.match("normalEC"));
694
+ (defined(globe._material.shaderSource.match(/slope/)) ||
695
+ defined(globe._material.shaderSource.match("normalEC")));
696
696
 
697
697
  const fragmentSources = [AtmosphereCommon, GroundAtmosphere];
698
698
  if (
@@ -1106,6 +1106,7 @@ Globe.prototype.beginFrame = function (frameState) {
1106
1106
  tileProvider.undergroundColor = this._undergroundColor;
1107
1107
  tileProvider.undergroundColorAlphaByDistance = this._undergroundColorAlphaByDistance;
1108
1108
  tileProvider.lambertDiffuseMultiplier = this.lambertDiffuseMultiplier;
1109
+
1109
1110
  surface.beginFrame(frameState);
1110
1111
  }
1111
1112
  };
@@ -2502,7 +2502,9 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
2502
2502
  uniformMapProperties.localizedTranslucencyRectangle
2503
2503
  );
2504
2504
 
2505
- // For performance, use fog in the shader only when the tile is in fog.
2505
+ // For performance, render fog only when fog is enabled and the effect of
2506
+ // fog would be non-negligible. This prevents the shader from running when
2507
+ // the camera is in space, for example.
2506
2508
  const applyFog =
2507
2509
  enableFog &&
2508
2510
  CesiumMath.fog(tile._distance, frameState.fog.density) >
@@ -179,6 +179,7 @@ const GltfLoaderState = {
179
179
  * @param {Axis} [options.forwardAxis=Axis.Z] The forward-axis of the glTF model.
180
180
  * @param {boolean} [options.loadAttributesAsTypedArray=false] Load all attributes and indices as typed arrays instead of GPU buffers. If the attributes are interleaved in the glTF they will be de-interleaved in the typed array.
181
181
  * @param {boolean} [options.loadAttributesFor2D=false] If <code>true</code>, load the positions buffer and any instanced attribute buffers as typed arrays for accurately projecting models to 2D.
182
+ * @param {boolean} [options.enablePick=false] If <code>true</code>, load the positions buffer, any instanced attribute buffers, and index buffer as typed arrays for CPU-enabled picking in WebGL1.
182
183
  * @param {boolean} [options.loadIndicesForWireframe=false] If <code>true</code>, load the index buffer as both a buffer and typed array. The latter is useful for creating wireframe indices in WebGL1.
183
184
  * @param {boolean} [options.loadPrimitiveOutline=true] If <code>true</code>, load outlines from the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. This can be set false to avoid post-processing geometry at load time.
184
185
  * @param {boolean} [options.loadForClassification=false] If <code>true</code> and if the model has feature IDs, load the feature IDs and indices as typed arrays. This is useful for batching features for classification.
@@ -203,6 +204,7 @@ function GltfLoader(options) {
203
204
  false
204
205
  );
205
206
  const loadAttributesFor2D = defaultValue(options.loadAttributesFor2D, false);
207
+ const enablePick = defaultValue(options.enablePick);
206
208
  const loadIndicesForWireframe = defaultValue(
207
209
  options.loadIndicesForWireframe,
208
210
  false
@@ -234,6 +236,7 @@ function GltfLoader(options) {
234
236
  this._forwardAxis = forwardAxis;
235
237
  this._loadAttributesAsTypedArray = loadAttributesAsTypedArray;
236
238
  this._loadAttributesFor2D = loadAttributesFor2D;
239
+ this._enablePick = enablePick;
237
240
  this._loadIndicesForWireframe = loadIndicesForWireframe;
238
241
  this._loadPrimitiveOutline = loadPrimitiveOutline;
239
242
  this._loadForClassification = loadForClassification;
@@ -1241,6 +1244,8 @@ function loadVertexAttribute(
1241
1244
  !hasInstances &&
1242
1245
  loader._loadAttributesFor2D &&
1243
1246
  !frameState.scene3DOnly;
1247
+ const loadTypedArrayForPicking =
1248
+ isPositionAttribute && loader._enablePick && !frameState.context.webgl2;
1244
1249
 
1245
1250
  const loadTypedArrayForClassification =
1246
1251
  loader._loadForClassification && isFeatureIdAttribute;
@@ -1252,6 +1257,7 @@ function loadVertexAttribute(
1252
1257
  const outputTypedArray =
1253
1258
  outputTypedArrayOnly ||
1254
1259
  loadTypedArrayFor2D ||
1260
+ loadTypedArrayForPicking ||
1255
1261
  loadTypedArrayForClassification;
1256
1262
 
1257
1263
  // Determine what to load right now:
@@ -1319,6 +1325,8 @@ function loadInstancedAttribute(
1319
1325
  loader._loadAttributesAsTypedArray ||
1320
1326
  (hasRotation && isTransformAttribute) ||
1321
1327
  !frameState.context.instancedArrays;
1328
+ const loadTypedArrayForPicking =
1329
+ loader._enablePick && !frameState.context.webgl2;
1322
1330
 
1323
1331
  const loadBuffer = !loadAsTypedArrayOnly;
1324
1332
 
@@ -1328,7 +1336,8 @@ function loadInstancedAttribute(
1328
1336
  // - the model will be projected to 2D.
1329
1337
  const loadFor2D = loader._loadAttributesFor2D && !frameState.scene3DOnly;
1330
1338
  const loadTranslationAsTypedArray =
1331
- isTranslationAttribute && (!hasTranslationMinMax || loadFor2D);
1339
+ isTranslationAttribute &&
1340
+ (!hasTranslationMinMax || loadFor2D || loadTypedArrayForPicking);
1332
1341
 
1333
1342
  const loadTypedArray = loadAsTypedArrayOnly || loadTranslationAsTypedArray;
1334
1343
 
@@ -1365,9 +1374,10 @@ function loadIndices(
1365
1374
  indices.count = accessor.count;
1366
1375
 
1367
1376
  const loadAttributesAsTypedArray = loader._loadAttributesAsTypedArray;
1368
- // Load the index buffer as a typed array to generate wireframes in WebGL1.
1369
- const loadForWireframe =
1370
- loader._loadIndicesForWireframe && !frameState.context.webgl2;
1377
+ // Load the index buffer as a typed array to generate wireframes or pick in WebGL1.
1378
+ const loadForCpuOperations =
1379
+ (loader._loadIndicesForWireframe || loader._enablePick) &&
1380
+ !frameState.context.webgl2;
1371
1381
 
1372
1382
  // Load the index buffer as a typed array to batch features together for classification.
1373
1383
  const loadForClassification = loader._loadForClassification && hasFeatureIds;
@@ -1377,7 +1387,7 @@ function loadIndices(
1377
1387
  const outputTypedArrayOnly = loadAttributesAsTypedArray;
1378
1388
  const outputBuffer = !outputTypedArrayOnly;
1379
1389
  const outputTypedArray =
1380
- loadAttributesAsTypedArray || loadForWireframe || loadForClassification;
1390
+ loadAttributesAsTypedArray || loadForCpuOperations || loadForClassification;
1381
1391
 
1382
1392
  // Determine what to load right now:
1383
1393
  //
@@ -12,17 +12,74 @@ const HeightReference = {
12
12
  NONE: 0,
13
13
 
14
14
  /**
15
- * The position is clamped to the terrain.
15
+ * The position is clamped to the terrain and 3D Tiles.
16
16
  * @type {number}
17
17
  * @constant
18
18
  */
19
19
  CLAMP_TO_GROUND: 1,
20
20
 
21
21
  /**
22
- * The position height is the height above the terrain.
22
+ * The position height is the height above the terrain and 3D Tiles.
23
23
  * @type {number}
24
24
  * @constant
25
25
  */
26
26
  RELATIVE_TO_GROUND: 2,
27
+
28
+ /**
29
+ * The position is clamped to terain.
30
+ * @type {number}
31
+ * @constant
32
+ */
33
+ CLAMP_TO_TERRAIN: 3,
34
+
35
+ /**
36
+ * The position height is the height above terrain.
37
+ * @type {number}
38
+ * @constant
39
+ */
40
+ RELATIVE_TO_TERRAIN: 4,
41
+
42
+ /**
43
+ * The position is clamped to 3D Tiles.
44
+ * @type {number}
45
+ * @constant
46
+ */
47
+ CLAMP_TO_3D_TILE: 5,
48
+
49
+ /**
50
+ * The position height is the height above 3D Tiles.
51
+ * @type {number}
52
+ * @constant
53
+ */
54
+ RELATIVE_TO_3D_TILE: 6,
27
55
  };
56
+
28
57
  export default Object.freeze(HeightReference);
58
+
59
+ /**
60
+ * Returns true if the height should be clamped to the surface
61
+ * @param {HeightReference} heightReference
62
+ * @returns true if the height should be clamped to the surface
63
+ * @private
64
+ */
65
+ export function isHeightReferenceClamp(heightReference) {
66
+ return (
67
+ heightReference === HeightReference.CLAMP_TO_GROUND ||
68
+ heightReference === HeightReference.CLAMP_TO_3D_TILE ||
69
+ heightReference === HeightReference.CLAMP_TO_TERRAIN
70
+ );
71
+ }
72
+
73
+ /**
74
+ * Returns true if the height should be offset relative to the surface
75
+ * @param {HeightReference} heightReference
76
+ * @returns true if the height should be offset relative to the surface
77
+ * @private
78
+ */
79
+ export function isHeightReferenceRelative(heightReference) {
80
+ return (
81
+ heightReference === HeightReference.RELATIVE_TO_GROUND ||
82
+ heightReference === HeightReference.RELATIVE_TO_3D_TILE ||
83
+ heightReference === HeightReference.RELATIVE_TO_TERRAIN
84
+ );
85
+ }
@@ -1177,6 +1177,10 @@ Implicit3DTileContent.prototype.applyStyle = function (style) {};
1177
1177
 
1178
1178
  Implicit3DTileContent.prototype.update = function (tileset, frameState) {};
1179
1179
 
1180
+ Implicit3DTileContent.prototype.pick = function (ray, frameState, result) {
1181
+ return undefined;
1182
+ };
1183
+
1180
1184
  Implicit3DTileContent.prototype.isDestroyed = function () {
1181
1185
  return false;
1182
1186
  };
@@ -10,7 +10,7 @@ import writeTextToCanvas from "../Core/writeTextToCanvas.js";
10
10
  import bitmapSDF from "bitmap-sdf";
11
11
  import BillboardCollection from "./BillboardCollection.js";
12
12
  import BlendOption from "./BlendOption.js";
13
- import HeightReference from "./HeightReference.js";
13
+ import { isHeightReferenceClamp } from "./HeightReference.js";
14
14
  import HorizontalOrigin from "./HorizontalOrigin.js";
15
15
  import Label from "./Label.js";
16
16
  import LabelStyle from "./LabelStyle.js";
@@ -510,7 +510,7 @@ function repositionAllGlyphs(label) {
510
510
  );
511
511
  }
512
512
 
513
- if (label.heightReference === HeightReference.CLAMP_TO_GROUND) {
513
+ if (isHeightReferenceClamp(label.heightReference)) {
514
514
  for (glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {
515
515
  glyph = glyphs[glyphIndex];
516
516
  const billboard = glyph.billboard;
@@ -0,0 +1,59 @@
1
+ import Cartesian3 from "../../Core/Cartesian3.js";
2
+ import CesiumMath from "../../Core/Math.js";
3
+ import ShaderDestination from "../../Renderer/ShaderDestination.js";
4
+ import AtmosphereStageFS from "../../Shaders/Model/AtmosphereStageFS.js";
5
+ import AtmosphereStageVS from "../../Shaders/Model/AtmosphereStageVS.js";
6
+
7
+ /**
8
+ * The atmosphere pipeline stage applies all earth atmosphere effects that apply
9
+ * to models, including fog.
10
+ *
11
+ * @namespace AtmospherePipelineStage
12
+ *
13
+ * @private
14
+ */
15
+ const AtmospherePipelineStage = {
16
+ name: "AtmospherePipelineStage", // Helps with debugging
17
+ };
18
+
19
+ AtmospherePipelineStage.process = function (
20
+ renderResources,
21
+ model,
22
+ frameState
23
+ ) {
24
+ const shaderBuilder = renderResources.shaderBuilder;
25
+
26
+ shaderBuilder.addDefine("HAS_ATMOSPHERE", undefined, ShaderDestination.BOTH);
27
+ shaderBuilder.addDefine(
28
+ "COMPUTE_POSITION_WC_ATMOSPHERE",
29
+ undefined,
30
+ ShaderDestination.BOTH
31
+ );
32
+
33
+ shaderBuilder.addVarying("vec3", "v_atmosphereRayleighColor");
34
+ shaderBuilder.addVarying("vec3", "v_atmosphereMieColor");
35
+ shaderBuilder.addVarying("float", "v_atmosphereOpacity");
36
+
37
+ shaderBuilder.addVertexLines([AtmosphereStageVS]);
38
+ shaderBuilder.addFragmentLines([AtmosphereStageFS]);
39
+
40
+ // Add a uniform so fog is only calculated when the efcfect would
41
+ // be non-negligible For example when the camera is in space, fog density decreases
42
+ // to 0 so fog shouldn't be rendered. Since this state may change rapidly if
43
+ // the camera is moving, this is implemented as a uniform, not a define.
44
+ shaderBuilder.addUniform("bool", "u_isInFog", ShaderDestination.FRAGMENT);
45
+ renderResources.uniformMap.u_isInFog = function () {
46
+ // We only need a rough measure of distance to the model, so measure
47
+ // from the camera to the bounding sphere center.
48
+ const distance = Cartesian3.distance(
49
+ frameState.camera.positionWC,
50
+ model.boundingSphere.center
51
+ );
52
+
53
+ return (
54
+ CesiumMath.fog(distance, frameState.fog.density) > CesiumMath.EPSILON3
55
+ );
56
+ };
57
+ };
58
+
59
+ export default AtmospherePipelineStage;
@@ -50,6 +50,7 @@ const FeatureIdAttribute = ModelComponents.FeatureIdAttribute;
50
50
  * @param {Axis} [options.forwardAxis=Axis.X] The forward-axis of the glTF model.
51
51
  * @param {boolean} [options.loadAttributesAsTypedArray=false] If <code>true</code>, load all attributes as typed arrays instead of GPU buffers. If the attributes are interleaved in the glTF they will be de-interleaved in the typed array.
52
52
  * @param {boolean} [options.loadAttributesFor2D=false] If <code>true</code>, load the positions buffer and any instanced attribute buffers as typed arrays for accurately projecting models to 2D.
53
+ * @param {boolean} [options.enablePick=false] If <code>true</code>, load the positions buffer, any instanced attribute buffers, and index buffer as typed arrays for CPU-enabled picking in WebGL1.
53
54
  * @param {boolean} [options.loadIndicesForWireframe=false] If <code>true</code>, load the index buffer as a typed array. This is useful for creating wireframe indices in WebGL1.
54
55
  * @param {boolean} [options.loadPrimitiveOutline=true] If <code>true</code>, load outlines from the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. This can be set false to avoid post-processing geometry at load time.
55
56
  * @param {boolean} [options.loadForClassification=false] If <code>true</code> and if the model has feature IDs, load the feature IDs and indices as typed arrays. This is useful for batching features for classification.
@@ -74,6 +75,7 @@ function B3dmLoader(options) {
74
75
  false
75
76
  );
76
77
  const loadAttributesFor2D = defaultValue(options.loadAttributesFor2D, false);
78
+ const enablePick = defaultValue(options.enablePick, false);
77
79
  const loadIndicesForWireframe = defaultValue(
78
80
  options.loadIndicesForWireframe,
79
81
  false
@@ -102,6 +104,7 @@ function B3dmLoader(options) {
102
104
  this._forwardAxis = forwardAxis;
103
105
  this._loadAttributesAsTypedArray = loadAttributesAsTypedArray;
104
106
  this._loadAttributesFor2D = loadAttributesFor2D;
107
+ this._enablePick = enablePick;
105
108
  this._loadIndicesForWireframe = loadIndicesForWireframe;
106
109
  this._loadPrimitiveOutline = loadPrimitiveOutline;
107
110
  this._loadForClassification = loadForClassification;
@@ -223,6 +226,7 @@ B3dmLoader.prototype.load = function () {
223
226
  incrementallyLoadTextures: this._incrementallyLoadTextures,
224
227
  loadAttributesAsTypedArray: this._loadAttributesAsTypedArray,
225
228
  loadAttributesFor2D: this._loadAttributesFor2D,
229
+ enablePick: this._enablePick,
226
230
  loadIndicesForWireframe: this._loadIndicesForWireframe,
227
231
  loadPrimitiveOutline: this._loadPrimitiveOutline,
228
232
  loadForClassification: this._loadForClassification,
@@ -9,6 +9,7 @@ import FeatureIdStageVS from "../../Shaders/Model/FeatureIdStageVS.js";
9
9
  import ModelComponents from "../ModelComponents.js";
10
10
  import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
11
11
  import ModelUtility from "./ModelUtility.js";
12
+ import Matrix3 from "../../Core/Matrix3.js";
12
13
 
13
14
  /**
14
15
  * The feature ID pipeline stage is responsible for processing feature IDs
@@ -387,10 +388,32 @@ function processTexture(
387
388
  ShaderDestination.FRAGMENT
388
389
  );
389
390
 
391
+ // Get a GLSL expression for the texture coordinates
392
+ const texCoord = textureReader.texCoord;
393
+ const texCoordVariable = `v_texCoord_${texCoord}`;
394
+ let texCoordVariableExpression = texCoordVariable;
395
+
396
+ // Check if the texture defines a `transform` from a `KHR_texture_transform`
397
+ const transform = textureReader.transform;
398
+ if (defined(transform) && !Matrix3.equals(transform, Matrix3.IDENTITY)) {
399
+ // Add a uniform for the transformation matrix
400
+ const transformUniformName = `${uniformName}Transform`;
401
+ shaderBuilder.addUniform(
402
+ "mat3",
403
+ transformUniformName,
404
+ ShaderDestination.FRAGMENT
405
+ );
406
+ uniformMap[transformUniformName] = function () {
407
+ return transform;
408
+ };
409
+ // Update the expression for the texture coordinates
410
+ // with one that transforms the texture coordinates
411
+ // with the transform matrix first
412
+ texCoordVariableExpression = `vec2(${transformUniformName} * vec3(${texCoordVariable}, 1.0))`;
413
+ }
390
414
  // Read one or more channels from the texture
391
415
  // example: texture(u_featureIdTexture_0, v_texCoord_1).rg
392
- const texCoord = `v_texCoord_${textureReader.texCoord}`;
393
- const textureRead = `texture(${uniformName}, ${texCoord}).${channels}`;
416
+ const textureRead = `texture(${uniformName}, ${texCoordVariableExpression}).${channels}`;
394
417
 
395
418
  // Finally, assign to the struct field. Example:
396
419
  // featureIds.featureId_0 = unpacked;
@@ -64,6 +64,7 @@ const Instances = ModelComponents.Instances;
64
64
  * @param {Axis} [options.upAxis=Axis.Y] The up-axis of the glTF model.
65
65
  * @param {Axis} [options.forwardAxis=Axis.X] The forward-axis of the glTF model.
66
66
  * @param {boolean} [options.loadAttributesAsTypedArray=false] Load all attributes as typed arrays instead of GPU buffers. If the attributes are interleaved in the glTF they will be de-interleaved in the typed array.
67
+ * @param {boolean} [options.enablePick=false] If <code>true</code>, load the positions buffer, any instanced attribute buffers, and index buffer as typed arrays for CPU-enabled picking in WebGL1.
67
68
  * @param {boolean} [options.loadIndicesForWireframe=false] Load the index buffer as a typed array so wireframe indices can be created for WebGL1.
68
69
  * @param {boolean} [options.loadPrimitiveOutline=true] If true, load outlines from the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. This can be set false to avoid post-processing geometry at load time.
69
70
  */
@@ -91,6 +92,7 @@ function I3dmLoader(options) {
91
92
  false
92
93
  );
93
94
  const loadPrimitiveOutline = defaultValue(options.loadPrimitiveOutline, true);
95
+ const enablePick = defaultValue(options.enablePick, false);
94
96
 
95
97
  //>>includeStart('debug', pragmas.debug);
96
98
  Check.typeOf.object("options.i3dmResource", i3dmResource);
@@ -111,6 +113,7 @@ function I3dmLoader(options) {
111
113
  this._loadAttributesAsTypedArray = loadAttributesAsTypedArray;
112
114
  this._loadIndicesForWireframe = loadIndicesForWireframe;
113
115
  this._loadPrimitiveOutline = loadPrimitiveOutline;
116
+ this._enablePick = enablePick;
114
117
 
115
118
  this._state = I3dmLoaderState.NOT_LOADED;
116
119
  this._promise = undefined;
@@ -240,6 +243,7 @@ I3dmLoader.prototype.load = function () {
240
243
  releaseGltfJson: this._releaseGltfJson,
241
244
  incrementallyLoadTextures: this._incrementallyLoadTextures,
242
245
  loadAttributesAsTypedArray: this._loadAttributesAsTypedArray,
246
+ enablePick: this._enablePick,
243
247
  loadIndicesForWireframe: this._loadIndicesForWireframe,
244
248
  loadPrimitiveOutline: this._loadPrimitiveOutline,
245
249
  };
@@ -73,6 +73,7 @@ InstancingPipelineStage.process = function (renderResources, node, frameState) {
73
73
  frameState.mode !== SceneMode.SCENE3D &&
74
74
  !frameState.scene3DOnly &&
75
75
  model._projectTo2D;
76
+ const keepTypedArray = model._enablePick && !frameState.context.webgl2;
76
77
 
77
78
  const instancingVertexAttributes = [];
78
79
 
@@ -81,7 +82,8 @@ InstancingPipelineStage.process = function (renderResources, node, frameState) {
81
82
  frameState,
82
83
  instances,
83
84
  instancingVertexAttributes,
84
- use2D
85
+ use2D,
86
+ keepTypedArray
85
87
  );
86
88
 
87
89
  processFeatureIdAttributes(
@@ -697,7 +699,8 @@ function processTransformAttributes(
697
699
  frameState,
698
700
  instances,
699
701
  instancingVertexAttributes,
700
- use2D
702
+ use2D,
703
+ keepTypedArray
701
704
  ) {
702
705
  const rotationAttribute = ModelUtility.getAttributeBySemantic(
703
706
  instances,
@@ -711,7 +714,8 @@ function processTransformAttributes(
711
714
  instances,
712
715
  instancingVertexAttributes,
713
716
  frameState,
714
- use2D
717
+ use2D,
718
+ keepTypedArray
715
719
  );
716
720
  } else {
717
721
  processTransformVec3Attributes(
@@ -729,7 +733,8 @@ function processTransformMatrixAttributes(
729
733
  instances,
730
734
  instancingVertexAttributes,
731
735
  frameState,
732
- use2D
736
+ use2D,
737
+ keepTypedArray
733
738
  ) {
734
739
  const shaderBuilder = renderResources.shaderBuilder;
735
740
  const count = instances.attributes[0].count;
@@ -755,6 +760,10 @@ function processTransformMatrixAttributes(
755
760
  buffer = createVertexBuffer(transformsTypedArray, frameState);
756
761
  model._modelResources.push(buffer);
757
762
 
763
+ if (keepTypedArray) {
764
+ runtimeNode.transformsTypedArray = transformsTypedArray;
765
+ }
766
+
758
767
  runtimeNode.instancingTransformsBuffer = buffer;
759
768
  }
760
769
 
@@ -812,7 +821,8 @@ function processTransformVec3Attributes(
812
821
  instances,
813
822
  instancingVertexAttributes,
814
823
  frameState,
815
- use2D
824
+ use2D,
825
+ keepTypedArray
816
826
  ) {
817
827
  const shaderBuilder = renderResources.shaderBuilder;
818
828
  const runtimeNode = renderResources.runtimeNode;
@@ -872,7 +882,7 @@ function processTransformVec3Attributes(
872
882
  attributeString
873
883
  );
874
884
 
875
- if (!use2D) {
885
+ if (!use2D && !keepTypedArray) {
876
886
  return;
877
887
  }
878
888
 
@@ -898,6 +908,10 @@ function processTransformVec3Attributes(
898
908
  );
899
909
  const projectedTypedArray = translationsToTypedArray(projectedTranslations);
900
910
 
911
+ if (keepTypedArray) {
912
+ runtimeNode.transformsTypedArray = projectedTypedArray;
913
+ }
914
+
901
915
  // This memory is counted during the statistics stage at the end
902
916
  // of the pipeline.
903
917
  buffer2D = createVertexBuffer(projectedTypedArray, frameState);
@@ -906,6 +920,10 @@ function processTransformVec3Attributes(
906
920
  runtimeNode.instancingTranslationBuffer2D = buffer2D;
907
921
  }
908
922
 
923
+ if (!use2D) {
924
+ return;
925
+ }
926
+
909
927
  const byteOffset = 0;
910
928
  const byteStride = undefined;
911
929
 
@@ -1,3 +1,4 @@
1
+ import Matrix3 from "../../Core/Matrix3.js";
1
2
  import defined from "../../Core/defined.js";
2
3
  import ShaderDestination from "../../Renderer/ShaderDestination.js";
3
4
  import MetadataStageFS from "../../Shaders/Model/MetadataStageFS.js";
@@ -430,7 +431,13 @@ function addPropertyTexturePropertyMetadata(renderResources, propertyInfo) {
430
431
  const { shaderBuilder, uniformMap } = renderResources;
431
432
  const { metadataVariable, glslType, property } = propertyInfo;
432
433
 
433
- const { texCoord, channels, index, texture } = property.textureReader;
434
+ const {
435
+ texCoord,
436
+ channels,
437
+ index,
438
+ texture,
439
+ transform,
440
+ } = property.textureReader;
434
441
  const textureUniformName = `u_propertyTexture_${index}`;
435
442
 
436
443
  // Property texture properties may share the same physical texture, so only
@@ -450,9 +457,30 @@ function addPropertyTexturePropertyMetadata(renderResources, propertyInfo) {
450
457
  metadataVariable
451
458
  );
452
459
 
453
- // Get a GLSL expression for the value of the property
460
+ // Get a GLSL expression for the texture coordinates of the property.
461
+ // By default, this will be taken directly from the attributes.
454
462
  const texCoordVariable = `attributes.texCoord_${texCoord}`;
455
- const valueExpression = `texture(${textureUniformName}, ${texCoordVariable}).${channels}`;
463
+ let texCoordVariableExpression = texCoordVariable;
464
+
465
+ // Check if the texture defines a `transform` from a `KHR_texture_transform`
466
+ if (defined(transform) && !Matrix3.equals(transform, Matrix3.IDENTITY)) {
467
+ // Add a uniform for the transformation matrix
468
+ const transformUniformName = `${textureUniformName}Transform`;
469
+ shaderBuilder.addUniform(
470
+ "mat3",
471
+ transformUniformName,
472
+ ShaderDestination.FRAGMENT
473
+ );
474
+ uniformMap[transformUniformName] = function () {
475
+ return transform;
476
+ };
477
+
478
+ // Update the expression for the texture coordinates
479
+ // with one that transforms the texture coordinates
480
+ // with the transform matrix first
481
+ texCoordVariableExpression = `vec2(${transformUniformName} * vec3(${texCoordVariable}, 1.0))`;
482
+ }
483
+ const valueExpression = `texture(${textureUniformName}, ${texCoordVariableExpression}).${channels}`;
456
484
 
457
485
  // Some types need an unpacking step or two. For example, since texture reads
458
486
  // are always normalized, UINT8 (not normalized) properties need to be