@cesium/engine 8.0.0 → 9.1.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 (192) hide show
  1. package/Build/ThirdParty/Workers/z-worker-pako.js +7 -10
  2. package/Build/Workers/{chunk-F4HFJMGM.js → chunk-2CSEEWHN.js} +6 -6
  3. package/Build/Workers/{chunk-7TC63SJW.js → chunk-34DGOKCO.js} +10 -12
  4. package/Build/Workers/{chunk-7ZFGPDJA.js → chunk-3RZK5NNV.js} +4 -4
  5. package/Build/Workers/{chunk-M7ERACJJ.js → chunk-3S2MFY4B.js} +13 -13
  6. package/Build/Workers/{chunk-BROJAZRZ.js → chunk-4AJGCQFX.js} +13 -13
  7. package/Build/Workers/{chunk-2FWRMUTY.js → chunk-4KIUON73.js} +4 -4
  8. package/Build/Workers/{chunk-5QULIR53.js → chunk-4PHPQRSH.js} +4 -4
  9. package/Build/Workers/{chunk-X4356LRH.js → chunk-66E3H2KU.js} +12 -12
  10. package/Build/Workers/{chunk-G43QFN4Q.js → chunk-6HCAQOVK.js} +6 -6
  11. package/Build/Workers/{chunk-23UFSGND.js → chunk-7LPEGKOF.js} +7 -7
  12. package/Build/Workers/{chunk-DDUQAJ4P.js → chunk-7VZNXIKG.js} +7 -7
  13. package/Build/Workers/{chunk-JURN7NPV.js → chunk-A6NCZSL3.js} +19 -19
  14. package/Build/Workers/{chunk-ZT7KWISZ.js → chunk-AOFMPKUB.js} +4 -4
  15. package/Build/Workers/{chunk-BIKA3NRA.js → chunk-AOIKO5Y7.js} +5 -5
  16. package/Build/Workers/{chunk-YWTJ2B4B.js → chunk-BDUJXBVF.js} +1 -1
  17. package/Build/Workers/{chunk-OGXZVPPM.js → chunk-C5CE4OG6.js} +469 -6
  18. package/Build/Workers/{chunk-FNIRWHJB.js → chunk-CE6GTZ4I.js} +11 -13
  19. package/Build/Workers/{chunk-SH5USDPI.js → chunk-CYAJYEKW.js} +6 -6
  20. package/Build/Workers/{chunk-Y5UQJLYE.js → chunk-FOZQIHZK.js} +6 -6
  21. package/Build/Workers/{chunk-2FRVPMCS.js → chunk-G7CJQKKD.js} +7 -7
  22. package/Build/Workers/{chunk-EERJKOAF.js → chunk-GIFJ77E4.js} +4 -4
  23. package/Build/Workers/{chunk-FJKNFAKQ.js → chunk-I5TDPPC4.js} +7197 -5096
  24. package/Build/Workers/{chunk-3VAZEH7M.js → chunk-IBXGK4WV.js} +2 -2
  25. package/Build/Workers/{chunk-VOXYEYJT.js → chunk-JI2445T5.js} +11 -11
  26. package/Build/Workers/{chunk-PGSJK77E.js → chunk-KPY4F4BW.js} +6 -6
  27. package/Build/Workers/{chunk-I46ZRR5W.js → chunk-LVJCR7DH.js} +17 -17
  28. package/Build/Workers/{chunk-T3XIFPYR.js → chunk-LW7WGHEU.js} +16 -16
  29. package/Build/Workers/{chunk-HU6N6EXB.js → chunk-MWYZ64MH.js} +12 -11
  30. package/Build/Workers/chunk-NI2R52QD.js +961 -0
  31. package/Build/Workers/{chunk-SOWMRMWA.js → chunk-PEABJLCK.js} +1 -1
  32. package/Build/Workers/{chunk-EG6PTBY2.js → chunk-PK7TEP3J.js} +15 -15
  33. package/Build/Workers/{chunk-GRC2ZTAF.js → chunk-POLFRINT.js} +14 -14
  34. package/Build/Workers/{chunk-Z3TIFFGF.js → chunk-PS6AEMBR.js} +7 -7
  35. package/Build/Workers/{chunk-Y2ME2IJV.js → chunk-PWF3YJJ5.js} +13 -13
  36. package/Build/Workers/{chunk-2A75IWRS.js → chunk-QKF7XXEQ.js} +7 -7
  37. package/Build/Workers/{chunk-4H7PY4U5.js → chunk-RL73GOEF.js} +2 -2
  38. package/Build/Workers/{chunk-MDWEGWPA.js → chunk-RR7EOKGZ.js} +10 -10
  39. package/Build/Workers/{chunk-F3YA3Y2Z.js → chunk-S4XDCPKD.js} +1 -1
  40. package/Build/Workers/{chunk-PPH7OFP3.js → chunk-TMMOULW3.js} +5 -5
  41. package/Build/Workers/{chunk-XGI5BXZY.js → chunk-U4IMCOF5.js} +2 -2
  42. package/Build/Workers/{chunk-4DO5W5XZ.js → chunk-UAJEGIWA.js} +6 -6
  43. package/Build/Workers/{chunk-BBWDMCVU.js → chunk-UCPPWV64.js} +1 -1
  44. package/Build/Workers/{chunk-FZRIVR7Y.js → chunk-V7JB576Q.js} +5 -5
  45. package/Build/Workers/{chunk-2UPKWTMJ.js → chunk-WEGCQ5DY.js} +6 -6
  46. package/Build/Workers/{chunk-STW2DGFI.js → chunk-WFICTTOE.js} +2 -2
  47. package/Build/Workers/{chunk-LPR3YNP2.js → chunk-WWP3I7R5.js} +5 -5
  48. package/Build/Workers/{chunk-A5DWLWCY.js → chunk-XHLDDE65.js} +10 -10
  49. package/Build/Workers/{chunk-UEXTBDBE.js → chunk-XWML5Y7N.js} +11 -13
  50. package/Build/Workers/{chunk-EHWHNOEX.js → chunk-YLZTCEBJ.js} +1 -1
  51. package/Build/Workers/{chunk-34FXV7D7.js → chunk-ZC4AGBZK.js} +2 -2
  52. package/Build/Workers/{chunk-GATZHF3K.js → chunk-ZDP32RQI.js} +2 -2
  53. package/Build/Workers/{chunk-KKCR2YOP.js → chunk-ZWPIM77Q.js} +11 -11
  54. package/Build/Workers/combineGeometry.js +22 -24
  55. package/Build/Workers/createBoxGeometry.js +16 -18
  56. package/Build/Workers/createBoxOutlineGeometry.js +14 -16
  57. package/Build/Workers/createCircleGeometry.js +24 -26
  58. package/Build/Workers/createCircleOutlineGeometry.js +17 -19
  59. package/Build/Workers/createCoplanarPolygonGeometry.js +33 -34
  60. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +29 -31
  61. package/Build/Workers/createCorridorGeometry.js +27 -29
  62. package/Build/Workers/createCorridorOutlineGeometry.js +26 -28
  63. package/Build/Workers/createCylinderGeometry.js +18 -20
  64. package/Build/Workers/createCylinderOutlineGeometry.js +16 -18
  65. package/Build/Workers/createEllipseGeometry.js +24 -26
  66. package/Build/Workers/createEllipseOutlineGeometry.js +17 -19
  67. package/Build/Workers/createEllipsoidGeometry.js +17 -19
  68. package/Build/Workers/createEllipsoidOutlineGeometry.js +16 -18
  69. package/Build/Workers/createFrustumGeometry.js +16 -18
  70. package/Build/Workers/createFrustumOutlineGeometry.js +18 -19
  71. package/Build/Workers/createGeometry.js +23 -25
  72. package/Build/Workers/createGroundPolylineGeometry.js +23 -25
  73. package/Build/Workers/createPlaneGeometry.js +14 -16
  74. package/Build/Workers/createPlaneOutlineGeometry.js +13 -15
  75. package/Build/Workers/createPolygonGeometry.js +33 -35
  76. package/Build/Workers/createPolygonOutlineGeometry.js +28 -30
  77. package/Build/Workers/createPolylineGeometry.js +23 -25
  78. package/Build/Workers/createPolylineVolumeGeometry.js +29 -31
  79. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +25 -27
  80. package/Build/Workers/createRectangleGeometry.js +27 -29
  81. package/Build/Workers/createRectangleOutlineGeometry.js +18 -20
  82. package/Build/Workers/createSimplePolylineGeometry.js +21 -23
  83. package/Build/Workers/createSphereGeometry.js +17 -19
  84. package/Build/Workers/createSphereOutlineGeometry.js +16 -18
  85. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  86. package/Build/Workers/createVectorTileClampedPolylines.js +14 -16
  87. package/Build/Workers/createVectorTileGeometries.js +22 -24
  88. package/Build/Workers/createVectorTilePoints.js +12 -12
  89. package/Build/Workers/createVectorTilePolygons.js +20 -22
  90. package/Build/Workers/createVectorTilePolylines.js +14 -16
  91. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +23 -25
  92. package/Build/Workers/createVerticesFromHeightmap.js +23 -25
  93. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +19 -22
  94. package/Build/Workers/createWallGeometry.js +22 -24
  95. package/Build/Workers/createWallOutlineGeometry.js +21 -23
  96. package/Build/Workers/decodeDraco.js +11 -11
  97. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  98. package/Build/Workers/decodeI3S.js +10 -11
  99. package/Build/Workers/transcodeKTX2.js +8 -8
  100. package/Build/Workers/transferTypedArrayTest.js +1 -1
  101. package/Build/Workers/upsampleQuantizedTerrainMesh.js +20 -22
  102. package/Source/Core/Check.d.ts +127 -0
  103. package/Source/Core/Check.js +0 -1
  104. package/Source/Core/Geometry.js +1 -1
  105. package/Source/Core/Ion.js +1 -1
  106. package/Source/Core/PixelFormat.js +1 -0
  107. package/Source/Core/PolygonGeometry.js +1 -1
  108. package/Source/Core/Rectangle.js +89 -0
  109. package/Source/Core/VerticalExaggeration.js +2 -1
  110. package/Source/DataSources/DataSourceDisplay.js +5 -0
  111. package/Source/Renderer/ShaderBuilder.js +6 -3
  112. package/Source/Scene/ArcGisMapService.js +1 -1
  113. package/Source/Scene/Billboard.js +37 -3
  114. package/Source/Scene/BillboardCollection.js +1 -1
  115. package/Source/Scene/BingMapsImageryProvider.js +4 -0
  116. package/Source/Scene/Cesium3DTile.js +65 -0
  117. package/Source/Scene/Cesium3DTilesVoxelProvider.js +2 -9
  118. package/Source/Scene/Cesium3DTileset.js +52 -40
  119. package/Source/Scene/ClippingPolygon.js +212 -0
  120. package/Source/Scene/ClippingPolygonCollection.js +968 -0
  121. package/Source/Scene/Globe.js +14 -67
  122. package/Source/Scene/GlobeSurfaceShaderSet.js +81 -15
  123. package/Source/Scene/GlobeSurfaceTileProvider.js +81 -1
  124. package/Source/Scene/Label.js +33 -0
  125. package/Source/Scene/LabelCollection.js +2 -1
  126. package/Source/Scene/Model/Model.js +83 -0
  127. package/Source/Scene/Model/Model3DTileContent.js +21 -0
  128. package/Source/Scene/Model/ModelClippingPolygonsPipelineStage.js +92 -0
  129. package/Source/Scene/Model/ModelSceneGraph.js +5 -0
  130. package/Source/Scene/Primitive.js +0 -3
  131. package/Source/Scene/SensorVolumePortionToDisplay.js +1 -1
  132. package/Source/Scene/Terrain.js +2 -2
  133. package/Source/Scene/VoxelBoxShape.js +0 -15
  134. package/Source/Scene/VoxelCylinderShape.js +14 -131
  135. package/Source/Scene/VoxelEllipsoidShape.js +136 -227
  136. package/Source/Scene/VoxelPrimitive.js +106 -14
  137. package/Source/Scene/VoxelRenderResources.js +9 -3
  138. package/Source/Scene/VoxelShape.js +0 -10
  139. package/Source/Scene/processVoxelProperties.js +1 -0
  140. package/Source/Shaders/Builtin/CzmBuiltins.js +4 -0
  141. package/Source/Shaders/Builtin/Functions/clipPolygons.glsl +37 -0
  142. package/Source/Shaders/Builtin/Functions/clipPolygons.js +39 -0
  143. package/Source/Shaders/Builtin/Functions/unpackClippingExtents.glsl +14 -0
  144. package/Source/Shaders/Builtin/Functions/unpackClippingExtents.js +15 -0
  145. package/Source/Shaders/GlobeFS.glsl +12 -0
  146. package/Source/Shaders/GlobeFS.js +12 -0
  147. package/Source/Shaders/GlobeVS.glsl +32 -0
  148. package/Source/Shaders/GlobeVS.js +32 -0
  149. package/Source/Shaders/Model/GeometryStageVS.glsl +1 -1
  150. package/Source/Shaders/Model/GeometryStageVS.js +1 -1
  151. package/Source/Shaders/Model/ModelClippingPolygonsStageFS.glsl +6 -0
  152. package/Source/Shaders/Model/ModelClippingPolygonsStageFS.js +8 -0
  153. package/Source/Shaders/Model/ModelClippingPolygonsStageVS.glsl +27 -0
  154. package/Source/Shaders/Model/ModelClippingPolygonsStageVS.js +29 -0
  155. package/Source/Shaders/Model/ModelFS.glsl +6 -0
  156. package/Source/Shaders/Model/ModelFS.js +7 -1
  157. package/Source/Shaders/Model/ModelVS.glsl +4 -0
  158. package/Source/Shaders/Model/ModelVS.js +4 -0
  159. package/Source/Shaders/PolygonSignedDistanceFS.glsl +100 -0
  160. package/Source/Shaders/PolygonSignedDistanceFS.js +101 -0
  161. package/Source/Shaders/Voxels/IntersectBox.glsl +21 -47
  162. package/Source/Shaders/Voxels/IntersectBox.js +21 -47
  163. package/Source/Shaders/Voxels/IntersectClippingPlanes.glsl +1 -1
  164. package/Source/Shaders/Voxels/IntersectClippingPlanes.js +1 -1
  165. package/Source/Shaders/Voxels/IntersectCylinder.glsl +66 -96
  166. package/Source/Shaders/Voxels/IntersectCylinder.js +66 -96
  167. package/Source/Shaders/Voxels/IntersectEllipsoid.glsl +226 -154
  168. package/Source/Shaders/Voxels/IntersectEllipsoid.js +226 -154
  169. package/Source/Shaders/Voxels/IntersectionUtils.glsl +33 -11
  170. package/Source/Shaders/Voxels/IntersectionUtils.js +33 -11
  171. package/Source/Shaders/Voxels/Megatexture.glsl +1 -2
  172. package/Source/Shaders/Voxels/Megatexture.js +1 -2
  173. package/Source/Shaders/Voxels/Octree.glsl +14 -9
  174. package/Source/Shaders/Voxels/Octree.js +14 -9
  175. package/Source/Shaders/Voxels/VoxelFS.glsl +93 -43
  176. package/Source/Shaders/Voxels/VoxelFS.js +93 -43
  177. package/Source/Shaders/Voxels/VoxelUtils.glsl +31 -0
  178. package/Source/Shaders/Voxels/VoxelUtils.js +33 -0
  179. package/Source/Shaders/Voxels/convertUvToBox.glsl +24 -3
  180. package/Source/Shaders/Voxels/convertUvToBox.js +24 -4
  181. package/Source/Shaders/Voxels/convertUvToCylinder.glsl +50 -8
  182. package/Source/Shaders/Voxels/convertUvToCylinder.js +50 -8
  183. package/Source/Shaders/Voxels/convertUvToEllipsoid.glsl +82 -53
  184. package/Source/Shaders/Voxels/convertUvToEllipsoid.js +82 -53
  185. package/Source/ThirdParty/Workers/z-worker-pako.js +1 -1
  186. package/Source/Workers/createGeometry.js +1 -1
  187. package/index.d.ts +478 -35
  188. package/index.js +61 -52
  189. package/package.json +2 -2
  190. package/Build/Workers/chunk-BG4UCVXN.js +0 -73
  191. package/Build/Workers/chunk-TTUZP4BO.js +0 -501
  192. package/Build/Workers/chunk-YJEBABKH.js +0 -2977
