itowns 2.45.1-next.0 → 2.45.1-next.1

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 (185) hide show
  1. package/dist/455.js +2 -0
  2. package/dist/455.js.map +1 -0
  3. package/dist/debug.js +3 -0
  4. package/dist/debug.js.LICENSE.txt +13 -0
  5. package/dist/debug.js.map +1 -0
  6. package/dist/itowns.js +3 -0
  7. package/dist/itowns.js.LICENSE.txt +5 -0
  8. package/dist/itowns.js.map +1 -0
  9. package/dist/itowns_lasparser.js +2 -0
  10. package/dist/itowns_lasparser.js.map +1 -0
  11. package/dist/itowns_lasworker.js +2 -0
  12. package/dist/itowns_lasworker.js.map +1 -0
  13. package/dist/itowns_potree2worker.js +2 -0
  14. package/dist/itowns_potree2worker.js.map +1 -0
  15. package/dist/itowns_widgets.js +2 -0
  16. package/dist/itowns_widgets.js.map +1 -0
  17. package/lib/Controls/FirstPersonControls.js +308 -0
  18. package/lib/Controls/FlyControls.js +175 -0
  19. package/lib/Controls/GlobeControls.js +1178 -0
  20. package/lib/Controls/PlanarControls.js +1025 -0
  21. package/lib/Controls/StateControl.js +432 -0
  22. package/lib/Controls/StreetControls.js +392 -0
  23. package/lib/Converter/Feature2Mesh.js +612 -0
  24. package/lib/Converter/Feature2Texture.js +174 -0
  25. package/lib/Converter/convertToTile.js +70 -0
  26. package/lib/Converter/textureConverter.js +43 -0
  27. package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
  28. package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
  29. package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
  30. package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
  31. package/lib/Core/3DTiles/C3DTFeature.js +110 -0
  32. package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
  33. package/lib/Core/3DTiles/C3DTileset.js +99 -0
  34. package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
  35. package/lib/Core/AnimationPlayer.js +142 -0
  36. package/lib/Core/CopcNode.js +174 -0
  37. package/lib/Core/Deprecated/Undeprecator.js +74 -0
  38. package/lib/Core/EntwinePointTileNode.js +126 -0
  39. package/lib/Core/Feature.js +488 -0
  40. package/lib/Core/Geographic/GeoidGrid.js +108 -0
  41. package/lib/Core/Label.js +222 -0
  42. package/lib/Core/MainLoop.js +209 -0
  43. package/lib/Core/Picking.js +255 -0
  44. package/lib/Core/PointCloudNode.js +42 -0
  45. package/lib/Core/Potree2Node.js +206 -0
  46. package/lib/Core/Potree2PointAttributes.js +139 -0
  47. package/lib/Core/PotreeNode.js +101 -0
  48. package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
  49. package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
  50. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
  51. package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
  52. package/lib/Core/Prefab/GlobeView.js +155 -0
  53. package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
  54. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
  55. package/lib/Core/Prefab/PlanarView.js +62 -0
  56. package/lib/Core/Prefab/TileBuilder.js +82 -0
  57. package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
  58. package/lib/Core/Scheduler/Cache.js +17 -0
  59. package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
  60. package/lib/Core/Scheduler/Scheduler.js +294 -0
  61. package/lib/Core/Style.js +660 -0
  62. package/lib/Core/StyleOptions.js +486 -0
  63. package/lib/Core/System/Capabilities.js +63 -0
  64. package/lib/Core/Tile/Tile.js +205 -0
  65. package/lib/Core/Tile/TileGrid.js +49 -0
  66. package/lib/Core/TileGeometry.js +124 -0
  67. package/lib/Core/TileMesh.js +108 -0
  68. package/lib/Core/View.js +1115 -0
  69. package/lib/Layer/C3DTilesLayer.js +459 -0
  70. package/lib/Layer/ColorLayer.js +154 -0
  71. package/lib/Layer/CopcLayer.js +63 -0
  72. package/lib/Layer/ElevationLayer.js +139 -0
  73. package/lib/Layer/EntwinePointTileLayer.js +71 -0
  74. package/lib/Layer/FeatureGeometryLayer.js +77 -0
  75. package/lib/Layer/GeoidLayer.js +80 -0
  76. package/lib/Layer/GeometryLayer.js +233 -0
  77. package/lib/Layer/InfoLayer.js +64 -0
  78. package/lib/Layer/LabelLayer.js +469 -0
  79. package/lib/Layer/Layer.js +335 -0
  80. package/lib/Layer/LayerUpdateState.js +89 -0
  81. package/lib/Layer/LayerUpdateStrategy.js +80 -0
  82. package/lib/Layer/OGC3DTilesLayer.js +543 -0
  83. package/lib/Layer/OrientedImageLayer.js +227 -0
  84. package/lib/Layer/PointCloudLayer.js +405 -0
  85. package/lib/Layer/Potree2Layer.js +171 -0
  86. package/lib/Layer/PotreeLayer.js +72 -0
  87. package/lib/Layer/RasterLayer.js +37 -0
  88. package/lib/Layer/ReferencingLayerProperties.js +62 -0
  89. package/lib/Layer/TiledGeometryLayer.js +459 -0
  90. package/lib/Loader/LASLoader.js +193 -0
  91. package/lib/Loader/Potree2BrotliLoader.js +261 -0
  92. package/lib/Loader/Potree2Loader.js +207 -0
  93. package/lib/Main.js +113 -0
  94. package/lib/MainBundle.js +4 -0
  95. package/lib/Parser/B3dmParser.js +174 -0
  96. package/lib/Parser/CameraCalibrationParser.js +94 -0
  97. package/lib/Parser/GDFParser.js +72 -0
  98. package/lib/Parser/GTXParser.js +75 -0
  99. package/lib/Parser/GeoJsonParser.js +212 -0
  100. package/lib/Parser/GpxParser.js +25 -0
  101. package/lib/Parser/ISGParser.js +71 -0
  102. package/lib/Parser/KMLParser.js +25 -0
  103. package/lib/Parser/LASParser.js +137 -0
  104. package/lib/Parser/MapBoxUrlParser.js +83 -0
  105. package/lib/Parser/PntsParser.js +131 -0
  106. package/lib/Parser/Potree2BinParser.js +92 -0
  107. package/lib/Parser/PotreeBinParser.js +106 -0
  108. package/lib/Parser/PotreeCinParser.js +29 -0
  109. package/lib/Parser/ShapefileParser.js +78 -0
  110. package/lib/Parser/VectorTileParser.js +215 -0
  111. package/lib/Parser/XbilParser.js +120 -0
  112. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
  113. package/lib/Parser/iGLTFLoader.js +168 -0
  114. package/lib/Process/3dTilesProcessing.js +304 -0
  115. package/lib/Process/FeatureProcessing.js +76 -0
  116. package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
  117. package/lib/Process/ObjectRemovalHelper.js +97 -0
  118. package/lib/Process/handlerNodeError.js +23 -0
  119. package/lib/Provider/3dTilesProvider.js +149 -0
  120. package/lib/Provider/DataSourceProvider.js +24 -0
  121. package/lib/Provider/Fetcher.js +233 -0
  122. package/lib/Provider/PointCloudProvider.js +45 -0
  123. package/lib/Provider/TileProvider.js +16 -0
  124. package/lib/Provider/URLBuilder.js +116 -0
  125. package/lib/Renderer/Camera.js +281 -0
  126. package/lib/Renderer/Color.js +56 -0
  127. package/lib/Renderer/ColorLayersOrdering.js +115 -0
  128. package/lib/Renderer/CommonMaterial.js +31 -0
  129. package/lib/Renderer/Label2DRenderer.js +192 -0
  130. package/lib/Renderer/LayeredMaterial.js +243 -0
  131. package/lib/Renderer/OBB.js +150 -0
  132. package/lib/Renderer/OrientedImageCamera.js +118 -0
  133. package/lib/Renderer/OrientedImageMaterial.js +167 -0
  134. package/lib/Renderer/PointsMaterial.js +485 -0
  135. package/lib/Renderer/RasterTile.js +243 -0
  136. package/lib/Renderer/RenderMode.js +31 -0
  137. package/lib/Renderer/Shader/ShaderChunk.js +160 -0
  138. package/lib/Renderer/Shader/ShaderUtils.js +47 -0
  139. package/lib/Renderer/SphereHelper.js +17 -0
  140. package/lib/Renderer/WebXR.js +51 -0
  141. package/lib/Renderer/c3DEngine.js +214 -0
  142. package/lib/Source/C3DTilesGoogleSource.js +74 -0
  143. package/lib/Source/C3DTilesIonSource.js +54 -0
  144. package/lib/Source/C3DTilesSource.js +30 -0
  145. package/lib/Source/CopcSource.js +126 -0
  146. package/lib/Source/EntwinePointTileSource.js +72 -0
  147. package/lib/Source/FileSource.js +188 -0
  148. package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
  149. package/lib/Source/OGC3DTilesIonSource.js +34 -0
  150. package/lib/Source/OGC3DTilesSource.js +21 -0
  151. package/lib/Source/OrientedImageSource.js +59 -0
  152. package/lib/Source/Potree2Source.js +167 -0
  153. package/lib/Source/PotreeSource.js +82 -0
  154. package/lib/Source/Source.js +202 -0
  155. package/lib/Source/TMSSource.js +144 -0
  156. package/lib/Source/VectorTilesSource.js +182 -0
  157. package/lib/Source/WFSSource.js +170 -0
  158. package/lib/Source/WMSSource.js +167 -0
  159. package/lib/Source/WMTSSource.js +92 -0
  160. package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
  161. package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
  162. package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
  163. package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
  164. package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
  165. package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
  166. package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
  167. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  168. package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
  169. package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
  170. package/lib/Utils/CameraUtils.js +554 -0
  171. package/lib/Utils/DEMUtils.js +350 -0
  172. package/lib/Utils/FeaturesUtils.js +156 -0
  173. package/lib/Utils/Gradients.js +16 -0
  174. package/lib/Utils/ThreeUtils.js +115 -0
  175. package/lib/Utils/gui/C3DTilesStyle.js +218 -0
  176. package/lib/Utils/gui/Main.js +7 -0
  177. package/lib/Utils/gui/Minimap.js +152 -0
  178. package/lib/Utils/gui/Navigation.js +245 -0
  179. package/lib/Utils/gui/Scale.js +104 -0
  180. package/lib/Utils/gui/Searchbar.js +234 -0
  181. package/lib/Utils/gui/Widget.js +80 -0
  182. package/lib/Utils/placeObjectOnGround.js +136 -0
  183. package/lib/Worker/LASLoaderWorker.js +19 -0
  184. package/lib/Worker/Potree2Worker.js +21 -0
  185. package/package.json +2 -2