@@ -79,10 +79,15 @@ int getOctreeParentIndex(in int octreeIndex) {
79
79
  */
80
80
  vec3 getTileUv(in vec3 shapePosition, in ivec4 octreeCoords) {
81
81
  // PERFORMANCE_IDEA: use bit-shifting (only in WebGL2)
82
- float dimAtLevel = pow(2.0, float(octreeCoords.w));
82
+ float dimAtLevel = exp2(float(octreeCoords.w));
83
83
  return shapePosition * dimAtLevel - vec3(octreeCoords.xyz);
84
84
  }
85
85
 
86
+ vec3 getClampedTileUv(in vec3 shapePosition, in ivec4 octreeCoords) {
87
+ vec3 tileUv = getTileUv(shapePosition, octreeCoords);
88
+ return clamp(tileUv, vec3(0.0), vec3(1.0));
89
+ }
90
+
86
91
  void getOctreeLeafSampleData(in OctreeNodeData data, in ivec4 octreeCoords, out SampleData sampleData) {
87
92
  sampleData.megatextureIndex = data.data;
88
93
  sampleData.tileCoords = (data.flag == OCTREE_FLAG_PACKED_LEAF_FROM_PARENT)
@@ -121,7 +126,7 @@ void getOctreeLeafSampleDatas(in OctreeNodeData data, in ivec4 octreeCoords, out
121
126
  #endif
122
127
 
123
128
  OctreeNodeData traverseOctreeDownwards(in vec3 shapePosition, inout TraversalData traversalData) {
124
- float sizeAtLevel = 1.0 / pow(2.0, float(traversalData.octreeCoords.w));
129
+ float sizeAtLevel = exp2(-1.0 * float(traversalData.octreeCoords.w));
125
130
  vec3 start = vec3(traversalData.octreeCoords.xyz) * sizeAtLevel;
126
131
  vec3 end = start + vec3(sizeAtLevel);
127
132
  OctreeNodeData childData;
@@ -167,11 +172,11 @@ void traverseOctreeFromBeginning(in vec3 shapePosition, out TraversalData traver
167
172
 
168
173
  #if (SAMPLE_COUNT == 1)
169
174
  getOctreeLeafSampleData(nodeData, traversalData.octreeCoords, sampleDatas[0]);
170
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);
175
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);
171
176
  #else
172
177
  getOctreeLeafSampleDatas(nodeData, traversalData.octreeCoords, sampleDatas);
173
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);
174
- sampleDatas[1].tileUv = getTileUv(shapePosition, sampleDatas[1].tileCoords);
178
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);
179
+ sampleDatas[1].tileUv = getClampedTileUv(shapePosition, sampleDatas[1].tileCoords);
175
180
  #endif
176
181
  }
177
182
 
@@ -189,7 +194,7 @@ bool insideTile(in vec3 shapePosition, in ivec4 octreeCoords) {
189
194
  void traverseOctreeFromExisting(in vec3 shapePosition, inout TraversalData traversalData, inout SampleData sampleDatas[SAMPLE_COUNT]) {
190
195
  if (insideTile(shapePosition, traversalData.octreeCoords)) {
191
196
  for (int i = 0; i < SAMPLE_COUNT; i++) {
192
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);
197
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);
193
198
  }
194
199
  return;
195
200
  }
@@ -211,10 +216,10 @@ void traverseOctreeFromExisting(in vec3 shapePosition, inout TraversalData trave
211
216
 
212
217
  #if (SAMPLE_COUNT == 1)
213
218
  getOctreeLeafSampleData(nodeData, traversalData.octreeCoords, sampleDatas[0]);
214
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);
219
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);
215
220
  #else
216
221
  getOctreeLeafSampleDatas(nodeData, traversalData.octreeCoords, sampleDatas);
217
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);
218
- sampleDatas[1].tileUv = getTileUv(shapePosition, sampleDatas[1].tileCoords);
222
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);
223
+ sampleDatas[1].tileUv = getClampedTileUv(shapePosition, sampleDatas[1].tileCoords);
219
224
  #endif
220
225
  }