@@ -0,0 +1,293 @@
1
+ import * as THREE from 'three';
2
+ import GeometryLayer from "../../../Layer/GeometryLayer.js";
3
+ import { Coordinates, ellipsoidSizes, CoordStars } from '@itowns/geographic';
4
+ import Sky from "./SkyShader.js";
5
+ /* babel-plugin-inline-import './Shaders/skyFS.glsl' */
6
+ const skyFS = "uniform vec3 v3LightPos;\nuniform float g;\nuniform float g2;\n\nvarying vec3 v3Direction;\nvarying vec3 c0;\nvarying vec3 c1;\n\n// Calculates the Mie phase function\nfloat getMiePhase(float fCos, float fCos2, float g, float g2) {\n return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0 * g * fCos, 1.5);\n}\n\n// Calculates the Rayleigh phase function\nfloat getRayleighPhase(float fCos2) {\n return 0.75 + 0.75 * fCos2;\n}\n\nvoid main (void) {\n float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);\n float fCos2 = fCos * fCos;\n\n vec3 color = getRayleighPhase(fCos2) * c0 + getMiePhase(fCos, fCos2, g, g2) * c1;\n\n gl_FragColor = vec4(color, 1.0);\n gl_FragColor.a = gl_FragColor.b;\n}";
7
+ /* babel-plugin-inline-import './Shaders/skyVS.glsl' */
8
+ const skyVS = "uniform vec3 v3LightPosition; // The direction vector to the light source\nuniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels\nuniform float fCameraHeight; // The camera's current height\nuniform float fCameraHeight2; // fCameraHeight^2\nuniform float fOuterRadius; // The outer (atmosphere) radius\nuniform float fOuterRadius2; // fOuterRadius^2\nuniform float fInnerRadius; // The inner (planetary) radius\nuniform float fInnerRadius2; // fInnerRadius^2\nuniform float fKrESun; // Kr * ESun\nuniform float fKmESun; // Km * ESun\nuniform float fKr4PI; // Kr * 4 * PI\nuniform float fKm4PI; // Km * 4 * PI\nuniform float fScale; // 1 / (fOuterRadius - fInnerRadius)\nuniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)\nuniform float fScaleOverScaleDepth; // fScale / fScaleDepth\n\nconst int nSamples = 3;\nconst float fSamples = 3.0;\n\nvarying vec3 v3Direction;\nvarying vec3 c0;\nvarying vec3 c1;\n\nfloat scale(float fCos) {\n float x = 1.0 - fCos;\n return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));\n}\n\nvoid main(void) {\n float lengthCamera = length(cameraPosition);\n float cameraHeight2 = lengthCamera * lengthCamera;\n\n // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)\n vec3 v3Ray = position - cameraPosition;\n float fFar = length(v3Ray);\n v3Ray /= fFar;\n\n // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)\n float B = 2.0 * dot(cameraPosition, v3Ray);\n float C = cameraHeight2 - fOuterRadius2;\n float fDet = max(0.0, B*B - 4.0 * C);\n float fNear = 0.5 * (-B - sqrt(fDet));\n\n // Calculate the ray's starting position, then calculate its scattering offset\n vec3 v3Start = cameraPosition + v3Ray * fNear;\n fFar -= fNear;\n float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;\n float fStartDepth = exp(-1.0 / fScaleDepth);\n float fStartOffset = fStartDepth * scale(fStartAngle);\n\n // Initialize the scattering loop variables\n float fSampleLength = fFar / fSamples;\n float fScaledLength = fSampleLength * fScale;\n vec3 v3SampleRay = v3Ray * fSampleLength;\n vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;\n\n // Now loop through the sample rays\n vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);\n for(int i=0; i<nSamples; i++)\n {\n float fHeight = length(v3SamplePoint);\n float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));\n float fLightAngle = dot(v3LightPosition, v3SamplePoint) / fHeight;\n float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;\n float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));\n vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));\n\n v3FrontColor += v3Attenuate * (fDepth * fScaledLength);\n v3SamplePoint += v3SampleRay;\n }\n\n // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n c0 = v3FrontColor * (v3InvWavelength * fKrESun);\n c1 = v3FrontColor * fKmESun;\n v3Direction = cameraPosition - position;\n}";
9
+ /* babel-plugin-inline-import './Shaders/groundFS.glsl' */
10
+ const groundFS = "varying vec3 c0;\nvarying vec3 c1;\n\nvoid main (void) {\n\tgl_FragColor = vec4(c1, 1.0 - c0/4.);\n}";
11
+ /* babel-plugin-inline-import './Shaders/groundVS.glsl' */
12
+ const groundVS = "uniform vec3 v3LightPosition; // The direction vector to the light source\nuniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels\nuniform float fCameraHeight; // The camera's current height\nuniform float fCameraHeight2; // fCameraHeight^2\nuniform float fOuterRadius; // The outer (atmosphere) radius\nuniform float fOuterRadius2; // fOuterRadius^2\nuniform float fInnerRadius; // The inner (planetary) radius\nuniform float fInnerRadius2; // fInnerRadius^2\nuniform float fKrESun; // Kr * ESun\nuniform float fKmESun; // Km * ESun\nuniform float fKr4PI; // Kr * 4 * PI\nuniform float fKm4PI; // Km * 4 * PI\nuniform float fScale; // 1 / (fOuterRadius - fInnerRadius)\nuniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)\nuniform float fScaleOverScaleDepth; // fScale / fScaleDepth\n\nvarying vec3 c0;\nvarying vec3 c1;\n\nconst int nSamples = 3;\nconst float fSamples = 3.0;\n\nfloat scale(float fCos)\n{\n float x = 1.0 - fCos;\n return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));\n}\n\nvoid main(void) {\n\n float cameraHeight2 = length(cameraPosition) * length(cameraPosition);\n\n // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)\n vec3 v3Ray = position - cameraPosition;\n float fFar = length(v3Ray);\n v3Ray /= fFar;\n\n // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)\n float B = 2.0 * dot(cameraPosition, v3Ray);\n float C = cameraHeight2 - fOuterRadius2;\n float fDet = max(0.0, B*B - 4.0 * C);\n float fNear = 0.5 * (-B - sqrt(fDet));\n\n // Calculate the ray's starting position, then calculate its scattering offset\n vec3 v3Start = cameraPosition + v3Ray * fNear;\n fFar -= fNear;\n float fDepth = exp((fInnerRadius - fOuterRadius) / fScaleDepth);\n float fCameraAngle = dot(-v3Ray, position) / length(position);\n float fLightAngle = dot(v3LightPosition, position) / length(position);\n float fCameraScale = scale(fCameraAngle);\n float fLightScale = scale(fLightAngle);\n float fCameraOffset = fDepth*fCameraScale;\n float fTemp = (fLightScale + fCameraScale);\n\n // Initialize the scattering loop variables\n float fSampleLength = fFar / fSamples;\n float fScaledLength = fSampleLength * fScale;\n vec3 v3SampleRay = v3Ray * fSampleLength;\n vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;\n\n // Now loop through the sample rays\n vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);\n vec3 v3Attenuate = vec3(0.0, 0.0, 0.0);\n for(int i=0; i<nSamples; i++)\n {\n float fHeight = length(v3SamplePoint);\n float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));\n float fScatter = fDepth*fTemp - fCameraOffset;\n v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));\n v3FrontColor += v3Attenuate * (fDepth * fScaledLength);\n v3SamplePoint += v3SampleRay;\n }\n\n // Calculate the attenuation factor for the ground\n c0 = v3Attenuate;\n c1 = v3FrontColor * (v3InvWavelength * fKrESun + fKmESun);\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
13
+ /* babel-plugin-inline-import './Shaders/GlowFS.glsl' */
14
+ const GlowFS = "#include <logdepthbuf_pars_fragment>\n\nuniform int atmoIN;\nvarying float intensity;\n\nvec4 glowColor = vec4(0.45, 0.74, 1. ,1.0);\n\nvoid main() {\n #include <logdepthbuf_fragment>\n gl_FragColor = glowColor * intensity;\n}\n\n";
15
+ /* babel-plugin-inline-import './Shaders/GlowVS.glsl' */
16
+ const GlowVS = "#include <common>\n#include <logdepthbuf_pars_vertex>\n\nuniform int atmoIN;\nvarying float intensity;\n\nvoid main()\n{\n vec3 normalES = normalize( normalMatrix * normal );\n vec3 normalCAMES = normalize( normalMatrix * cameraPosition );\n\n if(atmoIN == 0) {\n intensity = pow(0.666 - dot(normalES, normalCAMES), 4. );\n } else {\n intensity = pow( 1. - dot(normalES, normalCAMES), 0.8 );\n }\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n #include <logdepthbuf_vertex>\n}\n\n\n";
17
+ const LIGHTING_POSITION = new THREE.Vector3(1, 0, 0);
18
+ const v = new THREE.Vector3();
19
+ const coordCam = new Coordinates('EPSG:4326');
20
+ const coordGeoCam = new Coordinates('EPSG:4326');
21
+ const skyBaseColor = new THREE.Color(0x93d5f8);
22
+ const colorSky = new THREE.Color();
23
+ const spaceColor = new THREE.Color(0x030508);
24
+ const limitAlti = 600000;
25
+ const mfogDistance = ellipsoidSizes.x * 160.0;
26
+
27
+ /**
28
+ * @extends GeometryLayer
29
+ */
30
+ class Atmosphere extends GeometryLayer {
31
+ /**
32
+ * It's layer to simulate Globe atmosphere.
33
+ * There's 2 modes : simple and realistic (atmospheric-scattering).
34
+ *
35
+ * The atmospheric-scattering it is taken from :
36
+ * * [Atmosphere Shader From Space (Atmospheric scattering)](http://stainlessbeer.weebly.com/planets-9-atmospheric-scattering.html)
37
+ * * [Accurate Atmospheric Scattering (NVIDIA GPU Gems 2)](https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering).
38
+ *
39
+ * @param {string} id - The id of the layer Atmosphere.
40
+ * @param {Object} [options] - options layer.
41
+ * @param {number} [options.Kr] - `Kr` is the rayleigh scattering constant.
42
+ * @param {number} [options.Km] - `Km` is the Mie scattering constant.
43
+ * @param {number} [options.ESun] - `ESun` is the brightness of the sun.
44
+ * @param {number} [options.g] - constant `g` that affects the symmetry of the scattering.
45
+ * @param {number} [options.innerRadius] - The inner (planetary) radius
46
+ * @param {number} [options.outerRadius] - The outer (Atmosphere) radius
47
+ * @param {number[]} [options.wavelength] - The constant is the `wavelength` (or color) of light.
48
+ * @param {number} [options.scaleDepth] - The `scale depth` (i.e. the altitude at which the atmosphere's average density is found).
49
+ * @param {number} [options.mieScaleDepth] - not used.
50
+ */
51
+ constructor() {
52
+ let id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'atmosphere';
53
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
54
+ options.source = false;
55
+ super(id, new THREE.Object3D(), options);
56
+ this.isAtmosphere = true;
57
+ const material = new THREE.ShaderMaterial({
58
+ uniforms: {
59
+ atmoIN: {
60
+ type: 'i',
61
+ value: 0
62
+ },
63
+ screenSize: {
64
+ type: 'v2',
65
+ value: new THREE.Vector2(window.innerWidth, window.innerHeight)
66
+ } // Should be updated on screen resize...
67
+ },
68
+ vertexShader: GlowVS,
69
+ fragmentShader: GlowFS,
70
+ side: THREE.BackSide,
71
+ blending: THREE.AdditiveBlending,
72
+ transparent: true,
73
+ wireframe: false
74
+ });
75
+ const sphereGeometry = new THREE.SphereGeometry(1, 64, 64);
76
+ const basicAtmosphereOut = new THREE.Mesh(sphereGeometry, material);
77
+ basicAtmosphereOut.scale.copy(ellipsoidSizes).multiplyScalar(1.14);
78
+ this.basicAtmosphere = new THREE.Object3D();
79
+ this.realisticAtmosphere = new THREE.Object3D();
80
+ this.realisticAtmosphere.visible = false;
81
+ this.object3d.add(this.basicAtmosphere);
82
+ this.object3d.add(this.realisticAtmosphere);
83
+ this.basicAtmosphere.add(basicAtmosphereOut);
84
+ const materialAtmoIn = new THREE.ShaderMaterial({
85
+ uniforms: {
86
+ atmoIN: {
87
+ type: 'i',
88
+ value: 1
89
+ },
90
+ screenSize: {
91
+ type: 'v2',
92
+ value: new THREE.Vector2(window.innerWidth, window.innerHeight)
93
+ } // Should be updated on screen resize...
94
+ },
95
+ vertexShader: GlowVS,
96
+ fragmentShader: GlowFS,
97
+ side: THREE.FrontSide,
98
+ blending: THREE.AdditiveBlending,
99
+ transparent: true,
100
+ depthWrite: false
101
+ });
102
+ const basicAtmosphereIn = new THREE.Mesh(sphereGeometry, materialAtmoIn);
103
+ basicAtmosphereIn.scale.copy(ellipsoidSizes).multiplyScalar(1.002);
104
+ this.basicAtmosphere.add(basicAtmosphereIn);
105
+ this.realisticLightingPosition = {
106
+ x: -0.5,
107
+ y: 0.0,
108
+ z: 1.0
109
+ };
110
+ this.fog = {
111
+ enable: true,
112
+ distance: mfogDistance
113
+ };
114
+
115
+ // Atmosphere Shader From Space (Atmospheric scattering)
116
+ // http://stainlessbeer.weebly.com/planets-9-atmospheric-scattering.html
117
+ // https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering
118
+ this.realisticAtmosphereInitParams = options.Kr ? options : {
119
+ Kr: 0.0025,
120
+ Km: 0.0015,
121
+ ESun: 20.0,
122
+ g: -0.950,
123
+ innerRadius: 6400000,
124
+ outerRadius: 6700000,
125
+ wavelength: [0.650, 0.570, 0.475],
126
+ scaleDepth: 0.25
127
+ // mieScaleDepth: 0.1,
128
+ };
129
+ this.object3d.updateMatrixWorld();
130
+ }
131
+ update(context, layer, node) {
132
+ // update uniforms
133
+ node.material.fogDistance = this.fog.distance;
134
+ node.material.lightingEnabled = this.realisticAtmosphere.visible;
135
+ node.material.lightPosition = this.realisticLightingPosition;
136
+ }
137
+
138
+ // eslint-disable-next-line no-unused-vars
139
+ preUpdate(context) {
140
+ const cameraPosition = context.view.camera3D.position;
141
+ if (this.fog.enable) {
142
+ v.setFromMatrixPosition(context.view.tileLayer.object3d.matrixWorld);
143
+ const len = v.distanceTo(cameraPosition);
144
+ // Compute fog distance, this function makes it possible to have a shorter distance
145
+ // when the camera approaches the ground
146
+ this.fog.distance = mfogDistance * ((len - ellipsoidSizes.x * 0.99) * 0.25 / ellipsoidSizes.x) ** 1.5;
147
+ } else {
148
+ this.fog.distance = 10e10;
149
+ }
150
+ const renderer = context.view.mainLoop.gfxEngine.renderer;
151
+ // get altitude camera
152
+ coordCam.crs = context.view.referenceCrs;
153
+ coordCam.setFromVector3(cameraPosition).as('EPSG:4326', coordGeoCam);
154
+ const altitude = coordGeoCam.altitude;
155
+
156
+ // If the camera altitude is below limitAlti,
157
+ // we interpolate between the sky color and the space color
158
+ if (altitude < limitAlti) {
159
+ colorSky.copy(spaceColor).lerp(skyBaseColor, (limitAlti - altitude) / limitAlti);
160
+ renderer.setClearColor(colorSky, renderer.getClearAlpha());
161
+ } else {
162
+ renderer.setClearColor(spaceColor, renderer.getClearAlpha());
163
+ }
164
+ }
165
+
166
+ // default to non-realistic lightning
167
+ _initRealisticLighning() {
168
+ const atmosphere = this.realisticAtmosphereInitParams;
169
+ const uniformsAtmosphere = {
170
+ v3LightPosition: {
171
+ value: LIGHTING_POSITION.clone().normalize()
172
+ },
173
+ v3InvWavelength: {
174
+ value: new THREE.Vector3(1 / atmosphere.wavelength[0] ** 4, 1 / atmosphere.wavelength[1] ** 4, 1 / atmosphere.wavelength[2] ** 4)
175
+ },
176
+ fCameraHeight: {
177
+ value: 0.0
178
+ },
179
+ fCameraHeight2: {
180
+ value: 0.0
181
+ },
182
+ fInnerRadius: {
183
+ value: atmosphere.innerRadius
184
+ },
185
+ fInnerRadius2: {
186
+ value: atmosphere.innerRadius * atmosphere.innerRadius
187
+ },
188
+ fOuterRadius: {
189
+ value: atmosphere.outerRadius
190
+ },
191
+ fOuterRadius2: {
192
+ value: atmosphere.outerRadius * atmosphere.outerRadius
193
+ },
194
+ fKrESun: {
195
+ value: atmosphere.Kr * atmosphere.ESun
196
+ },
197
+ fKmESun: {
198
+ value: atmosphere.Km * atmosphere.ESun
199
+ },
200
+ fKr4PI: {
201
+ value: atmosphere.Kr * 4.0 * Math.PI
202
+ },
203
+ fKm4PI: {
204
+ value: atmosphere.Km * 4.0 * Math.PI
205
+ },
206
+ fScale: {
207
+ value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius)
208
+ },
209
+ fScaleDepth: {
210
+ value: atmosphere.scaleDepth
211
+ },
212
+ fScaleOverScaleDepth: {
213
+ value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) / atmosphere.scaleDepth
214
+ },
215
+ g: {
216
+ value: atmosphere.g
217
+ },
218
+ g2: {
219
+ value: atmosphere.g * atmosphere.g
220
+ },
221
+ nSamples: {
222
+ value: 3
223
+ },
224
+ fSamples: {
225
+ value: 3.0
226
+ },
227
+ tDisplacement: {
228
+ value: new THREE.Texture()
229
+ },
230
+ tSkyboxDiffuse: {
231
+ value: new THREE.Texture()
232
+ },
233
+ fNightScale: {
234
+ value: 1.0
235
+ }
236
+ };
237
+ const geometryAtmosphereIn = new THREE.SphereGeometry(atmosphere.innerRadius, 50, 50);
238
+ const materialAtmosphereIn = new THREE.ShaderMaterial({
239
+ uniforms: uniformsAtmosphere,
240
+ vertexShader: groundVS,
241
+ fragmentShader: groundFS,
242
+ blending: THREE.AdditiveBlending,
243
+ transparent: true,
244
+ depthTest: false,
245
+ depthWrite: false
246
+ });
247
+ const ground = new THREE.Mesh(geometryAtmosphereIn, materialAtmosphereIn);
248
+ const geometryAtmosphereOut = new THREE.SphereGeometry(atmosphere.outerRadius, 196, 196);
249
+ const materialAtmosphereOut = new THREE.ShaderMaterial({
250
+ uniforms: uniformsAtmosphere,
251
+ vertexShader: skyVS,
252
+ fragmentShader: skyFS,
253
+ transparent: true,
254
+ side: THREE.BackSide
255
+ });
256
+ const sky = new THREE.Mesh(geometryAtmosphereOut, materialAtmosphereOut);
257
+ const skyDome = new Sky();
258
+ skyDome.frustumCulled = false;
259
+ this.realisticAtmosphere.add(ground);
260
+ this.realisticAtmosphere.add(sky);
261
+ this.realisticAtmosphere.add(skyDome);
262
+ const effectController = {
263
+ turbidity: 10,
264
+ reileigh: 2,
265
+ mieCoefficient: 0.005,
266
+ mieDirectionalG: 0.8,
267
+ luminance: 1,
268
+ inclination: 0.49,
269
+ // elevation / inclination
270
+ azimuth: 0.25,
271
+ // Facing front,
272
+ sun: !true
273
+ };
274
+ skyDome.material.uniforms.turbidity.value = effectController.turbidity;
275
+ skyDome.material.uniforms.reileigh.value = effectController.reileigh;
276
+ skyDome.material.uniforms.luminance.value = effectController.luminance;
277
+ skyDome.material.uniforms.mieCoefficient.value = effectController.mieCoefficient;
278
+ skyDome.material.uniforms.mieDirectionalG.value = effectController.mieDirectionalG;
279
+ skyDome.material.uniforms.up.value = new THREE.Vector3(); // no more necessary, estimate normal from cam..
280
+ }
281
+ setRealisticOn(bool) {
282
+ if (bool) {
283
+ if (!this.realisticAtmosphere.children.length) {
284
+ this._initRealisticLighning();
285
+ }
286
+ this.realisticLightingPosition = CoordStars.getSunPositionInScene(new Date().getTime(), 48.85, 2.35).normalize();
287
+ this.realisticAtmosphere.children.forEach(obj => obj.material.uniforms.v3LightPosition.value.copy(this.realisticLightingPosition));
288
+ }
289
+ this.basicAtmosphere.visible = !bool;
290
+ this.realisticAtmosphere.visible = bool;
291
+ }
292
+ }
293
+ export default Atmosphere;
@@ -0,0 +1,152 @@
1
+ import * as THREE from 'three';
2
+ import TiledGeometryLayer from "../../../Layer/TiledGeometryLayer.js";
3
+ import { ellipsoidSizes } from '@itowns/geographic';
4
+ import { globalExtentTMS, schemeTiles } from "../../Tile/TileGrid.js";
5
+ import { GlobeTileBuilder } from "./GlobeTileBuilder.js";
6
+
7
+ // matrix to convert sphere to ellipsoid
8
+ const worldToScaledEllipsoid = new THREE.Matrix4();
9
+ // camera's position in worldToScaledEllipsoid system
10
+ const cameraPosition = new THREE.Vector3();
11
+ let magnitudeSquared = 0.0;
12
+
13
+ // vectors for operation purpose
14
+ const scaledHorizonCullingPoint = new THREE.Vector3();
15
+
16
+ /**
17
+ * @property {boolean} isGlobeLayer - Used to checkout whether this layer is a
18
+ * GlobeLayer. Default is true. You should not change this, as it is used
19
+ * internally for optimisation.
20
+ *
21
+ * @extends TiledGeometryLayer
22
+ */
23
+ class GlobeLayer extends TiledGeometryLayer {
24
+ /**
25
+ * A {@link TiledGeometryLayer} to use with a {@link GlobeView}. It has
26
+ * specific method for updating and subdivising its grid.
27
+ *
28
+ * @param {string} id - The id of the layer, that should be unique. It is
29
+ * not mandatory, but an error will be emitted if this layer is added a
30
+ * {@link View} that already has a layer going by that id.
31
+ * @param {THREE.Object3D} [object3d=THREE.Group] - The object3d used to
32
+ * contain the geometry of the TiledGeometryLayer. It is usually a
33
+ * `THREE.Group`, but it can be anything inheriting from a `THREE.Object3d`.
34
+ * @param {Object} [config] - Optional configuration, all elements in it
35
+ * will be merged as is in the layer. For example, if the configuration
36
+ * contains three elements `name, protocol, extent`, these elements will be
37
+ * available using `layer.name` or something else depending on the property
38
+ * name.
39
+ * @param {number} [config.minSubdivisionLevel=2] - Minimum subdivision
40
+ * level for this tiled layer.
41
+ * @param {number} [config.maxSubdivisionLevel=18] - Maximum subdivision
42
+ * level for this tiled layer.
43
+ * @param {number} [config.sseSubdivisionThreshold=1] - Threshold level for
44
+ * the SSE.
45
+ *
46
+ * @throws {Error} `object3d` must be a valid `THREE.Object3d`.
47
+ */
48
+ constructor(id, object3d) {
49
+ let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
50
+ const {
51
+ minSubdivisionLevel = 2,
52
+ maxSubdivisionLevel = 19,
53
+ ...tiledConfig
54
+ } = config;
55
+
56
+ // Configure tiles
57
+ const scheme = schemeTiles.get('EPSG:4326');
58
+ const schemeTile = globalExtentTMS.get('EPSG:4326').subdivisionByScheme(scheme);
59
+
60
+ // Supported tile matrix set for color/elevation layer
61
+ const tileMatrixSets = ['EPSG:4326', 'EPSG:3857'];
62
+ const uvCount = tileMatrixSets.length;
63
+ const builder = new GlobeTileBuilder({
64
+ uvCount
65
+ });
66
+ super(id, object3d || new THREE.Group(), schemeTile, builder, {
67
+ tileMatrixSets,
68
+ ...tiledConfig
69
+ });
70
+ this.isGlobeLayer = true;
71
+ this.options.defaultPickingRadius = 5;
72
+ this.minSubdivisionLevel = minSubdivisionLevel;
73
+ this.maxSubdivisionLevel = maxSubdivisionLevel;
74
+ this.extent = this.schemeTile[0].clone();
75
+ for (let i = 1; i < this.schemeTile.length; i++) {
76
+ this.extent.union(this.schemeTile[i]);
77
+ }
78
+
79
+ // We're going to use the method described here:
80
+ // https://cesiumjs.org/2013/04/25/Horizon-culling/
81
+ // This method assumes that the globe is a unit sphere at 0,0,0 so
82
+ // we setup a world-to-scaled-ellipsoid matrix4
83
+ worldToScaledEllipsoid.copy(this.object3d.matrixWorld).invert();
84
+ worldToScaledEllipsoid.premultiply(new THREE.Matrix4().makeScale(1 / ellipsoidSizes.x, 1 / ellipsoidSizes.y, 1 / ellipsoidSizes.z));
85
+ }
86
+ preUpdate(context, changeSources) {
87
+ // pre-horizon culling
88
+ cameraPosition.copy(context.camera.camera3D.position).applyMatrix4(worldToScaledEllipsoid);
89
+ magnitudeSquared = cameraPosition.lengthSq() - 1.0;
90
+ return super.preUpdate(context, changeSources);
91
+ }
92
+ countColorLayersTextures() {
93
+ let occupancy = 0;
94
+ for (var _len = arguments.length, layers = new Array(_len), _key = 0; _key < _len; _key++) {
95
+ layers[_key] = arguments[_key];
96
+ }
97
+ for (const layer of layers) {
98
+ const crs = layer.crs || layer.source.crs;
99
+ // 'EPSG:3857' occupies the maximum 3 textures on tiles
100
+ // 'EPSG:4326' occupies 1 textures on tile
101
+ occupancy += crs == 'EPSG:3857' ? 3 : 1;
102
+ }
103
+ return occupancy;
104
+ }
105
+ subdivision(context, layer, node) {
106
+ if (node.level == 5) {
107
+ const row = node.getExtentsByProjection('EPSG:4326')[0].row;
108
+ if (row == 31 || row == 0) {
109
+ // doesn't subdivise the pole
110
+ return false;
111
+ }
112
+ }
113
+ return super.subdivision(context, layer, node);
114
+ }
115
+ culling(node, camera) {
116
+ if (super.culling(node, camera)) {
117
+ return true;
118
+ }
119
+ if (node.level < this.minSubdivisionLevel) {
120
+ return false;
121
+ }
122
+ return GlobeLayer.horizonCulling(node.horizonCullingPointElevationScaled);
123
+ }
124
+ static horizonCulling(point) {
125
+ // see https://cesiumjs.org/2013/04/25/Horizon-culling/
126
+ scaledHorizonCullingPoint.copy(point).applyMatrix4(worldToScaledEllipsoid);
127
+ scaledHorizonCullingPoint.sub(cameraPosition);
128
+ const vtMagnitudeSquared = scaledHorizonCullingPoint.lengthSq();
129
+ const dot = -scaledHorizonCullingPoint.dot(cameraPosition);
130
+ const isOccluded = magnitudeSquared < 0 ? dot > 0 : magnitudeSquared < dot && magnitudeSquared < dot * dot / vtMagnitudeSquared;
131
+ return isOccluded;
132
+ }
133
+ computeTileZoomFromDistanceCamera(distance, camera) {
134
+ const preSinus = this.sizeDiagonalTexture * (this.sseSubdivisionThreshold * 0.5) / camera._preSSE / ellipsoidSizes.x;
135
+ let sinus = distance * preSinus;
136
+ let zoom = Math.log(Math.PI / (2.0 * Math.asin(sinus))) / Math.log(2);
137
+ const delta = Math.PI / 2 ** zoom;
138
+ const circleChord = 2.0 * ellipsoidSizes.x * Math.sin(delta * 0.5);
139
+ // adjust with bounding sphere rayon
140
+ sinus = (distance - circleChord * 0.5) * preSinus;
141
+ zoom = Math.log(Math.PI / (2.0 * Math.asin(sinus))) / Math.log(2);
142
+ return isNaN(zoom) ? 0 : Math.round(zoom);
143
+ }
144
+ computeDistanceCameraFromTileZoom(zoom, camera) {
145
+ const delta = Math.PI / 2 ** zoom;
146
+ const circleChord = 2.0 * ellipsoidSizes.x * Math.sin(delta * 0.5);
147
+ const radius = circleChord * 0.5;
148
+ const error = radius / this.sizeDiagonalTexture;
149
+ return camera._preSSE * error / (this.sseSubdivisionThreshold * 0.5) + radius;
150
+ }
151
+ }
152
+ export default GlobeLayer;
@@ -0,0 +1,110 @@
1
+ import * as THREE from 'three';
2
+ import { Coordinates, Extent } from '@itowns/geographic';
3
+ const PI_OV_FOUR = Math.PI / 4;
4
+ const INV_TWO_PI = 1.0 / (Math.PI * 2);
5
+ const axisZ = new THREE.Vector3(0, 0, 1);
6
+ const axisY = new THREE.Vector3(0, 1, 0);
7
+ const quatToAlignLongitude = new THREE.Quaternion();
8
+ const quatToAlignLatitude = new THREE.Quaternion();
9
+ const quatNormalToZ = new THREE.Quaternion();
10
+
11
+ /** Transforms a WGS84 latitude into a usable texture offset. */
12
+ function WGS84ToOneSubY(latitude) {
13
+ return 1.0 - (0.5 - Math.log(Math.tan(PI_OV_FOUR + THREE.MathUtils.degToRad(latitude) * 0.5)) * INV_TWO_PI);
14
+ }
15
+
16
+ /** Specialized parameters for the [GlobeTileBuilder]. */
17
+
18
+ /**
19
+ * TileBuilder implementation for the purpose of generating globe (or more
20
+ * precisely ellipsoidal) tile arrangements.
21
+ */
22
+ export class GlobeTileBuilder {
23
+ static _crs = 'EPSG:4978';
24
+ static _computeExtraOffset(params) {
25
+ const t = WGS84ToOneSubY(params.coordinates.latitude) * params.nbRow;
26
+ return (!isFinite(t) ? 0 : t) - params.deltaUV1;
27
+ }
28
+
29
+ /**
30
+ * Buffer holding information about the tile/vertex currently being
31
+ * processed.
32
+ */
33
+
34
+ get crs() {
35
+ return GlobeTileBuilder._crs;
36
+ }
37
+ constructor(options) {
38
+ this._transform = {
39
+ coords: [new Coordinates('EPSG:4326', 0, 0), new Coordinates('EPSG:4326', 0, 0)],
40
+ position: new THREE.Vector3(),
41
+ dimension: new THREE.Vector2()
42
+ };
43
+
44
+ // UV: Normalized coordinates (from degree) on the entire tile
45
+ // EPSG:4326
46
+ // Offset: Float row coordinate from Pseudo mercator coordinates
47
+ // EPSG:3857
48
+ if (options.uvCount > 1) {
49
+ this.computeExtraOffset = GlobeTileBuilder._computeExtraOffset;
50
+ }
51
+ }
52
+ prepare(params) {
53
+ const nbRow = 2 ** (params.level + 1.0);
54
+ let st1 = WGS84ToOneSubY(params.extent.south);
55
+ if (!isFinite(st1)) {
56
+ st1 = 0;
57
+ }
58
+ const start = st1 % (1.0 / nbRow);
59
+ const newParams = {
60
+ nbRow,
61
+ deltaUV1: (st1 - start) * nbRow,
62
+ // transformation to align tile's normal to z axis
63
+ quatNormalToZ: quatNormalToZ.setFromAxisAngle(axisY, -(Math.PI * 0.5 - THREE.MathUtils.degToRad(params.extent.center().latitude))),
64
+ // let's avoid building too much temp objects
65
+ coordinates: new Coordinates(this.crs)
66
+ };
67
+ params.extent.planarDimensions(this._transform.dimension);
68
+ return {
69
+ ...params,
70
+ ...newParams
71
+ };
72
+ }
73
+ center(extent) {
74
+ return extent.center(this._transform.coords[0]).as(this.crs, this._transform.coords[1]).toVector3();
75
+ }
76
+ vertexPosition(coordinates) {
77
+ return this._transform.coords[0].setFromValues(coordinates.x, coordinates.y).as(this.crs, this._transform.coords[1]).toVector3(this._transform.position);
78
+ }
79
+ vertexNormal() {
80
+ return this._transform.coords[1].geodesicNormal;
81
+ }
82
+ uProject(u, extent) {
83
+ return extent.west + u * this._transform.dimension.x;
84
+ }
85
+ vProject(v, extent) {
86
+ return extent.south + v * this._transform.dimension.y;
87
+ }
88
+ computeShareableExtent(extent) {
89
+ // NOTE: It should be possible to take advantage of equatorial plane
90
+ // symmetry, for which we'd have to reverse the tile's UVs.
91
+ // This would halve the memory requirement when viewing a full globe,
92
+ // but that case is not that relevant for iTowns' usual use cases and
93
+ // the globe mesh memory usage is already inconsequential.
94
+ const sizeLongitude = Math.abs(extent.west - extent.east) / 2;
95
+ const shareableExtent = new Extent(extent.crs, -sizeLongitude, sizeLongitude, extent.south, extent.north);
96
+
97
+ // Compute rotation to transform the tile to position on the ellispoid.
98
+ // This transformation takes the parents' transformation into account.
99
+ const rotLon = THREE.MathUtils.degToRad(extent.west - shareableExtent.west);
100
+ const rotLat = THREE.MathUtils.degToRad(90 - extent.center(this._transform.coords[0]).latitude);
101
+ quatToAlignLongitude.setFromAxisAngle(axisZ, rotLon);
102
+ quatToAlignLatitude.setFromAxisAngle(axisY, rotLat);
103
+ quatToAlignLongitude.multiply(quatToAlignLatitude);
104
+ return {
105
+ shareableExtent,
106
+ quaternion: quatToAlignLongitude.clone(),
107
+ position: this.center(extent)
108
+ };
109
+ }
110
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @author zz85 / https://github.com/zz85
3
+ *
4
+ * Based on "A Practical Analytic Model for Daylight"
5
+ * aka The Preetham Model, the de facto standard analytic skydome model
6
+ * http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
7
+ *
8
+ * First implemented by Simon Wallner
9
+ * http://www.simonwallner.at/projects/atmospheric-scattering
10
+ *
11
+ * Improved by Martin Upitis
12
+ * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
13
+ *
14
+ * Three.js integration by zz85 http://twitter.com/blurspline
15
+ */
16
+
17
+ import * as THREE from 'three';
18
+ const skyShader = {
19
+ uniforms: {
20
+ luminance: {
21
+ type: 'f',
22
+ value: 1
23
+ },
24
+ turbidity: {
25
+ type: 'f',
26
+ value: 2
27
+ },
28
+ reileigh: {
29
+ type: 'f',
30
+ value: 1
31
+ },
32
+ mieCoefficient: {
33
+ type: 'f',
34
+ value: 0.005
35
+ },
36
+ mieDirectionalG: {
37
+ type: 'f',
38
+ value: 0.8
39
+ },
40
+ v3LightPosition: {
41
+ type: 'v3',
42
+ value: new THREE.Vector3()
43
+ },
44
+ up: {
45
+ type: 'v3',
46
+ value: new THREE.Vector3(0.0, 1.0, 0.0)
47
+ }
48
+ },
49
+ vertexShader: ['varying vec3 vWorldPosition;', 'void main() {', 'vec4 worldPosition = modelMatrix * vec4( cameraPosition + position, 1.0 );', 'vWorldPosition = worldPosition.xyz;', 'gl_Position = projectionMatrix * modelViewMatrix * vec4( cameraPosition + position, 1.0 );', '}'].join('\n'),
50
+ fragmentShader: ['uniform sampler2D skySampler;', 'uniform vec3 v3LightPosition;', 'uniform vec3 up;', 'varying vec3 vWorldPosition;',
51
+ // "vec3 cameraPos = cameraPosition; //vec3(0., 0., 0.);",
52
+ '// uniform sampler2D sDiffuse;', '// const float turbidity = 10.0; //', '// const float reileigh = 2.; //', '// const float luminance = 1.0; //', '// const float mieCoefficient = 0.005;', '// const float mieDirectionalG = 0.8;', 'uniform float luminance;', 'uniform float turbidity;', 'uniform float reileigh;', 'uniform float mieCoefficient;', 'uniform float mieDirectionalG;', '// constants for atmospheric scattering', 'const float e = 2.71828182845904523536028747135266249775724709369995957;', 'const float pi = 3.141592653589793238462643383279502884197169;', 'const float n = 1.0003; // refractive index of air', 'const float N = 2.545E25; // number of molecules per unit volume for air at', '// 288.15K and 1013mb (sea level -45 celsius)', 'const float pn = 0.035; // depolatization factor for standard air', '// wavelength of used primaries, according to preetham', 'const vec3 lambda = vec3(680E-9, 550E-9, 450E-9);', '// mie stuff', '// K coefficient for the primaries', 'const vec3 K = vec3(0.686, 0.678, 0.666);', 'const float v = 4.0;', '// optical length at zenith for molecules', 'const float rayleighZenithLength = 8.4E3;', 'const float mieZenithLength = 1.25E3;',
53
+ // "const vec3 up = vec3(0.0, 1.0, 0.0);",
54
+
55
+ 'const float EE = 1000.0;', 'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;', '// 66 arc seconds -> degrees, and the cosine of that', '// earth shadow hack', 'const float cutoffAngle = pi/1.95;', 'const float steepness = 1.5;', 'vec3 totalRayleigh(vec3 lambda)', '{', 'return (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn));', '}',
56
+ // see http://blenderartists.org/forum/showthread.php?321110-Shaders-and-Skybox-madness
57
+ '// A simplied version of the total Reayleigh scattering to works on browsers that use ANGLE', 'vec3 simplifiedRayleigh()', '{', 'return 0.0005 / vec3(94, 40, 18);',
58
+ // return 0.00054532832366 / (3.0 * 2.545E25 * pow(vec3(680E-9, 550E-9, 450E-9), vec3(4.0)) * 6.245);
59
+ '}', 'float rayleighPhase(float cosTheta)', '{ ', 'return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));', '// return (1.0 / (3.0*pi)) * (1.0 + pow(cosTheta, 2.0));', '// return (3.0 / 4.0) * (1.0 + pow(cosTheta, 2.0));', '}', 'vec3 totalMie(vec3 lambda, vec3 K, float T)', '{', 'float c = (0.2 * T ) * 10E-18;', 'return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;', '}', 'float hgPhase(float cosTheta, float g)', '{', 'return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(1.0 - 2.0*g*cosTheta + pow(g, 2.0), 1.5));', '}', 'float sunIntensity(float zenithAngleCos)', '{', 'return EE * max(0.0, 1.0 - exp(-((cutoffAngle - acos(zenithAngleCos))/steepness)));', '}', '// float logLuminance(vec3 c)', '// {', '// return log(c.r * 0.2126 + c.g * 0.7152 + c.b * 0.0722);', '// }', '// Filmic ToneMapping http://filmicgames.com/archives/75', 'float A = 0.15;', 'float B = 0.50;', 'float C = 0.10;', 'float D = 0.20;', 'float E = 0.02;', 'float F = 0.30;', 'float W = 1000.0;', 'vec3 Uncharted2Tonemap(vec3 x)', '{', 'return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;', '}', 'void main() ', '{', 'vec3 up2 = normalize(cameraPosition.xyz);', 'float sunfade = 1.0-clamp(1.0-exp((v3LightPosition.y/450000.0)),0.0,1.0);', 'float reileighCoefficient = reileigh - (1.0* (1.0-sunfade));', 'vec3 sunDirection = normalize(v3LightPosition);', 'float sunE = sunIntensity(dot(sunDirection, up2));', '// extinction (absorbtion + out scattering) ', '// rayleigh coefficients',
60
+ // "vec3 betaR = totalRayleigh(lambda) * reileighCoefficient;",
61
+ 'vec3 betaR = simplifiedRayleigh() * reileighCoefficient;', '// mie coefficients', 'vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;', '// optical length', '// cutoff angle at 90 to avoid singularity in next formula.', 'float zenithAngle = acos(max(0.0, dot(up2, normalize(vWorldPosition - cameraPosition))));', 'float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));', 'float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));', '// combined extinction factor', 'vec3 Fex = exp(-(betaR * sR + betaM * sM));', '// in scattering', 'float cosTheta = dot(normalize(vWorldPosition - cameraPosition), sunDirection);', 'float rPhase = rayleighPhase(cosTheta*0.5+0.5);', 'vec3 betaRTheta = betaR * rPhase;', 'float mPhase = hgPhase(cosTheta, mieDirectionalG);', 'vec3 betaMTheta = betaM * mPhase;', 'vec3 Lin = pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * (1.0 - Fex),vec3(1.5));', 'Lin *= mix(vec3(1.0),pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up2, sunDirection),5.0),0.0,1.0));', '//nightsky', 'vec3 direction = normalize(vWorldPosition - cameraPosition);', 'float theta = acos(direction.y); // elevation --> y-axis, [-pi/2, pi/2]', 'float phi = atan(direction.z, direction.x); // azimuth --> x-axis [-pi/2, pi/2]', 'vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);', '// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;', 'vec3 L0 = vec3(0.1) * Fex;', '// composition + solar disc', '//if (cosTheta > sunAngularDiameterCos)', 'float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);', '// if (normalize(vWorldPosition - cameraPosition).y>0.0)', 'L0 += (sunE * 19000.0 * Fex)*sundisk;', 'vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));', 'vec3 texColor = (Lin+L0); ', 'texColor *= 0.04 ;', 'texColor += vec3(0.0,0.001,0.0025)*0.3;', 'float g_fMaxLuminance = 1.0;', 'float fLumScaled = 0.1 / luminance; ', 'float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ', 'float ExposureBias = fLumCompressed;', 'vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);', 'vec3 color = curr*whiteScale;', 'vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));', 'gl_FragColor.rgb = retColor;', 'gl_FragColor.a = 1. - ( (length(cameraPosition) - 6400000.) / 1000.);', '}'].join('\n')
62
+ };
63
+ class Sky extends THREE.Mesh {
64
+ constructor() {
65
+ const skyUniforms = THREE.UniformsUtils.clone(skyShader.uniforms);
66
+ const skyMat = new THREE.ShaderMaterial({
67
+ fragmentShader: skyShader.fragmentShader,
68
+ vertexShader: skyShader.vertexShader,
69
+ uniforms: skyUniforms,
70
+ side: THREE.BackSide,
71
+ transparent: true,
72
+ depthWrite: false
73
+ });
74
+ const skyGeo = new THREE.SphereGeometry(40000, 32, 15);
75
+ super(skyGeo, skyMat);
76
+ }
77
+ }
78
+ export default Sky;