@@ -80,10 +80,15 @@ int getOctreeParentIndex(in int octreeIndex) {\n\
80
80
  */\n\
81
81
  vec3 getTileUv(in vec3 shapePosition, in ivec4 octreeCoords) {\n\
82
82
  // PERFORMANCE_IDEA: use bit-shifting (only in WebGL2)\n\
83
- float dimAtLevel = pow(2.0, float(octreeCoords.w));\n\
83
+ float dimAtLevel = exp2(float(octreeCoords.w));\n\
84
84
  return shapePosition * dimAtLevel - vec3(octreeCoords.xyz);\n\
85
85
  }\n\
86
86
  \n\
87
+ vec3 getClampedTileUv(in vec3 shapePosition, in ivec4 octreeCoords) {\n\
88
+ vec3 tileUv = getTileUv(shapePosition, octreeCoords);\n\
89
+ return clamp(tileUv, vec3(0.0), vec3(1.0));\n\
90
+ }\n\
91
+ \n\
87
92
  void getOctreeLeafSampleData(in OctreeNodeData data, in ivec4 octreeCoords, out SampleData sampleData) {\n\
88
93
  sampleData.megatextureIndex = data.data;\n\
89
94
  sampleData.tileCoords = (data.flag == OCTREE_FLAG_PACKED_LEAF_FROM_PARENT)\n\
@@ -122,7 +127,7 @@ void getOctreeLeafSampleDatas(in OctreeNodeData data, in ivec4 octreeCoords, out
122
127
  #endif\n\
123
128
  \n\
124
129
  OctreeNodeData traverseOctreeDownwards(in vec3 shapePosition, inout TraversalData traversalData) {\n\
125
- float sizeAtLevel = 1.0 / pow(2.0, float(traversalData.octreeCoords.w));\n\
130
+ float sizeAtLevel = exp2(-1.0 * float(traversalData.octreeCoords.w));\n\
126
131
  vec3 start = vec3(traversalData.octreeCoords.xyz) * sizeAtLevel;\n\
127
132
  vec3 end = start + vec3(sizeAtLevel);\n\
128
133
  OctreeNodeData childData;\n\
@@ -168,11 +173,11 @@ void traverseOctreeFromBeginning(in vec3 shapePosition, out TraversalData traver
168
173
  \n\
169
174
  #if (SAMPLE_COUNT == 1)\n\
170
175
  getOctreeLeafSampleData(nodeData, traversalData.octreeCoords, sampleDatas[0]);\n\
171
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
176
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
172
177
  #else\n\
173
178
  getOctreeLeafSampleDatas(nodeData, traversalData.octreeCoords, sampleDatas);\n\
174
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
175
- sampleDatas[1].tileUv = getTileUv(shapePosition, sampleDatas[1].tileCoords);\n\
179
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
180
+ sampleDatas[1].tileUv = getClampedTileUv(shapePosition, sampleDatas[1].tileCoords);\n\
176
181
  #endif\n\
177
182
  }\n\
178
183
  \n\
@@ -190,7 +195,7 @@ bool insideTile(in vec3 shapePosition, in ivec4 octreeCoords) {\n\
190
195
  void traverseOctreeFromExisting(in vec3 shapePosition, inout TraversalData traversalData, inout SampleData sampleDatas[SAMPLE_COUNT]) {\n\
191
196
  if (insideTile(shapePosition, traversalData.octreeCoords)) {\n\
192
197
  for (int i = 0; i < SAMPLE_COUNT; i++) {\n\
193
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
198
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
194
199
  }\n\
195
200
  return;\n\
196
201
  }\n\
@@ -212,11 +217,11 @@ void traverseOctreeFromExisting(in vec3 shapePosition, inout TraversalData trave
212
217
  \n\
213
218
  #if (SAMPLE_COUNT == 1)\n\
214
219
  getOctreeLeafSampleData(nodeData, traversalData.octreeCoords, sampleDatas[0]);\n\
215
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
220
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
216
221
  #else\n\
217
222
  getOctreeLeafSampleDatas(nodeData, traversalData.octreeCoords, sampleDatas);\n\
218
- sampleDatas[0].tileUv = getTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
219
- sampleDatas[1].tileUv = getTileUv(shapePosition, sampleDatas[1].tileCoords);\n\
223
+ sampleDatas[0].tileUv = getClampedTileUv(shapePosition, sampleDatas[0].tileCoords);\n\
224
+ sampleDatas[1].tileUv = getClampedTileUv(shapePosition, sampleDatas[1].tileCoords);\n\
220
225
  #endif\n\
221
226
  }\n\
222
227
  ";
@@ -23,27 +23,68 @@ uniform float u_stepSize;
23
23
  uniform vec4 u_pickColor;
24
24
  #endif
25
25
 
26
- #if defined(JITTER)
27
- float hash(vec2 p)
28
- {
29
- vec3 p3 = fract(vec3(p.xyx) * 50.0); // magic number = hashscale
30
- p3 += dot(p3, p3.yzx + 19.19);
31
- return fract((p3.x + p3.y) * p3.z);
26
+ vec3 getSampleSize(in int level) {
27
+ vec3 sampleCount = exp2(float(level)) * vec3(u_dimensions);
28
+ vec3 sampleSizeUv = 1.0 / sampleCount;
29
+ return scaleShapeUvToShapeSpace(sampleSizeUv);
32
30
  }
33
- #endif
34
31
 
35
- vec4 getStepSize(in SampleData sampleData, in Ray viewRay, in RayShapeIntersection shapeIntersection) {
36
- #if defined(SHAPE_BOX)
37
- Box voxelBox = constructVoxelBox(sampleData.tileCoords, sampleData.tileUv);
38
- RayShapeIntersection voxelIntersection = intersectBox(viewRay, voxelBox);
39
- vec4 entry = shapeIntersection.entry.w >= voxelIntersection.entry.w ? shapeIntersection.entry : voxelIntersection.entry;
40
- float exit = min(voxelIntersection.exit.w, shapeIntersection.exit.w);
41
- float dt = (exit - entry.w) * RAY_SCALE;
42
- return vec4(normalize(entry.xyz), dt);
43
- #else
44
- float dimAtLevel = pow(2.0, float(sampleData.tileCoords.w));
45
- return vec4(viewRay.dir, u_stepSize / dimAtLevel);
46
- #endif
32
+ #define MINIMUM_STEP_SCALAR (0.02)
33
+ #define SHIFT_FRACTION (0.001)
34
+
35
+ /**
36
+ * Given a coordinate within a tile, and sample spacings along a ray through
37
+ * the coordinate, find the distance to the points where the ray entered and
38
+ * exited the voxel cell, along with the surface normals at those points.
39
+ * The surface normals are returned in shape space coordinates.
40
+ */
41
+ RayShapeIntersection getVoxelIntersection(in vec3 tileUv, in vec3 sampleSizeAlongRay) {
42
+ vec3 voxelCoord = tileUv * vec3(u_dimensions);
43
+ vec3 directions = sign(sampleSizeAlongRay);
44
+ vec3 positiveDirections = max(directions, 0.0);
45
+ vec3 entryCoord = mix(ceil(voxelCoord), floor(voxelCoord), positiveDirections);
46
+ vec3 exitCoord = entryCoord + directions;
47
+
48
+ vec3 distanceFromEntry = -abs((entryCoord - voxelCoord) * sampleSizeAlongRay);
49
+ float lastEntry = maxComponent(distanceFromEntry);
50
+ bvec3 isLastEntry = equal(distanceFromEntry, vec3(lastEntry));
51
+ vec3 entryNormal = -1.0 * vec3(isLastEntry) * directions;
52
+ vec4 entry = vec4(entryNormal, lastEntry);
53
+
54
+ vec3 distanceToExit = abs((exitCoord - voxelCoord) * sampleSizeAlongRay);
55
+ float firstExit = minComponent(distanceToExit);
56
+ bvec3 isFirstExit = equal(distanceToExit, vec3(firstExit));
57
+ vec3 exitNormal = vec3(isFirstExit) * directions;
58
+ vec4 exit = vec4(exitNormal, firstExit);
59
+
60
+ return RayShapeIntersection(entry, exit);
61
+ }
62
+
63
+ vec4 getStepSize(in SampleData sampleData, in Ray viewRay, in RayShapeIntersection shapeIntersection, in mat3 jacobianT, in float currentT) {
64
+ // The Jacobian is computed in a space where the shape spans [-1, 1].
65
+ // But the ray is marched in a space where the shape fills [0, 1].
66
+ // So we need to scale the Jacobian by 2.
67
+ vec3 gradient = 2.0 * viewRay.rawDir * jacobianT;
68
+ vec3 sampleSizeAlongRay = getSampleSize(sampleData.tileCoords.w) / gradient;
69
+
70
+ RayShapeIntersection voxelIntersection = getVoxelIntersection(sampleData.tileUv, sampleSizeAlongRay);
71
+
72
+ // Transform normal from shape space to Cartesian space
73
+ vec3 voxelNormal = normalize(jacobianT * voxelIntersection.entry.xyz);
74
+ // Compare with the shape intersection, to choose the appropriate normal
75
+ vec4 voxelEntry = vec4(voxelNormal, currentT + voxelIntersection.entry.w);
76
+ vec4 entry = intersectionMax(shapeIntersection.entry, voxelEntry);
77
+
78
+ float fixedStep = minComponent(abs(sampleSizeAlongRay)) * u_stepSize;
79
+ float shift = fixedStep * SHIFT_FRACTION;
80
+ float dt = voxelIntersection.exit.w + shift;
81
+ if ((currentT + dt) > shapeIntersection.exit.w) {
82
+ // Stop at end of shape
83
+ dt = shapeIntersection.exit.w - currentT + shift;
84
+ }
85
+ float stepSize = clamp(dt, fixedStep * MINIMUM_STEP_SCALAR, fixedStep + shift);
86
+
87
+ return vec4(entry.xyz, stepSize);
47
88
  }
48
89
 
49
90
  vec2 packIntToVec2(int value) {
@@ -61,13 +102,19 @@ vec2 packFloatToVec2(float value) {
61
102
 
62
103
  int getSampleIndex(in vec3 tileUv) {
63
104
  ivec3 voxelDimensions = u_dimensions;
64
- vec3 tileCoordinate = clamp(tileUv, 0.0, 1.0) * vec3(voxelDimensions);
65
- ivec3 tileIndex = ivec3(floor(tileCoordinate));
105
+ vec3 sampleCoordinate = tileUv * vec3(voxelDimensions);
106
+ // tileUv = 1.0 is a valid coordinate but sampleIndex = voxelDimensions is not.
107
+ // (tileUv = 1.0 corresponds to the last sample, at index = voxelDimensions - 1).
108
+ // Clamp to [0, voxelDimensions - 0.5) to avoid numerical error before flooring
109
+ vec3 maxCoordinate = vec3(voxelDimensions) - vec3(0.5);
110
+ sampleCoordinate = clamp(sampleCoordinate, vec3(0.0), maxCoordinate);
111
+ ivec3 sampleIndex = ivec3(floor(sampleCoordinate));
66
112
  #if defined(PADDING)
67
113
  voxelDimensions += u_paddingBefore + u_paddingAfter;
68
- tileIndex += u_paddingBefore;
114
+ sampleIndex += u_paddingBefore;
69
115
  #endif
70
- return tileIndex.x + voxelDimensions.x * (tileIndex.y + voxelDimensions.y * tileIndex.z);
116
+ // Convert to a 1D index for lookup in a 1D data array
117
+ return sampleIndex.x + voxelDimensions.x * (sampleIndex.y + voxelDimensions.y * sampleIndex.z);
71
118
  }
72
119
 
73
120
  void main()
@@ -78,11 +125,13 @@ void main()
78
125
  vec3 viewDirWorld = normalize(czm_inverseViewRotation * eyeDirection); // normalize again just in case
79
126
  vec3 viewDirUv = normalize(u_transformDirectionViewToLocal * eyeDirection); // normalize again just in case
80
127
  vec3 viewPosUv = u_cameraPositionUv;
81
- #if defined(SHAPE_BOX)
82
- vec3 dInv = 1.0 / viewDirUv;
83
- Ray viewRayUv = Ray(viewPosUv, viewDirUv, dInv);
128
+ #if defined(SHAPE_ELLIPSOID)
129
+ // viewDirUv has been scaled to a space where the ellipsoid is a sphere.
130
+ // Undo this scaling to get the raw direction.
131
+ vec3 rawDir = viewDirUv * u_ellipsoidRadiiUv;
132
+ Ray viewRayUv = Ray(viewPosUv, viewDirUv, rawDir);
84
133
  #else
85
- Ray viewRayUv = Ray(viewPosUv, viewDirUv);
134
+ Ray viewRayUv = Ray(viewPosUv, viewDirUv, viewDirUv);
86
135
  #endif
87
136
 
88
137
  Intersections ix;
@@ -93,20 +142,20 @@ void main()
93
142
  discard;
94
143
  }
95
144
 
96
- float currT = shapeIntersection.entry.w * RAY_SCALE;
145
+ float currentT = shapeIntersection.entry.w;
97
146
  float endT = shapeIntersection.exit.w;
98
- vec3 positionUv = viewPosUv + currT * viewDirUv;
99
- vec3 positionUvShapeSpace = convertUvToShapeUvSpace(positionUv);
147
+ vec3 positionUv = viewPosUv + currentT * viewDirUv;
148
+ PointJacobianT pointJacobian = convertUvToShapeUvSpaceDerivative(positionUv);
100
149
 
101
150
  // Traverse the tree from the start position
102
151
  TraversalData traversalData;
103
152
  SampleData sampleDatas[SAMPLE_COUNT];
104
- traverseOctreeFromBeginning(positionUvShapeSpace, traversalData, sampleDatas);
105
- vec4 step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection);
153
+ traverseOctreeFromBeginning(pointJacobian.point, traversalData, sampleDatas);
154
+ vec4 step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection, pointJacobian.jacobianT, currentT);
106
155
 
107
156
  #if defined(JITTER)
108
157
  float noise = hash(screenCoord); // [0,1]
109
- currT += noise * step.w;
158
+ currentT += noise * step.w;
110
159
  positionUv += noise * step.w * viewDirUv;
111
160
  #endif
112
161
 
@@ -115,7 +164,7 @@ void main()
115
164
  setStatistics(fragmentInput.metadata.statistics);
116
165
  #endif
117
166
 
118
- vec4 colorAccum =vec4(0.0);
167
+ vec4 colorAccum = vec4(0.0);
119
168
 
120
169
  for (int stepCount = 0; stepCount < STEP_COUNT_MAX; ++stepCount) {
121
170
  // Read properties from the megatexture based on the traversal state
@@ -124,12 +173,13 @@ void main()
124
173
  // Prepare the custom shader inputs
125
174
  copyPropertiesToMetadata(properties, fragmentInput.metadata);
126
175
  fragmentInput.voxel.positionUv = positionUv;
127
- fragmentInput.voxel.positionShapeUv = positionUvShapeSpace;
176
+ fragmentInput.voxel.positionShapeUv = pointJacobian.point;
128
177
  fragmentInput.voxel.positionUvLocal = sampleDatas[0].tileUv;
129
178
  fragmentInput.voxel.viewDirUv = viewDirUv;
130
179
  fragmentInput.voxel.viewDirWorld = viewDirWorld;
131
180
  fragmentInput.voxel.surfaceNormal = step.xyz;
132
181
  fragmentInput.voxel.travelDistance = step.w;
182
+ fragmentInput.voxel.stepCount = stepCount;
133
183
  fragmentInput.voxel.tileIndex = sampleDatas[0].megatextureIndex;
134
184
  fragmentInput.voxel.sampleIndex = getSampleIndex(sampleDatas[0].tileUv);
135
185
 
@@ -158,11 +208,11 @@ void main()
158
208
  }
159
209
 
160
210
  // Keep raymarching
161
- currT += step.w;
162
- positionUv += step.w * viewDirUv;
211
+ currentT += step.w;
212
+ positionUv = viewPosUv + currentT * viewDirUv;
163
213
 
164
214
  // Check if there's more intersections.
165
- if (currT > endT) {
215
+ if (currentT > endT) {
166
216
  #if (INTERSECTION_COUNT == 1)
167
217
  break;
168
218
  #else
@@ -171,18 +221,18 @@ void main()
171
221
  break;
172
222
  } else {
173
223
  // Found another intersection. Resume raymarching there
174
- currT = shapeIntersection.entry.w * RAY_SCALE;
224
+ currentT = shapeIntersection.entry.w;
175
225
  endT = shapeIntersection.exit.w;
176
- positionUv = viewPosUv + currT * viewDirUv;
226
+ positionUv = viewPosUv + currentT * viewDirUv;
177
227
  }
178
228
  #endif
179
229
  }
180
230
 
181
231
  // Traverse the tree from the current ray position.
182
232
  // This is similar to traverseOctreeFromBeginning but is faster when the ray is in the same tile as the previous step.
183
- positionUvShapeSpace = convertUvToShapeUvSpace(positionUv);
184
- traverseOctreeFromExisting(positionUvShapeSpace, traversalData, sampleDatas);
185
- step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection);
233
+ pointJacobian = convertUvToShapeUvSpaceDerivative(positionUv);
234
+ traverseOctreeFromExisting(pointJacobian.point, traversalData, sampleDatas);
235
+ step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection, pointJacobian.jacobianT, currentT);
186
236
  }
187
237
 
188
238
  // Convert the alpha from [0,ALPHA_ACCUM_MAX] to [0,1]
@@ -24,27 +24,68 @@ uniform float u_stepSize;\n\
24
24
  uniform vec4 u_pickColor;\n\
25
25
  #endif\n\
26
26
  \n\
27
- #if defined(JITTER)\n\
28
- float hash(vec2 p)\n\
29
- {\n\
30
- vec3 p3 = fract(vec3(p.xyx) * 50.0); // magic number = hashscale\n\
31
- p3 += dot(p3, p3.yzx + 19.19);\n\
32
- return fract((p3.x + p3.y) * p3.z);\n\
27
+ vec3 getSampleSize(in int level) {\n\
28
+ vec3 sampleCount = exp2(float(level)) * vec3(u_dimensions);\n\
29
+ vec3 sampleSizeUv = 1.0 / sampleCount;\n\
30
+ return scaleShapeUvToShapeSpace(sampleSizeUv);\n\
33
31
  }\n\
34
- #endif\n\
35
32
  \n\
36
- vec4 getStepSize(in SampleData sampleData, in Ray viewRay, in RayShapeIntersection shapeIntersection) {\n\
37
- #if defined(SHAPE_BOX)\n\
38
- Box voxelBox = constructVoxelBox(sampleData.tileCoords, sampleData.tileUv);\n\
39
- RayShapeIntersection voxelIntersection = intersectBox(viewRay, voxelBox);\n\
40
- vec4 entry = shapeIntersection.entry.w >= voxelIntersection.entry.w ? shapeIntersection.entry : voxelIntersection.entry;\n\
41
- float exit = min(voxelIntersection.exit.w, shapeIntersection.exit.w);\n\
42
- float dt = (exit - entry.w) * RAY_SCALE;\n\
43
- return vec4(normalize(entry.xyz), dt);\n\
44
- #else\n\
45
- float dimAtLevel = pow(2.0, float(sampleData.tileCoords.w));\n\
46
- return vec4(viewRay.dir, u_stepSize / dimAtLevel);\n\
47
- #endif\n\
33
+ #define MINIMUM_STEP_SCALAR (0.02)\n\
34
+ #define SHIFT_FRACTION (0.001)\n\
35
+ \n\
36
+ /**\n\
37
+ * Given a coordinate within a tile, and sample spacings along a ray through\n\
38
+ * the coordinate, find the distance to the points where the ray entered and\n\
39
+ * exited the voxel cell, along with the surface normals at those points.\n\
40
+ * The surface normals are returned in shape space coordinates.\n\
41
+ */\n\
42
+ RayShapeIntersection getVoxelIntersection(in vec3 tileUv, in vec3 sampleSizeAlongRay) {\n\
43
+ vec3 voxelCoord = tileUv * vec3(u_dimensions);\n\
44
+ vec3 directions = sign(sampleSizeAlongRay);\n\
45
+ vec3 positiveDirections = max(directions, 0.0);\n\
46
+ vec3 entryCoord = mix(ceil(voxelCoord), floor(voxelCoord), positiveDirections);\n\
47
+ vec3 exitCoord = entryCoord + directions;\n\
48
+ \n\
49
+ vec3 distanceFromEntry = -abs((entryCoord - voxelCoord) * sampleSizeAlongRay);\n\
50
+ float lastEntry = maxComponent(distanceFromEntry);\n\
51
+ bvec3 isLastEntry = equal(distanceFromEntry, vec3(lastEntry));\n\
52
+ vec3 entryNormal = -1.0 * vec3(isLastEntry) * directions;\n\
53
+ vec4 entry = vec4(entryNormal, lastEntry);\n\
54
+ \n\
55
+ vec3 distanceToExit = abs((exitCoord - voxelCoord) * sampleSizeAlongRay);\n\
56
+ float firstExit = minComponent(distanceToExit);\n\
57
+ bvec3 isFirstExit = equal(distanceToExit, vec3(firstExit));\n\
58
+ vec3 exitNormal = vec3(isFirstExit) * directions;\n\
59
+ vec4 exit = vec4(exitNormal, firstExit);\n\
60
+ \n\
61
+ return RayShapeIntersection(entry, exit);\n\
62
+ }\n\
63
+ \n\
64
+ vec4 getStepSize(in SampleData sampleData, in Ray viewRay, in RayShapeIntersection shapeIntersection, in mat3 jacobianT, in float currentT) {\n\
65
+ // The Jacobian is computed in a space where the shape spans [-1, 1].\n\
66
+ // But the ray is marched in a space where the shape fills [0, 1].\n\
67
+ // So we need to scale the Jacobian by 2.\n\
68
+ vec3 gradient = 2.0 * viewRay.rawDir * jacobianT;\n\
69
+ vec3 sampleSizeAlongRay = getSampleSize(sampleData.tileCoords.w) / gradient;\n\
70
+ \n\
71
+ RayShapeIntersection voxelIntersection = getVoxelIntersection(sampleData.tileUv, sampleSizeAlongRay);\n\
72
+ \n\
73
+ // Transform normal from shape space to Cartesian space\n\
74
+ vec3 voxelNormal = normalize(jacobianT * voxelIntersection.entry.xyz);\n\
75
+ // Compare with the shape intersection, to choose the appropriate normal\n\
76
+ vec4 voxelEntry = vec4(voxelNormal, currentT + voxelIntersection.entry.w);\n\
77
+ vec4 entry = intersectionMax(shapeIntersection.entry, voxelEntry);\n\
78
+ \n\
79
+ float fixedStep = minComponent(abs(sampleSizeAlongRay)) * u_stepSize;\n\
80
+ float shift = fixedStep * SHIFT_FRACTION;\n\
81
+ float dt = voxelIntersection.exit.w + shift;\n\
82
+ if ((currentT + dt) > shapeIntersection.exit.w) {\n\
83
+ // Stop at end of shape\n\
84
+ dt = shapeIntersection.exit.w - currentT + shift;\n\
85
+ }\n\
86
+ float stepSize = clamp(dt, fixedStep * MINIMUM_STEP_SCALAR, fixedStep + shift);\n\
87
+ \n\
88
+ return vec4(entry.xyz, stepSize);\n\
48
89
  }\n\
49
90
  \n\
50
91
  vec2 packIntToVec2(int value) {\n\
@@ -62,13 +103,19 @@ vec2 packFloatToVec2(float value) {\n\
62
103
  \n\
63
104
  int getSampleIndex(in vec3 tileUv) {\n\
64
105
  ivec3 voxelDimensions = u_dimensions;\n\
65
- vec3 tileCoordinate = clamp(tileUv, 0.0, 1.0) * vec3(voxelDimensions);\n\
66
- ivec3 tileIndex = ivec3(floor(tileCoordinate));\n\
106
+ vec3 sampleCoordinate = tileUv * vec3(voxelDimensions);\n\
107
+ // tileUv = 1.0 is a valid coordinate but sampleIndex = voxelDimensions is not.\n\
108
+ // (tileUv = 1.0 corresponds to the last sample, at index = voxelDimensions - 1).\n\
109
+ // Clamp to [0, voxelDimensions - 0.5) to avoid numerical error before flooring\n\
110
+ vec3 maxCoordinate = vec3(voxelDimensions) - vec3(0.5);\n\
111
+ sampleCoordinate = clamp(sampleCoordinate, vec3(0.0), maxCoordinate);\n\
112
+ ivec3 sampleIndex = ivec3(floor(sampleCoordinate));\n\
67
113
  #if defined(PADDING)\n\
68
114
  voxelDimensions += u_paddingBefore + u_paddingAfter;\n\
69
- tileIndex += u_paddingBefore;\n\
115
+ sampleIndex += u_paddingBefore;\n\
70
116
  #endif\n\
71
- return tileIndex.x + voxelDimensions.x * (tileIndex.y + voxelDimensions.y * tileIndex.z);\n\
117
+ // Convert to a 1D index for lookup in a 1D data array\n\
118
+ return sampleIndex.x + voxelDimensions.x * (sampleIndex.y + voxelDimensions.y * sampleIndex.z);\n\
72
119
  }\n\
73
120
  \n\
74
121
  void main()\n\
@@ -79,11 +126,13 @@ void main()\n\
79
126
  vec3 viewDirWorld = normalize(czm_inverseViewRotation * eyeDirection); // normalize again just in case\n\
80
127
  vec3 viewDirUv = normalize(u_transformDirectionViewToLocal * eyeDirection); // normalize again just in case\n\
81
128
  vec3 viewPosUv = u_cameraPositionUv;\n\
82
- #if defined(SHAPE_BOX)\n\
83
- vec3 dInv = 1.0 / viewDirUv;\n\
84
- Ray viewRayUv = Ray(viewPosUv, viewDirUv, dInv);\n\
129
+ #if defined(SHAPE_ELLIPSOID)\n\
130
+ // viewDirUv has been scaled to a space where the ellipsoid is a sphere.\n\
131
+ // Undo this scaling to get the raw direction.\n\
132
+ vec3 rawDir = viewDirUv * u_ellipsoidRadiiUv;\n\
133
+ Ray viewRayUv = Ray(viewPosUv, viewDirUv, rawDir);\n\
85
134
  #else\n\
86
- Ray viewRayUv = Ray(viewPosUv, viewDirUv);\n\
135
+ Ray viewRayUv = Ray(viewPosUv, viewDirUv, viewDirUv);\n\
87
136
  #endif\n\
88
137
  \n\
89
138
  Intersections ix;\n\
@@ -94,20 +143,20 @@ void main()\n\
94
143
  discard;\n\
95
144
  }\n\
96
145
  \n\
97
- float currT = shapeIntersection.entry.w * RAY_SCALE;\n\
146
+ float currentT = shapeIntersection.entry.w;\n\
98
147
  float endT = shapeIntersection.exit.w;\n\
99
- vec3 positionUv = viewPosUv + currT * viewDirUv;\n\
100
- vec3 positionUvShapeSpace = convertUvToShapeUvSpace(positionUv);\n\
148
+ vec3 positionUv = viewPosUv + currentT * viewDirUv;\n\
149
+ PointJacobianT pointJacobian = convertUvToShapeUvSpaceDerivative(positionUv);\n\
101
150
  \n\
102
151
  // Traverse the tree from the start position\n\
103
152
  TraversalData traversalData;\n\
104
153
  SampleData sampleDatas[SAMPLE_COUNT];\n\
105
- traverseOctreeFromBeginning(positionUvShapeSpace, traversalData, sampleDatas);\n\
106
- vec4 step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection);\n\
154
+ traverseOctreeFromBeginning(pointJacobian.point, traversalData, sampleDatas);\n\
155
+ vec4 step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection, pointJacobian.jacobianT, currentT);\n\
107
156
  \n\
108
157
  #if defined(JITTER)\n\
109
158
  float noise = hash(screenCoord); // [0,1]\n\
110
- currT += noise * step.w;\n\
159
+ currentT += noise * step.w;\n\
111
160
  positionUv += noise * step.w * viewDirUv;\n\
112
161
  #endif\n\
113
162
  \n\
@@ -116,7 +165,7 @@ void main()\n\
116
165
  setStatistics(fragmentInput.metadata.statistics);\n\
117
166
  #endif\n\
118
167
  \n\
119
- vec4 colorAccum =vec4(0.0);\n\
168
+ vec4 colorAccum = vec4(0.0);\n\
120
169
  \n\
121
170
  for (int stepCount = 0; stepCount < STEP_COUNT_MAX; ++stepCount) {\n\
122
171
  // Read properties from the megatexture based on the traversal state\n\
@@ -125,12 +174,13 @@ void main()\n\
125
174
  // Prepare the custom shader inputs\n\
126
175
  copyPropertiesToMetadata(properties, fragmentInput.metadata);\n\
127
176
  fragmentInput.voxel.positionUv = positionUv;\n\
128
- fragmentInput.voxel.positionShapeUv = positionUvShapeSpace;\n\
177
+ fragmentInput.voxel.positionShapeUv = pointJacobian.point;\n\
129
178
  fragmentInput.voxel.positionUvLocal = sampleDatas[0].tileUv;\n\
130
179
  fragmentInput.voxel.viewDirUv = viewDirUv;\n\
131
180
  fragmentInput.voxel.viewDirWorld = viewDirWorld;\n\
132
181
  fragmentInput.voxel.surfaceNormal = step.xyz;\n\
133
182
  fragmentInput.voxel.travelDistance = step.w;\n\
183
+ fragmentInput.voxel.stepCount = stepCount;\n\
134
184
  fragmentInput.voxel.tileIndex = sampleDatas[0].megatextureIndex;\n\
135
185
  fragmentInput.voxel.sampleIndex = getSampleIndex(sampleDatas[0].tileUv);\n\
136
186
  \n\
@@ -159,11 +209,11 @@ void main()\n\
159
209
  }\n\
160
210
  \n\
161
211
  // Keep raymarching\n\
162
- currT += step.w;\n\
163
- positionUv += step.w * viewDirUv;\n\
212
+ currentT += step.w;\n\
213
+ positionUv = viewPosUv + currentT * viewDirUv;\n\
164
214
  \n\
165
215
  // Check if there's more intersections.\n\
166
- if (currT > endT) {\n\
216
+ if (currentT > endT) {\n\
167
217
  #if (INTERSECTION_COUNT == 1)\n\
168
218
  break;\n\
169
219
  #else\n\
@@ -172,18 +222,18 @@ void main()\n\
172
222
  break;\n\
173
223
  } else {\n\
174
224
  // Found another intersection. Resume raymarching there\n\
175
- currT = shapeIntersection.entry.w * RAY_SCALE;\n\
225
+ currentT = shapeIntersection.entry.w;\n\
176
226
  endT = shapeIntersection.exit.w;\n\
177
- positionUv = viewPosUv + currT * viewDirUv;\n\
227
+ positionUv = viewPosUv + currentT * viewDirUv;\n\
178
228
  }\n\
179
229
  #endif\n\
180
230
  }\n\
181
231
  \n\
182
232
  // Traverse the tree from the current ray position.\n\
183
233
  // This is similar to traverseOctreeFromBeginning but is faster when the ray is in the same tile as the previous step.\n\
184
- positionUvShapeSpace = convertUvToShapeUvSpace(positionUv);\n\
185
- traverseOctreeFromExisting(positionUvShapeSpace, traversalData, sampleDatas);\n\
186
- step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection);\n\
234
+ pointJacobian = convertUvToShapeUvSpaceDerivative(positionUv);\n\
235
+ traverseOctreeFromExisting(pointJacobian.point, traversalData, sampleDatas);\n\
236
+ step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection, pointJacobian.jacobianT, currentT);\n\
187
237
  }\n\
188
238
  \n\
189
239
  // Convert the alpha from [0,ALPHA_ACCUM_MAX] to [0,1]\n\
@@ -0,0 +1,31 @@
1
+ struct Ray {
2
+ vec3 pos;
3
+ vec3 dir;
4
+ vec3 rawDir;
5
+ };
6
+
7
+ #if defined(JITTER)
8
+ /**
9
+ * Generate a pseudo-random value for a given 2D screen coordinate.
10
+ * Similar to https://www.shadertoy.com/view/4djSRW with a modified hashscale.
11
+ */
12
+ float hash(vec2 p)
13
+ {
14
+ vec3 p3 = fract(vec3(p.xyx) * 50.0);
15
+ p3 += dot(p3, p3.yzx + 19.19);
16
+ return fract((p3.x + p3.y) * p3.z);
17
+ }
18
+ #endif
19
+
20
+ float minComponent(in vec3 v) {
21
+ return min(min(v.x, v.y), v.z);
22
+ }
23
+
24
+ float maxComponent(in vec3 v) {
25
+ return max(max(v.x, v.y), v.z);
26
+ }
27
+
28
+ struct PointJacobianT {
29
+ vec3 point;
30
+ mat3 jacobianT;
31
+ };
@@ -0,0 +1,33 @@
1
+ //This file is automatically rebuilt by the Cesium build process.
2
+ export default "struct Ray {\n\
3
+ vec3 pos;\n\
4
+ vec3 dir;\n\
5
+ vec3 rawDir;\n\
6
+ };\n\
7
+ \n\
8
+ #if defined(JITTER)\n\
9
+ /**\n\
10
+ * Generate a pseudo-random value for a given 2D screen coordinate.\n\
11
+ * Similar to https://www.shadertoy.com/view/4djSRW with a modified hashscale.\n\
12
+ */\n\
13
+ float hash(vec2 p)\n\
14
+ {\n\
15
+ vec3 p3 = fract(vec3(p.xyx) * 50.0);\n\
16
+ p3 += dot(p3, p3.yzx + 19.19);\n\
17
+ return fract((p3.x + p3.y) * p3.z);\n\
18
+ }\n\
19
+ #endif\n\
20
+ \n\
21
+ float minComponent(in vec3 v) {\n\
22
+ return min(min(v.x, v.y), v.z);\n\
23
+ }\n\
24
+ \n\
25
+ float maxComponent(in vec3 v) {\n\
26
+ return max(max(v.x, v.y), v.z);\n\
27
+ }\n\
28
+ \n\
29
+ struct PointJacobianT {\n\
30
+ vec3 point;\n\
31
+ mat3 jacobianT;\n\
32
+ };\n\
33
+ ";