@3driseai/3drise-viewer 0.1.6 → 0.1.8

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 (277) hide show
  1. package/dist/components/Clouds.d.ts.map +1 -1
  2. package/dist/components/Clouds.js +0 -1
  3. package/dist/components/CloudsGenerator.d.ts +32 -0
  4. package/dist/components/CloudsGenerator.d.ts.map +1 -0
  5. package/dist/components/CloudsGenerator.js +58 -0
  6. package/dist/components/CustomPrimitive.js +1 -1
  7. package/dist/components/EnvironmentManager.d.ts +47 -5
  8. package/dist/components/EnvironmentManager.d.ts.map +1 -1
  9. package/dist/components/EnvironmentManager.js +35 -66
  10. package/dist/components/GeometryShape.d.ts.map +1 -1
  11. package/dist/components/GeometryShape.js +19 -3
  12. package/dist/components/HdrEnvironment.d.ts +20 -0
  13. package/dist/components/HdrEnvironment.d.ts.map +1 -0
  14. package/dist/components/HdrEnvironment.js +44 -0
  15. package/dist/components/LandscapeBuilder.d.ts +23 -0
  16. package/dist/components/LandscapeBuilder.d.ts.map +1 -0
  17. package/dist/components/LandscapeBuilder.js +25 -0
  18. package/dist/components/LandscapeObject.d.ts +24 -0
  19. package/dist/components/LandscapeObject.d.ts.map +1 -0
  20. package/dist/components/LandscapeObject.js +27 -0
  21. package/dist/components/ObjectNode.d.ts.map +1 -1
  22. package/dist/components/ObjectNode.js +11 -9
  23. package/dist/components/OceanBuilder.d.ts +35 -0
  24. package/dist/components/OceanBuilder.d.ts.map +1 -0
  25. package/dist/components/OceanBuilder.js +53 -0
  26. package/dist/components/ParticlesR3f.d.ts.map +1 -1
  27. package/dist/components/ParticlesR3f.js +63 -12
  28. package/dist/components/PointCloud.d.ts.map +1 -1
  29. package/dist/components/PointCloud.js +50 -10
  30. package/dist/components/SceneBuilder.d.ts.map +1 -1
  31. package/dist/components/SkySystem.d.ts +27 -6
  32. package/dist/components/SkySystem.d.ts.map +1 -1
  33. package/dist/components/SkySystem.js +6 -5
  34. package/dist/components/SunLight.d.ts.map +1 -1
  35. package/dist/components/SunLight.js +4 -1
  36. package/dist/components/TerrainBuilder.d.ts +30 -0
  37. package/dist/components/TerrainBuilder.d.ts.map +1 -0
  38. package/dist/components/TerrainBuilder.js +44 -0
  39. package/dist/components/index.d.ts +17 -1
  40. package/dist/components/index.d.ts.map +1 -1
  41. package/dist/components/index.js +10 -0
  42. package/dist/components/landscape/LandscapeMesh.d.ts +18 -0
  43. package/dist/components/landscape/LandscapeMesh.d.ts.map +1 -0
  44. package/dist/components/landscape/LandscapeMesh.js +278 -0
  45. package/dist/components/landscape/index.d.ts +3 -0
  46. package/dist/components/landscape/index.d.ts.map +1 -0
  47. package/dist/components/landscape/index.js +1 -0
  48. package/dist/components/landscape/types.d.ts +13 -0
  49. package/dist/components/landscape/types.d.ts.map +1 -0
  50. package/dist/components/landscape/types.js +1 -0
  51. package/dist/components/terrain/Canyon.d.ts +23 -0
  52. package/dist/components/terrain/Canyon.d.ts.map +1 -0
  53. package/dist/components/terrain/Canyon.js +29 -0
  54. package/dist/components/terrain/Dunes.d.ts +22 -0
  55. package/dist/components/terrain/Dunes.d.ts.map +1 -0
  56. package/dist/components/terrain/Dunes.js +25 -0
  57. package/dist/components/terrain/Hills.d.ts +17 -0
  58. package/dist/components/terrain/Hills.d.ts.map +1 -0
  59. package/dist/components/terrain/Hills.js +20 -0
  60. package/dist/components/terrain/Mountains.d.ts +19 -0
  61. package/dist/components/terrain/Mountains.d.ts.map +1 -0
  62. package/dist/components/terrain/Mountains.js +22 -0
  63. package/dist/components/terrain/TerrainSurface.d.ts +22 -0
  64. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -0
  65. package/dist/components/terrain/TerrainSurface.js +94 -0
  66. package/dist/components/terrain/index.d.ts +7 -0
  67. package/dist/components/terrain/index.d.ts.map +1 -0
  68. package/dist/components/terrain/index.js +7 -0
  69. package/dist/components/terrain/types.d.ts +17 -0
  70. package/dist/components/terrain/types.d.ts.map +1 -0
  71. package/dist/components/terrain/types.js +1 -0
  72. package/dist/components/volumetricClouds/Cirrus.d.ts +14 -0
  73. package/dist/components/volumetricClouds/Cirrus.d.ts.map +1 -0
  74. package/dist/components/volumetricClouds/Cirrus.js +13 -0
  75. package/dist/components/volumetricClouds/Cumulonimbus.d.ts +17 -0
  76. package/dist/components/volumetricClouds/Cumulonimbus.d.ts.map +1 -0
  77. package/dist/components/volumetricClouds/Cumulonimbus.js +20 -0
  78. package/dist/components/volumetricClouds/Cumulus.d.ts +14 -0
  79. package/dist/components/volumetricClouds/Cumulus.d.ts.map +1 -0
  80. package/dist/components/volumetricClouds/Cumulus.js +17 -0
  81. package/dist/components/volumetricClouds/Stratocumulus.d.ts +12 -0
  82. package/dist/components/volumetricClouds/Stratocumulus.d.ts.map +1 -0
  83. package/dist/components/volumetricClouds/Stratocumulus.js +16 -0
  84. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +42 -0
  85. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -0
  86. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +298 -0
  87. package/dist/components/volumetricClouds/index.d.ts +8 -0
  88. package/dist/components/volumetricClouds/index.d.ts.map +1 -0
  89. package/dist/components/volumetricClouds/index.js +7 -0
  90. package/dist/components/volumetricClouds/types.d.ts +17 -0
  91. package/dist/components/volumetricClouds/types.d.ts.map +1 -0
  92. package/dist/components/volumetricClouds/types.js +1 -0
  93. package/dist/components/water/Host.d.ts +12 -0
  94. package/dist/components/water/Host.d.ts.map +1 -0
  95. package/dist/components/water/Host.js +12 -0
  96. package/dist/components/water/Lake.d.ts +18 -0
  97. package/dist/components/water/Lake.d.ts.map +1 -0
  98. package/dist/components/water/Lake.js +21 -0
  99. package/dist/components/water/OceanSurface.d.ts +27 -0
  100. package/dist/components/water/OceanSurface.d.ts.map +1 -0
  101. package/dist/components/water/OceanSurface.js +60 -0
  102. package/dist/components/water/Sea.d.ts +18 -0
  103. package/dist/components/water/Sea.d.ts.map +1 -0
  104. package/dist/components/water/Sea.js +17 -0
  105. package/dist/components/water/Shore.d.ts +16 -0
  106. package/dist/components/water/Shore.d.ts.map +1 -0
  107. package/dist/components/water/Shore.js +15 -0
  108. package/dist/components/water/Storm.d.ts +14 -0
  109. package/dist/components/water/Storm.d.ts.map +1 -0
  110. package/dist/components/water/Storm.js +13 -0
  111. package/dist/components/water/WaterBody.d.ts +31 -0
  112. package/dist/components/water/WaterBody.d.ts.map +1 -0
  113. package/dist/components/water/WaterBody.js +76 -0
  114. package/dist/components/water/index.d.ts +9 -0
  115. package/dist/components/water/index.d.ts.map +1 -0
  116. package/dist/components/water/index.js +11 -0
  117. package/dist/components/water/types.d.ts +20 -0
  118. package/dist/components/water/types.d.ts.map +1 -0
  119. package/dist/components/water/types.js +1 -0
  120. package/dist/constants.d.ts +1 -0
  121. package/dist/constants.d.ts.map +1 -1
  122. package/dist/constants.js +15 -0
  123. package/dist/hooks/index.d.ts +24 -1
  124. package/dist/hooks/index.d.ts.map +1 -1
  125. package/dist/hooks/index.js +12 -0
  126. package/dist/hooks/useClipmap.d.ts +71 -0
  127. package/dist/hooks/useClipmap.d.ts.map +1 -0
  128. package/dist/hooks/useClipmap.js +81 -0
  129. package/dist/hooks/useCloudLive.d.ts +29 -0
  130. package/dist/hooks/useCloudLive.d.ts.map +1 -0
  131. package/dist/hooks/useCloudLive.js +43 -0
  132. package/dist/hooks/useCloudNoise.d.ts +28 -0
  133. package/dist/hooks/useCloudNoise.d.ts.map +1 -0
  134. package/dist/hooks/useCloudNoise.js +128 -0
  135. package/dist/hooks/useCloudSun.d.ts +49 -0
  136. package/dist/hooks/useCloudSun.d.ts.map +1 -0
  137. package/dist/hooks/useCloudSun.js +84 -0
  138. package/dist/hooks/useCubeCamera.d.ts +27 -9
  139. package/dist/hooks/useCubeCamera.d.ts.map +1 -1
  140. package/dist/hooks/useCubeCamera.js +28 -70
  141. package/dist/hooks/useEnvironmentProbe.d.ts +32 -0
  142. package/dist/hooks/useEnvironmentProbe.d.ts.map +1 -0
  143. package/dist/hooks/useEnvironmentProbe.js +35 -0
  144. package/dist/hooks/useFrameRenderer.d.ts +15 -0
  145. package/dist/hooks/useFrameRenderer.d.ts.map +1 -0
  146. package/dist/hooks/useFrameRenderer.js +23 -0
  147. package/dist/hooks/useLandscapeLive.d.ts +29 -0
  148. package/dist/hooks/useLandscapeLive.d.ts.map +1 -0
  149. package/dist/hooks/useLandscapeLive.js +41 -0
  150. package/dist/hooks/useLandscapeMaps.d.ts +32 -0
  151. package/dist/hooks/useLandscapeMaps.d.ts.map +1 -0
  152. package/dist/hooks/useLandscapeMaps.js +138 -0
  153. package/dist/hooks/useMaterialApplication.d.ts.map +1 -1
  154. package/dist/hooks/useMaterialApplication.js +2 -3
  155. package/dist/hooks/useMaterialOptions.d.ts +2 -2
  156. package/dist/hooks/useMaterialOptions.d.ts.map +1 -1
  157. package/dist/hooks/useMaterialOptions.js +13 -31
  158. package/dist/hooks/useObjectEdges.d.ts.map +1 -1
  159. package/dist/hooks/useObjectEdges.js +3 -49
  160. package/dist/hooks/useOceanLive.d.ts +29 -0
  161. package/dist/hooks/useOceanLive.d.ts.map +1 -0
  162. package/dist/hooks/useOceanLive.js +38 -0
  163. package/dist/hooks/useOceanMaterial.d.ts +39 -0
  164. package/dist/hooks/useOceanMaterial.d.ts.map +1 -0
  165. package/dist/hooks/useOceanMaterial.js +65 -0
  166. package/dist/hooks/useTerrainClipmap.d.ts +12 -0
  167. package/dist/hooks/useTerrainClipmap.d.ts.map +1 -0
  168. package/dist/hooks/useTerrainClipmap.js +10 -0
  169. package/dist/hooks/useTerrainLive.d.ts +34 -0
  170. package/dist/hooks/useTerrainLive.d.ts.map +1 -0
  171. package/dist/hooks/useTerrainLive.js +45 -0
  172. package/dist/index.d.ts +26 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +16 -0
  175. package/dist/presets/landscapePresets.d.ts +60 -0
  176. package/dist/presets/landscapePresets.d.ts.map +1 -0
  177. package/dist/presets/landscapePresets.js +194 -0
  178. package/dist/presets/landscapeTypes.d.ts +195 -0
  179. package/dist/presets/landscapeTypes.d.ts.map +1 -0
  180. package/dist/presets/landscapeTypes.js +315 -0
  181. package/dist/presets/oceanSurfacePresets.d.ts +33 -0
  182. package/dist/presets/oceanSurfacePresets.d.ts.map +1 -0
  183. package/dist/presets/oceanSurfacePresets.js +245 -0
  184. package/dist/presets/terrainPresets.d.ts +28 -0
  185. package/dist/presets/terrainPresets.d.ts.map +1 -0
  186. package/dist/presets/terrainPresets.js +293 -0
  187. package/dist/presets/volumetricCloudPresets.d.ts +38 -0
  188. package/dist/presets/volumetricCloudPresets.d.ts.map +1 -0
  189. package/dist/presets/volumetricCloudPresets.js +480 -0
  190. package/dist/shaders/clouds/CirrusMaterial.d.ts +84 -0
  191. package/dist/shaders/clouds/CirrusMaterial.d.ts.map +1 -0
  192. package/dist/shaders/clouds/CirrusMaterial.js +167 -0
  193. package/dist/shaders/clouds/CloudCompositeMaterial.d.ts +20 -0
  194. package/dist/shaders/clouds/CloudCompositeMaterial.d.ts.map +1 -0
  195. package/dist/shaders/clouds/CloudCompositeMaterial.js +82 -0
  196. package/dist/shaders/clouds/CloudResolveMaterial.d.ts +22 -0
  197. package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -0
  198. package/dist/shaders/clouds/CloudResolveMaterial.js +77 -0
  199. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +143 -0
  200. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -0
  201. package/dist/shaders/clouds/CloudVolumeMaterial.js +249 -0
  202. package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts +21 -0
  203. package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts.map +1 -0
  204. package/dist/shaders/clouds/SkyBackgroundMaterial.js +42 -0
  205. package/dist/shaders/glsl/cloudCore.glsl.d.ts +24 -0
  206. package/dist/shaders/glsl/cloudCore.glsl.d.ts.map +1 -0
  207. package/dist/shaders/glsl/cloudCore.glsl.js +348 -0
  208. package/dist/shaders/glsl/landscapeCore.glsl.d.ts +49 -0
  209. package/dist/shaders/glsl/landscapeCore.glsl.d.ts.map +1 -0
  210. package/dist/shaders/glsl/landscapeCore.glsl.js +518 -0
  211. package/dist/shaders/glsl/noiseBake.glsl.d.ts +30 -0
  212. package/dist/shaders/glsl/noiseBake.glsl.d.ts.map +1 -0
  213. package/dist/shaders/glsl/noiseBake.glsl.js +164 -0
  214. package/dist/shaders/glsl/oceanCore.glsl.d.ts +52 -0
  215. package/dist/shaders/glsl/oceanCore.glsl.d.ts.map +1 -0
  216. package/dist/shaders/glsl/oceanCore.glsl.js +421 -0
  217. package/dist/shaders/glsl/terrainCore.glsl.d.ts +78 -0
  218. package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -0
  219. package/dist/shaders/glsl/terrainCore.glsl.js +625 -0
  220. package/dist/shaders/landscape/LandscapeMaterial.d.ts +73 -0
  221. package/dist/shaders/landscape/LandscapeMaterial.d.ts.map +1 -0
  222. package/dist/shaders/landscape/LandscapeMaterial.js +136 -0
  223. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +57 -0
  224. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -0
  225. package/dist/shaders/ocean/OceanSurfaceMaterial.js +268 -0
  226. package/dist/shaders/terrain/TerrainMaterial.d.ts +80 -0
  227. package/dist/shaders/terrain/TerrainMaterial.d.ts.map +1 -0
  228. package/dist/shaders/terrain/TerrainMaterial.js +291 -0
  229. package/dist/types/cloudConfigs.d.ts +244 -0
  230. package/dist/types/cloudConfigs.d.ts.map +1 -0
  231. package/dist/types/cloudConfigs.js +282 -0
  232. package/dist/types/index.d.ts +8 -0
  233. package/dist/types/index.d.ts.map +1 -1
  234. package/dist/types/index.js +4 -1
  235. package/dist/types/landscapeConfigs.d.ts +218 -0
  236. package/dist/types/landscapeConfigs.d.ts.map +1 -0
  237. package/dist/types/landscapeConfigs.js +256 -0
  238. package/dist/types/oceanConfigs.d.ts +290 -0
  239. package/dist/types/oceanConfigs.d.ts.map +1 -0
  240. package/dist/types/oceanConfigs.js +380 -0
  241. package/dist/types/terrainConfigs.d.ts +251 -0
  242. package/dist/types/terrainConfigs.d.ts.map +1 -0
  243. package/dist/types/terrainConfigs.js +292 -0
  244. package/dist/utils/cloudUniforms.d.ts +14 -0
  245. package/dist/utils/cloudUniforms.d.ts.map +1 -0
  246. package/dist/utils/cloudUniforms.js +122 -0
  247. package/dist/utils/frameRenderer.d.ts +33 -0
  248. package/dist/utils/frameRenderer.d.ts.map +1 -0
  249. package/dist/utils/frameRenderer.js +24 -0
  250. package/dist/utils/handleCloudsAnimations.d.ts +16 -0
  251. package/dist/utils/handleCloudsAnimations.d.ts.map +1 -0
  252. package/dist/utils/handleCloudsAnimations.js +64 -0
  253. package/dist/utils/landscapeGeometry.d.ts +61 -0
  254. package/dist/utils/landscapeGeometry.d.ts.map +1 -0
  255. package/dist/utils/landscapeGeometry.js +126 -0
  256. package/dist/utils/landscapeHeight.d.ts +44 -0
  257. package/dist/utils/landscapeHeight.d.ts.map +1 -0
  258. package/dist/utils/landscapeHeight.js +65 -0
  259. package/dist/utils/landscapeTextures.d.ts +94 -0
  260. package/dist/utils/landscapeTextures.d.ts.map +1 -0
  261. package/dist/utils/landscapeTextures.js +290 -0
  262. package/dist/utils/landscapeUniforms.d.ts +20 -0
  263. package/dist/utils/landscapeUniforms.d.ts.map +1 -0
  264. package/dist/utils/landscapeUniforms.js +61 -0
  265. package/dist/utils/oceanUniforms.d.ts +47 -0
  266. package/dist/utils/oceanUniforms.d.ts.map +1 -0
  267. package/dist/utils/oceanUniforms.js +216 -0
  268. package/dist/utils/pointsMaterialOwnership.d.ts +9 -0
  269. package/dist/utils/pointsMaterialOwnership.d.ts.map +1 -0
  270. package/dist/utils/pointsMaterialOwnership.js +14 -0
  271. package/dist/utils/rtin.d.ts +63 -0
  272. package/dist/utils/rtin.d.ts.map +1 -0
  273. package/dist/utils/rtin.js +202 -0
  274. package/dist/utils/terrainUniforms.d.ts +14 -0
  275. package/dist/utils/terrainUniforms.d.ts.map +1 -0
  276. package/dist/utils/terrainUniforms.js +196 -0
  277. package/package.json +2 -2
@@ -0,0 +1,518 @@
1
+ /**
2
+ * Landscape GLSL — heightmap displacement, splat resolve, and the surface
3
+ * sampling that turns eight tiling materials into ground.
4
+ *
5
+ * Injected into a stock `MeshStandardMaterial` through `onBeforeCompile`, so
6
+ * every one of these snippets has to coexist with three's own chunks. Two
7
+ * consequences worth knowing before editing:
8
+ *
9
+ * - **three r163+ compiles every material as `#version 300 es`** and prepends
10
+ * `#define varying in/out`, `#define texture2D texture` and a `gl_FragColor`
11
+ * alias. So `sampler2DArray` and `textureGrad` are available with no
12
+ * `glslVersion` override — and setting `glslVersion: GLSL3` would REMOVE the
13
+ * `gl_FragColor` alias and break the stock chunks. Write GLSL1-flavoured code
14
+ * and let the prefix do the conversion.
15
+ * - Anything declared here shares a namespace with `<common>`. Everything is
16
+ * `ls`-prefixed or `u_ls`-prefixed for that reason.
17
+ *
18
+ * A backtick inside one of these template literals terminates the string. It has
19
+ * cost this codebase a debug cycle twice.
20
+ */
21
+ /** Uniforms and helpers the vertex stage needs. Shared with the depth material,
22
+ * which must displace identically or the landscape's shadow will not match it. */
23
+ export const landscapeVertexPars = /* glsl */ `
24
+ uniform sampler2D u_lsHeight;
25
+ uniform vec2 u_lsHeightSize;
26
+ uniform float u_lsSmoothness;
27
+ uniform float u_lsElevation;
28
+ uniform float u_lsElevationBias;
29
+ uniform float u_lsSize;
30
+
31
+ varying vec3 vLsWorld;
32
+ varying vec3 vLsNormalW;
33
+ varying float vLsHeight01;
34
+
35
+ // B-spline bicubic through four bilinear taps. What it is for is 8-bit
36
+ // heightmaps: 256 discrete levels over a kilometre of relief is a staircase, and
37
+ // a bilinear tap keeps every step. Widening the footprint by u_lsSmoothness
38
+ // turns the steps into slopes.
39
+ vec4 lsCubic(float v) {
40
+ vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
41
+ vec4 s = n * n * n;
42
+ float x = s.x;
43
+ float y = s.y - 4.0 * s.x;
44
+ float z = s.z - 4.0 * s.y + 6.0 * s.x;
45
+ float w = 6.0 - x - y - z;
46
+ return vec4(x, y, z, w) * (1.0 / 6.0);
47
+ }
48
+
49
+ float lsHeightBicubic(vec2 uv, vec2 texSize) {
50
+ vec2 invSize = 1.0 / texSize;
51
+ vec2 coord = uv * texSize - 0.5;
52
+ vec2 f = fract(coord);
53
+ coord -= f;
54
+
55
+ vec4 xc = lsCubic(f.x);
56
+ vec4 yc = lsCubic(f.y);
57
+ vec4 c = coord.xxyy + vec2(-0.5, 1.5).xyxy;
58
+ vec4 s = vec4(xc.xz + xc.yw, yc.xz + yc.yw);
59
+ vec4 o = (c + vec4(xc.yw, yc.yw) / s) * invSize.xxyy;
60
+
61
+ float s0 = texture2D(u_lsHeight, o.xz).r;
62
+ float s1 = texture2D(u_lsHeight, o.yz).r;
63
+ float s2 = texture2D(u_lsHeight, o.xw).r;
64
+ float s3 = texture2D(u_lsHeight, o.yw).r;
65
+ float sx = s.x / (s.x + s.y);
66
+ float sy = s.z / (s.z + s.w);
67
+ return mix(mix(s3, s2, sx), mix(s1, s0, sx), sy);
68
+ }
69
+
70
+ // Normalised height at a UV. NOT wrapped in abs() — the reference does that and
71
+ // it folds every below-zero basin upward, which matters the moment there is
72
+ // water in the scene.
73
+ // Single exit, and the result is initialised at its declaration. Every function
74
+ // in this file is written that way deliberately: ANGLE translates GLSL to HLSL on
75
+ // Windows and rewrites an early return into an assignment plus a jump, which
76
+ // D3D's compiler then reports as X4000 "use of potentially uninitialized
77
+ // variable" naming the function's own result. It is a warning rather than an
78
+ // error and the shader links either way, but the pattern is worth avoiding — the
79
+ // analysis that produces the warning is the same one that decides what to
80
+ // initialise.
81
+ float lsHeightAt(vec2 uv) {
82
+ vec2 c = clamp(uv, 0.0, 1.0);
83
+ float h = 0.0;
84
+ if (u_lsSmoothness > 0.001) {
85
+ h = lsHeightBicubic(c, u_lsHeightSize / max(u_lsSmoothness, 0.001));
86
+ } else {
87
+ h = texture2D(u_lsHeight, c).r;
88
+ }
89
+ return h;
90
+ }
91
+
92
+ float lsWorldHeight(vec2 uv) {
93
+ return lsHeightAt(uv) * u_lsElevation + u_lsElevationBias;
94
+ }
95
+
96
+ // Surface normal by central difference at the heightmap's real texel size and
97
+ // the real elevation scale. The reference hardcodes both (1.0/1024.0 and 120.0),
98
+ // so its normals are only correct for one map at one scale, and its smoothed
99
+ // variant returns abs(cross(...)) — a normal with the sign stripped, which is
100
+ // why that API needs per-surface normal-flipping flags to paper over it.
101
+ vec3 lsSurfaceNormal(vec2 uv) {
102
+ vec2 texel = 1.0 / u_lsHeightSize;
103
+ float hL = lsWorldHeight(uv - vec2(texel.x, 0.0));
104
+ float hR = lsWorldHeight(uv + vec2(texel.x, 0.0));
105
+ float hD = lsWorldHeight(uv - vec2(0.0, texel.y));
106
+ float hU = lsWorldHeight(uv + vec2(0.0, texel.y));
107
+ // World distance spanned by the two taps on each axis.
108
+ float dx = 2.0 * texel.x * u_lsSize;
109
+ float dz = 2.0 * texel.y * u_lsSize;
110
+ return normalize(vec3(-(hR - hL) * dz, dx * dz, -(hU - hD) * dx));
111
+ }
112
+ `;
113
+ /** Replaces `<begin_vertex>`. Displaces along local +Y and fills the varyings. */
114
+ export const landscapeVertexBody = /* glsl */ `
115
+ vec3 transformed = vec3(position);
116
+ float lsH01 = lsHeightAt(uv);
117
+ transformed.y += lsH01 * u_lsElevation + u_lsElevationBias;
118
+ vLsHeight01 = lsH01;
119
+ vLsWorld = (modelMatrix * vec4(transformed, 1.0)).xyz;
120
+ vLsNormalW = normalize(mat3(modelMatrix) * lsSurfaceNormal(uv));
121
+ `;
122
+ /** Replaces `<beginnormal_vertex>`. The geometry carries a flat up-normal — the
123
+ * shape is entirely in the heightmap — so the real normal is evaluated here and
124
+ * three's lighting sees a correctly shaded surface with no extra chunk. */
125
+ export const landscapeNormalBody = /* glsl */ `
126
+ vec3 objectNormal = lsSurfaceNormal(uv);
127
+ `;
128
+ /**
129
+ * Fragment uniforms, samplers and the surface sampling machinery.
130
+ *
131
+ * Compile-time counts rather than runtime loops: LS_COUNT is the actual surface
132
+ * count and LS_SAMPLES the blend width, so every loop here has constant bounds
133
+ * and unrolls. The reference runs an eight-element insertion sort in a dynamic
134
+ * while loop on every pixel of the screen.
135
+ */
136
+ export const landscapeFragmentPars = /* glsl */ `
137
+ uniform sampler2DArray u_lsDiffuse;
138
+ uniform sampler2DArray u_lsNormal; // rgb tangent-space normal, a surface height
139
+ uniform sampler2D u_lsSplat0;
140
+ uniform sampler2D u_lsSplat1;
141
+ uniform sampler2D u_lsAo;
142
+ // The height field as the fragment stage sees it: RG the one-texel gradient,
143
+ // biased by u_lsGradScale, B the height. One fetch replaces two interpolated
144
+ // varyings that were quantising both the splat and the shading to the
145
+ // triangulation. See buildFieldTexture.
146
+ uniform sampler2D u_lsField;
147
+ uniform float u_lsGradScale;
148
+ uniform vec2 u_lsFieldTexel;
149
+
150
+ // repeat, normalStrength, roughness, heightBlend
151
+ uniform vec4 u_lsSurfA[LS_COUNT];
152
+ // tint.rgb, saturation
153
+ uniform vec4 u_lsSurfB[LS_COUNT];
154
+ // triplanar, flipNormalY, metalness, aperiodic
155
+ uniform vec4 u_lsSurfC[LS_COUNT];
156
+ // mean colour per diffuse layer, for the variance-preserving stochastic blend
157
+ uniform vec3 u_lsSurfMean[LS_COUNT];
158
+
159
+ uniform vec4 u_lsAuto; // bandWidth, slopeStart, slopeEnd, noise
160
+ uniform float u_lsAutoBands[LS_COUNT];
161
+ uniform float u_lsNoiseScale; // 1 / noiseSize, world units
162
+ uniform float u_lsMacro;
163
+ uniform float u_lsMacroScale;
164
+ uniform float u_lsAoIntensity;
165
+ uniform float u_lsSize;
166
+ uniform float u_lsElevation;
167
+
168
+ varying vec3 vLsWorld;
169
+ varying vec3 vLsNormalW;
170
+ varying float vLsHeight01;
171
+
172
+ // Arithmetic hash. Never fract(sin(dot(...))): four hashes an octave with two
173
+ // sines each is most of a frame on its own, and this codebase has paid for that
174
+ // lesson once already in the terrain.
175
+ vec2 lsHash2(vec2 p) {
176
+ vec3 p3 = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));
177
+ p3 += dot(p3, p3.yzx + 33.33);
178
+ return fract((p3.xx + p3.yz) * p3.zy);
179
+ }
180
+
181
+ float lsHash1(vec2 p) {
182
+ vec3 p3 = fract(vec3(p.xyx) * 0.1031);
183
+ p3 += dot(p3, p3.yzx + 33.33);
184
+ return fract((p3.x + p3.y) * p3.z);
185
+ }
186
+
187
+ float lsValueNoise(vec2 p) {
188
+ vec2 i = floor(p);
189
+ vec2 f = fract(p);
190
+ vec2 u = f * f * (3.0 - 2.0 * f);
191
+ return mix(
192
+ mix(lsHash1(i), lsHash1(i + vec2(1.0, 0.0)), u.x),
193
+ mix(lsHash1(i + vec2(0.0, 1.0)), lsHash1(i + vec2(1.0, 1.0)), u.x),
194
+ u.y
195
+ );
196
+ }
197
+
198
+ #ifdef LS_STOCHASTIC
199
+ // Triangle-grid stochastic tiling. Three taps at hashed offsets, weighted by the
200
+ // barycentric coordinate of the point in its cell, so the repeat grid stops
201
+ // existing. The blend is variance-preserving: a straight weighted sum of three
202
+ // samples pulls every pixel toward the texture's mean and visibly washes out
203
+ // contrast, which is what the reference's two-tap smoothstep blend does. Dividing
204
+ // the deviation by sqrt(sum(w^2)) restores it. The mean comes from the CPU, where
205
+ // the pixels were already in hand when the array was packed.
206
+ // Cell size, in texture tiles. The point of stochastic tiling is to randomise
207
+ // PATCHES of texture, so a cell wants to be a tile or two across: smaller and it
208
+ // scrambles within a tile, which shows as noise rather than as break-up, and
209
+ // goes sub-pixel almost immediately.
210
+ //
211
+ // The first version used the bare 3.4641 grid on already-tiled UVs, so a cell was
212
+ // a THIRD of a tile — a fraction of a metre on the ground. It went sub-pixel at
213
+ // any distance, the fade dropped it back to plain sampling, and the repeat grid
214
+ // came straight back at exactly the range it exists to hide.
215
+ #define LS_CELL_TILES 1.5
216
+
217
+ void lsTriGrid(vec2 uv, out vec3 w, out vec2 v1, out vec2 v2, out vec2 v3) {
218
+ w = vec3(0.0);
219
+ v1 = vec2(0.0);
220
+ v2 = vec2(0.0);
221
+ v3 = vec2(0.0);
222
+ vec2 skewed = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (uv * (3.4641016 / LS_CELL_TILES));
223
+ vec2 base = floor(skewed);
224
+ vec3 t = vec3(fract(skewed), 0.0);
225
+ t.z = 1.0 - t.x - t.y;
226
+ if (t.z > 0.0) {
227
+ w = vec3(t.z, t.y, t.x);
228
+ v1 = base;
229
+ v2 = base + vec2(0.0, 1.0);
230
+ v3 = base + vec2(1.0, 0.0);
231
+ } else {
232
+ w = vec3(-t.z, 1.0 - t.y, 1.0 - t.x);
233
+ v1 = base + vec2(1.0, 1.0);
234
+ v2 = base + vec2(1.0, 0.0);
235
+ v3 = base + vec2(0.0, 1.0);
236
+ }
237
+ }
238
+
239
+ vec4 lsSampleStochastic(sampler2DArray tex, vec2 uv, float layer, vec3 mean) {
240
+ vec2 dx = dFdx(uv);
241
+ vec2 dy = dFdy(uv);
242
+ vec4 result = vec4(0.0);
243
+
244
+ // Stochastic cells per pixel. THIS FADE IS NOT OPTIONAL. A surface tiled 220
245
+ // times across a two-kilometre landscape has cells a metre or two wide, which
246
+ // is roughly a pixel by the time the ground is a few hundred metres away: the
247
+ // three taps then land in unrelated parts of the texture, the variance
248
+ // correction amplifies the difference, and the far field turns into a moire of
249
+ // black speckle. Rendered, that looked exactly like shadow acne and was not —
250
+ // turning shadows off changed nothing and turning stochastic sampling off
251
+ // fixed it. Past the fade this is a plain sample, which is what the mip chain
252
+ // is for. Gradients are explicit throughout, so the branch is safe.
253
+ float footprint = max(length(dx), length(dy)) * (3.4641016 / LS_CELL_TILES);
254
+ float fade = smoothstep(0.45, 1.10, footprint);
255
+
256
+ if (fade > 0.995) {
257
+ result = textureGrad(tex, vec3(uv, layer), dx, dy);
258
+ } else {
259
+ vec3 w;
260
+ vec2 v1, v2, v3;
261
+ lsTriGrid(uv, w, v1, v2, v3);
262
+ vec4 c1 = textureGrad(tex, vec3(uv + lsHash2(v1), layer), dx, dy);
263
+ vec4 c2 = textureGrad(tex, vec3(uv + lsHash2(v2), layer), dx, dy);
264
+ vec4 c3 = textureGrad(tex, vec3(uv + lsHash2(v3), layer), dx, dy);
265
+ vec4 m = vec4(mean, 0.5);
266
+ vec4 d = w.x * (c1 - m) + w.y * (c2 - m) + w.z * (c3 - m);
267
+ // Clamped: the correction multiplies the deviation by up to 1.73, which
268
+ // takes a dark texel below zero and a bright one past one.
269
+ result = clamp(m + d * inversesqrt(max(dot(w, w), 1e-4)), 0.0, 1.0);
270
+ if (fade >= 0.005) {
271
+ result = mix(result, textureGrad(tex, vec3(uv, layer), dx, dy), fade);
272
+ }
273
+ }
274
+ return result;
275
+ }
276
+ #endif
277
+
278
+ // Per surface, not per material: stochastic tiling is three fetches instead of
279
+ // one, and only the surfaces a camera gets close to need it. The whole path
280
+ // compiles out when no surface asks for it.
281
+ vec4 lsSampleArray(sampler2DArray tex, vec2 uv, float layer, vec3 mean, float stochastic) {
282
+ vec4 result = vec4(0.0);
283
+ #ifdef LS_STOCHASTIC
284
+ if (stochastic > 0.5) {
285
+ result = lsSampleStochastic(tex, uv, layer, mean);
286
+ } else {
287
+ result = texture(tex, vec3(uv, layer));
288
+ }
289
+ #else
290
+ result = texture(tex, vec3(uv, layer));
291
+ #endif
292
+ return result;
293
+ }
294
+
295
+ #ifdef LS_TRIPLANAR
296
+ // Biplanar: the two strongest axes, not three. The third contributes a fraction
297
+ // of a percent on any surface that is not an exact 45 degree corner, and it costs
298
+ // a third of the fetches. The reference ships biplanar samplers and then calls
299
+ // the triplanar path anyway.
300
+ vec4 lsSampleWorld(sampler2DArray tex, vec3 wp, vec3 n, float scale, float layer, vec3 mean, float stochastic) {
301
+ vec3 an = abs(n);
302
+ an = an * an * an;
303
+ an /= max(an.x + an.y + an.z, 1e-4);
304
+ float lo = min(an.x, min(an.y, an.z));
305
+ vec3 w = max(an - lo, 0.0);
306
+ w /= max(w.x + w.y + w.z, 1e-4);
307
+ vec4 c = vec4(0.0);
308
+ if (w.x > 0.002) c += w.x * lsSampleArray(tex, wp.zy * scale, layer, mean, stochastic);
309
+ if (w.y > 0.002) c += w.y * lsSampleArray(tex, wp.xz * scale, layer, mean, stochastic);
310
+ if (w.z > 0.002) c += w.z * lsSampleArray(tex, wp.xy * scale, layer, mean, stochastic);
311
+ return c;
312
+ }
313
+ #endif
314
+
315
+ // Saturation as a luma lerp. The reference runs a full RGB->HSV->RGB round trip
316
+ // per sampled surface per pixel for this.
317
+ vec3 lsSaturate(vec3 c, float s) {
318
+ return mix(vec3(dot(c, vec3(0.2126, 0.7152, 0.0722))), c, s);
319
+ }
320
+ `;
321
+ /**
322
+ * The resolve, called from `<map_fragment>`. Fills `lsAlbedo`, `lsNormalW`,
323
+ * `lsRoughness` and `lsMetalness`, which the roughness, metalness and normal
324
+ * chunks then read.
325
+ *
326
+ * Order matters: the surface heights come out of the normal array's alpha
327
+ * channel, so the height blend is computed before a single diffuse texel is
328
+ * fetched, and the diffuse pass already knows its final weights.
329
+ */
330
+ export const landscapeFragmentBody = /* glsl */ `
331
+ vec2 lsUv = vUv;
332
+
333
+ // PER FRAGMENT, not per vertex. The first version read an interpolated height
334
+ // and an interpolated normal out of varyings, and both are linear across a
335
+ // triangle: every splat threshold came out as a straight iso-line kinking at
336
+ // triangle edges — big polygonal patches of flat colour — and the shading normal
337
+ // was faceted to match. One fetch of the field texture fixes both, and makes the
338
+ // mesh resolution invisible to the shading: the ground reads smooth however
339
+ // coarse the triangles under it are.
340
+ vec4 lsField = texture2D(u_lsField, lsUv);
341
+ float lsHeight01 = lsField.b;
342
+
343
+ // Gradient back to a world-space normal. dx and dz are the world distance one
344
+ // field texel spans, so the normal is correct at any size and elevation rather
345
+ // than only at the one it was authored for.
346
+ vec2 lsGrad = (lsField.rg * 2.0 - 1.0) * u_lsGradScale;
347
+ float lsDx = u_lsFieldTexel.x * u_lsSize;
348
+ float lsDz = u_lsFieldTexel.y * u_lsSize;
349
+ vec3 lsN = normalize(vec3(
350
+ -lsGrad.x * u_lsElevation * lsDz,
351
+ lsDx * lsDz,
352
+ -lsGrad.y * u_lsElevation * lsDx
353
+ ));
354
+
355
+ // Slope as a fraction of vertical rather than 1 - n.y: the naive form is badly
356
+ // compressed at the angles that matter, so every threshold crowds into the top
357
+ // of its range and rock never appears where it should. This way 0.5 IS 45
358
+ // degrees. Same reasoning as the terrain material.
359
+ float lsSlope = acos(clamp(lsN.y, -1.0, 1.0)) * 0.63661977;
360
+
361
+ // ---- surface weights ------------------------------------------------------
362
+ float lsW[LS_COUNT];
363
+
364
+ #ifdef LS_AUTO
365
+ // Generated from the heightmap's own height and slope, so a bare heightmap with
366
+ // no authored splat map still renders as ground. Same rule the procedural
367
+ // terrain shades by: everything by height, rock by slope, rock applied last.
368
+ float lsHJit = lsHeight01 + (lsValueNoise(vLsWorld.xz * u_lsNoiseScale) - 0.5) * u_lsAuto.w;
369
+ float lsRock = smoothstep(u_lsAuto.y, u_lsAuto.z, lsSlope);
370
+ for (int i = 0; i < LS_COUNT; i++) {
371
+ float d = abs(lsHJit - u_lsAutoBands[i]);
372
+ lsW[i] = max(1.0 - d / max(u_lsAuto.x, 1e-3), 0.0);
373
+ }
374
+ // The last surface is the rock layer.
375
+ for (int i = 0; i < LS_COUNT - 1; i++) lsW[i] *= (1.0 - lsRock);
376
+ lsW[LS_COUNT - 1] = max(lsW[LS_COUNT - 1], lsRock);
377
+ #else
378
+ vec4 lsS0 = texture2D(u_lsSplat0, lsUv);
379
+ lsW[0] = lsS0.r;
380
+ #if LS_COUNT > 1
381
+ lsW[1] = lsS0.g;
382
+ #endif
383
+ #if LS_COUNT > 2
384
+ lsW[2] = lsS0.b;
385
+ #endif
386
+ #if LS_COUNT > 3
387
+ lsW[3] = lsS0.a;
388
+ #endif
389
+ #if LS_COUNT > 4
390
+ vec4 lsS1 = texture2D(u_lsSplat1, lsUv);
391
+ lsW[4] = lsS1.r;
392
+ #endif
393
+ #if LS_COUNT > 5
394
+ lsW[5] = lsS1.g;
395
+ #endif
396
+ #if LS_COUNT > 6
397
+ lsW[6] = lsS1.b;
398
+ #endif
399
+ #if LS_COUNT > 7
400
+ lsW[7] = lsS1.a;
401
+ #endif
402
+ #endif
403
+
404
+ // ---- pick the heaviest LS_SAMPLES ----------------------------------------
405
+ // Constant bounds both ways, so this unrolls. No sort, no swaps, no dynamic
406
+ // loop: LS_SAMPLES passes each taking the largest remaining weight.
407
+ int lsIdx[LS_SAMPLES];
408
+ float lsWt[LS_SAMPLES];
409
+ for (int s = 0; s < LS_SAMPLES; s++) {
410
+ int best = 0;
411
+ float bw = -1.0;
412
+ for (int i = 0; i < LS_COUNT; i++) {
413
+ if (lsW[i] > bw) { bw = lsW[i]; best = i; }
414
+ }
415
+ lsIdx[s] = best;
416
+ lsWt[s] = max(bw, 0.0);
417
+ lsW[best] = -1.0;
418
+ }
419
+
420
+ // ---- normals and heights, then the height blend ---------------------------
421
+ vec4 lsNrm[LS_SAMPLES];
422
+ float lsBlendRange = 1.0;
423
+ float lsPeak = -1e9;
424
+ float lsV[LS_SAMPLES];
425
+
426
+ for (int s = 0; s < LS_SAMPLES; s++) {
427
+ int i = lsIdx[s];
428
+ float repeat = u_lsSurfA[i].x;
429
+ vec2 uv = lsUv * repeat;
430
+ vec3 mean = vec3(0.5, 0.5, 1.0);
431
+ float stoch = u_lsSurfC[i].w;
432
+ vec4 n;
433
+ #ifdef LS_TRIPLANAR
434
+ if (u_lsSurfC[i].x > 0.5) {
435
+ n = lsSampleWorld(u_lsNormal, vLsWorld, lsN, repeat / max(u_lsSize, 1e-3), float(i), mean, stoch);
436
+ } else {
437
+ n = lsSampleArray(u_lsNormal, uv, float(i), mean, stoch);
438
+ }
439
+ #else
440
+ n = lsSampleArray(u_lsNormal, uv, float(i), mean, stoch);
441
+ #endif
442
+ lsNrm[s] = n;
443
+
444
+ // Height blending. Two surfaces meeting no longer cross-fade: the one whose
445
+ // own height map is higher at this texel wins, so gravel comes through grass
446
+ // along the gravel's grain. The reference loads these height maps and never
447
+ // samples them.
448
+ float hb = u_lsSurfA[i].w;
449
+ lsBlendRange = min(lsBlendRange, mix(1.0, 0.04, hb));
450
+ lsV[s] = lsWt[s] + n.a * hb;
451
+ lsPeak = max(lsPeak, lsV[s]);
452
+ }
453
+
454
+ float lsSum = 0.0;
455
+ for (int s = 0; s < LS_SAMPLES; s++) {
456
+ lsWt[s] = max(lsV[s] - (lsPeak - lsBlendRange), 0.0);
457
+ lsSum += lsWt[s];
458
+ }
459
+ lsSum = max(lsSum, 1e-4);
460
+ for (int s = 0; s < LS_SAMPLES; s++) lsWt[s] /= lsSum;
461
+
462
+ // ---- albedo, normal, roughness -------------------------------------------
463
+ vec3 lsAlbedo = vec3(0.0);
464
+ vec3 lsNsum = vec3(0.0);
465
+ float lsRoughness = 0.0;
466
+ float lsMetalness = 0.0;
467
+
468
+ for (int s = 0; s < LS_SAMPLES; s++) {
469
+ int i = lsIdx[s];
470
+ float w = lsWt[s];
471
+ float repeat = u_lsSurfA[i].x;
472
+ vec2 uv = lsUv * repeat;
473
+
474
+ float stoch = u_lsSurfC[i].w;
475
+ vec4 d;
476
+ #ifdef LS_TRIPLANAR
477
+ if (u_lsSurfC[i].x > 0.5) {
478
+ d = lsSampleWorld(u_lsDiffuse, vLsWorld, lsN, repeat / max(u_lsSize, 1e-3), float(i), u_lsSurfMean[i], stoch);
479
+ } else {
480
+ d = lsSampleArray(u_lsDiffuse, uv, float(i), u_lsSurfMean[i], stoch);
481
+ }
482
+ #else
483
+ d = lsSampleArray(u_lsDiffuse, uv, float(i), u_lsSurfMean[i], stoch);
484
+ #endif
485
+
486
+ vec3 col = lsSaturate(d.rgb, u_lsSurfB[i].w) * u_lsSurfB[i].rgb;
487
+ lsAlbedo += col * w;
488
+
489
+ // Whiteout-style blend: sum the tangent-space XY, keep Z positive, normalise
490
+ // once at the end. The reference slerps every surface against a flat normal
491
+ // and then RNM-blends the result — an acos and three sines per sampled
492
+ // surface, per pixel.
493
+ vec3 m = lsNrm[s].rgb * 2.0 - 1.0;
494
+ m.y *= u_lsSurfC[i].y;
495
+ m.xy *= u_lsSurfA[i].y;
496
+ lsNsum += m * w;
497
+
498
+ lsRoughness += u_lsSurfA[i].z * w;
499
+ lsMetalness += u_lsSurfC[i].z * w;
500
+ }
501
+
502
+ // Large-scale albedo break-up, generated rather than sampled. Without it a splat
503
+ // layer is one flat colour across hundreds of metres and reads as untextured;
504
+ // the reference ships a 2.7 MB texture to do this.
505
+ if (u_lsMacro > 0.001) {
506
+ float macro = lsValueNoise(vLsWorld.xz * u_lsMacroScale) * 0.6
507
+ + lsValueNoise(vLsWorld.xz * u_lsMacroScale * 2.7) * 0.4;
508
+ lsAlbedo *= mix(1.0, 0.6 + macro * 0.8, u_lsMacro);
509
+ }
510
+
511
+ vec3 lsMapN = normalize(vec3(lsNsum.xy, max(1.0 - length(lsNsum.xy) * 0.5, 0.05)));
512
+ // Tangent frame for a heightfield with axis-aligned UVs: world X, orthogonalised
513
+ // against the surface normal. No tangent attribute and no derivative-based TBN
514
+ // needed, because the mapping is known.
515
+ vec3 lsT = normalize(vec3(1.0, 0.0, 0.0) - lsN * lsN.x);
516
+ vec3 lsB = cross(lsN, lsT);
517
+ vec3 lsNormalW = normalize(lsT * lsMapN.x + lsB * lsMapN.y + lsN * lsMapN.z);
518
+ `;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Bake-time noise. Runs once at startup, never per frame.
3
+ *
4
+ * Everything here is *tileable*: the hash wraps its lattice with mod(p, freq) so the
5
+ * volumes repeat seamlessly under RepeatWrapping. Non-tileable noise in a repeating
6
+ * 3D texture produces a visible grid of seams across the sky, which is the single most
7
+ * common giveaway in a volumetric cloud implementation.
8
+ */
9
+ export declare const bakeCommon = "\n#define PI 3.14159265359\n#define saturate(x) clamp(x, 0.0, 1.0)\nfloat remap(float v, float a, float b, float c, float d){\n return c + (v - a) * (d - c) / max(b - a, 1e-6);\n}\n\nvec3 hash33t(vec3 p, float f){\n p = mod(p, vec3(f));\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yxx) * p.zyx);\n}\nvec2 hash22t(vec2 p, float f){\n p = mod(p, vec2(f));\n vec3 q = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));\n q += dot(q, q.yzx + 19.19);\n return fract((q.xx + q.yz) * q.zy);\n}\n\nfloat perlin3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n vec3 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n000 = dot(hash33t(i+vec3(0,0,0),f)*2.0-1.0, t-vec3(0,0,0));\n float n100 = dot(hash33t(i+vec3(1,0,0),f)*2.0-1.0, t-vec3(1,0,0));\n float n010 = dot(hash33t(i+vec3(0,1,0),f)*2.0-1.0, t-vec3(0,1,0));\n float n110 = dot(hash33t(i+vec3(1,1,0),f)*2.0-1.0, t-vec3(1,1,0));\n float n001 = dot(hash33t(i+vec3(0,0,1),f)*2.0-1.0, t-vec3(0,0,1));\n float n101 = dot(hash33t(i+vec3(1,0,1),f)*2.0-1.0, t-vec3(1,0,1));\n float n011 = dot(hash33t(i+vec3(0,1,1),f)*2.0-1.0, t-vec3(0,1,1));\n float n111 = dot(hash33t(i+vec3(1,1,1),f)*2.0-1.0, t-vec3(1,1,1));\n float x00 = mix(n000,n100,u.x), x10 = mix(n010,n110,u.x);\n float x01 = mix(n001,n101,u.x), x11 = mix(n011,n111,u.x);\n return mix(mix(x00,x10,u.y), mix(x01,x11,u.y), u.z);\n}\n\nfloat perlin2(vec2 x, float f){\n vec2 p = x * f;\n vec2 i = floor(p); vec2 t = p - i;\n vec2 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n00 = dot(hash22t(i+vec2(0,0),f)*2.0-1.0, t-vec2(0,0));\n float n10 = dot(hash22t(i+vec2(1,0),f)*2.0-1.0, t-vec2(1,0));\n float n01 = dot(hash22t(i+vec2(0,1),f)*2.0-1.0, t-vec2(0,1));\n float n11 = dot(hash22t(i+vec2(1,1),f)*2.0-1.0, t-vec2(1,1));\n return mix(mix(n00,n10,u.x), mix(n01,n11,u.x), u.y);\n}\n\nfloat worley3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n float md = 1e9;\n for(int z=-1; z<=1; z++)\n for(int y=-1; y<=1; y++)\n for(int w=-1; w<=1; w++){\n vec3 o = vec3(float(w), float(y), float(z));\n vec3 h = hash33t(i + o, f);\n vec3 d = o + h - t;\n md = min(md, dot(d, d));\n }\n return saturate(sqrt(md));\n}\n";
10
+ export declare const bakeVertex = "\nout vec2 vUv;\nvoid main(){ vUv = uv; gl_Position = vec4(position.xy, 0.0, 1.0); }\n";
11
+ /**
12
+ * Base shape, 128³ RGBA.
13
+ * R = Perlin-Worley (Schneider): perlin fbm remapped by an inverted-worley fbm, which
14
+ * gives billowy tops without losing perlin's connectedness.
15
+ * G/B/A = inverted worley at 4 / 8 / 16, recombined in the march as the low-frequency
16
+ * fbm that erodes R.
17
+ */
18
+ export declare const bakeBaseFrag = "\n\n#define PI 3.14159265359\n#define saturate(x) clamp(x, 0.0, 1.0)\nfloat remap(float v, float a, float b, float c, float d){\n return c + (v - a) * (d - c) / max(b - a, 1e-6);\n}\n\nvec3 hash33t(vec3 p, float f){\n p = mod(p, vec3(f));\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yxx) * p.zyx);\n}\nvec2 hash22t(vec2 p, float f){\n p = mod(p, vec2(f));\n vec3 q = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));\n q += dot(q, q.yzx + 19.19);\n return fract((q.xx + q.yz) * q.zy);\n}\n\nfloat perlin3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n vec3 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n000 = dot(hash33t(i+vec3(0,0,0),f)*2.0-1.0, t-vec3(0,0,0));\n float n100 = dot(hash33t(i+vec3(1,0,0),f)*2.0-1.0, t-vec3(1,0,0));\n float n010 = dot(hash33t(i+vec3(0,1,0),f)*2.0-1.0, t-vec3(0,1,0));\n float n110 = dot(hash33t(i+vec3(1,1,0),f)*2.0-1.0, t-vec3(1,1,0));\n float n001 = dot(hash33t(i+vec3(0,0,1),f)*2.0-1.0, t-vec3(0,0,1));\n float n101 = dot(hash33t(i+vec3(1,0,1),f)*2.0-1.0, t-vec3(1,0,1));\n float n011 = dot(hash33t(i+vec3(0,1,1),f)*2.0-1.0, t-vec3(0,1,1));\n float n111 = dot(hash33t(i+vec3(1,1,1),f)*2.0-1.0, t-vec3(1,1,1));\n float x00 = mix(n000,n100,u.x), x10 = mix(n010,n110,u.x);\n float x01 = mix(n001,n101,u.x), x11 = mix(n011,n111,u.x);\n return mix(mix(x00,x10,u.y), mix(x01,x11,u.y), u.z);\n}\n\nfloat perlin2(vec2 x, float f){\n vec2 p = x * f;\n vec2 i = floor(p); vec2 t = p - i;\n vec2 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n00 = dot(hash22t(i+vec2(0,0),f)*2.0-1.0, t-vec2(0,0));\n float n10 = dot(hash22t(i+vec2(1,0),f)*2.0-1.0, t-vec2(1,0));\n float n01 = dot(hash22t(i+vec2(0,1),f)*2.0-1.0, t-vec2(0,1));\n float n11 = dot(hash22t(i+vec2(1,1),f)*2.0-1.0, t-vec2(1,1));\n return mix(mix(n00,n10,u.x), mix(n01,n11,u.x), u.y);\n}\n\nfloat worley3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n float md = 1e9;\n for(int z=-1; z<=1; z++)\n for(int y=-1; y<=1; y++)\n for(int w=-1; w<=1; w++){\n vec3 o = vec3(float(w), float(y), float(z));\n vec3 h = hash33t(i + o, f);\n vec3 d = o + h - t;\n md = min(md, dot(d, d));\n }\n return saturate(sqrt(md));\n}\n\n\nin vec2 vUv;\nout vec4 outColor;\n\n\nuniform vec2 u_atlas;\nuniform float u_tiles;\nuniform float u_res;\nvec3 volCoord(){\n vec2 px = floor(vUv * u_atlas);\n vec2 tile = floor(px / u_res);\n float z = tile.y * u_tiles + tile.x;\n vec2 xy = px - tile * u_res;\n return (vec3(xy, z) + 0.5) / u_res;\n}\n\nvoid main(){\n vec3 p = volCoord();\n float pf = perlin3(p, 4.0) * 0.5 + perlin3(p, 8.0) * 0.25\n + perlin3(p, 16.0) * 0.125 + perlin3(p, 32.0) * 0.0625;\n pf = saturate(pf * 1.35 + 0.5);\n float w4 = 1.0 - worley3(p, 4.0);\n float w8 = 1.0 - worley3(p, 8.0);\n float w16 = 1.0 - worley3(p, 16.0);\n float wfbm = saturate(w4 * 0.625 + w8 * 0.25 + w16 * 0.125);\n outColor = vec4(saturate(remap(pf, wfbm - 1.0, 1.0, 0.0, 1.0)), w4, w8, w16);\n}\n";
19
+ /** Detail erosion, 64³ RGB inverted worley at 4 / 8 / 16. */
20
+ export declare const bakeDetailFrag = "\n\n#define PI 3.14159265359\n#define saturate(x) clamp(x, 0.0, 1.0)\nfloat remap(float v, float a, float b, float c, float d){\n return c + (v - a) * (d - c) / max(b - a, 1e-6);\n}\n\nvec3 hash33t(vec3 p, float f){\n p = mod(p, vec3(f));\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yxx) * p.zyx);\n}\nvec2 hash22t(vec2 p, float f){\n p = mod(p, vec2(f));\n vec3 q = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));\n q += dot(q, q.yzx + 19.19);\n return fract((q.xx + q.yz) * q.zy);\n}\n\nfloat perlin3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n vec3 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n000 = dot(hash33t(i+vec3(0,0,0),f)*2.0-1.0, t-vec3(0,0,0));\n float n100 = dot(hash33t(i+vec3(1,0,0),f)*2.0-1.0, t-vec3(1,0,0));\n float n010 = dot(hash33t(i+vec3(0,1,0),f)*2.0-1.0, t-vec3(0,1,0));\n float n110 = dot(hash33t(i+vec3(1,1,0),f)*2.0-1.0, t-vec3(1,1,0));\n float n001 = dot(hash33t(i+vec3(0,0,1),f)*2.0-1.0, t-vec3(0,0,1));\n float n101 = dot(hash33t(i+vec3(1,0,1),f)*2.0-1.0, t-vec3(1,0,1));\n float n011 = dot(hash33t(i+vec3(0,1,1),f)*2.0-1.0, t-vec3(0,1,1));\n float n111 = dot(hash33t(i+vec3(1,1,1),f)*2.0-1.0, t-vec3(1,1,1));\n float x00 = mix(n000,n100,u.x), x10 = mix(n010,n110,u.x);\n float x01 = mix(n001,n101,u.x), x11 = mix(n011,n111,u.x);\n return mix(mix(x00,x10,u.y), mix(x01,x11,u.y), u.z);\n}\n\nfloat perlin2(vec2 x, float f){\n vec2 p = x * f;\n vec2 i = floor(p); vec2 t = p - i;\n vec2 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n00 = dot(hash22t(i+vec2(0,0),f)*2.0-1.0, t-vec2(0,0));\n float n10 = dot(hash22t(i+vec2(1,0),f)*2.0-1.0, t-vec2(1,0));\n float n01 = dot(hash22t(i+vec2(0,1),f)*2.0-1.0, t-vec2(0,1));\n float n11 = dot(hash22t(i+vec2(1,1),f)*2.0-1.0, t-vec2(1,1));\n return mix(mix(n00,n10,u.x), mix(n01,n11,u.x), u.y);\n}\n\nfloat worley3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n float md = 1e9;\n for(int z=-1; z<=1; z++)\n for(int y=-1; y<=1; y++)\n for(int w=-1; w<=1; w++){\n vec3 o = vec3(float(w), float(y), float(z));\n vec3 h = hash33t(i + o, f);\n vec3 d = o + h - t;\n md = min(md, dot(d, d));\n }\n return saturate(sqrt(md));\n}\n\n\nin vec2 vUv;\nout vec4 outColor;\n\n\nuniform vec2 u_atlas;\nuniform float u_tiles;\nuniform float u_res;\nvec3 volCoord(){\n vec2 px = floor(vUv * u_atlas);\n vec2 tile = floor(px / u_res);\n float z = tile.y * u_tiles + tile.x;\n vec2 xy = px - tile * u_res;\n return (vec3(xy, z) + 0.5) / u_res;\n}\n\nvoid main(){\n vec3 p = volCoord();\n outColor = vec4(1.0 - worley3(p, 4.0), 1.0 - worley3(p, 8.0), 1.0 - worley3(p, 16.0), 1.0);\n}\n";
21
+ /**
22
+ * Weather map, 512² RGBA. Domain-warped so cell edges are not perlin-round.
23
+ * The warp offsets are themselves tileable, so the map still wraps exactly.
24
+ * R = coverage, low frequency B = cloud type bias
25
+ * G = coverage, high frequency A = precipitation
26
+ */
27
+ export declare const bakeWeatherFrag = "\n\n#define PI 3.14159265359\n#define saturate(x) clamp(x, 0.0, 1.0)\nfloat remap(float v, float a, float b, float c, float d){\n return c + (v - a) * (d - c) / max(b - a, 1e-6);\n}\n\nvec3 hash33t(vec3 p, float f){\n p = mod(p, vec3(f));\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yxx) * p.zyx);\n}\nvec2 hash22t(vec2 p, float f){\n p = mod(p, vec2(f));\n vec3 q = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));\n q += dot(q, q.yzx + 19.19);\n return fract((q.xx + q.yz) * q.zy);\n}\n\nfloat perlin3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n vec3 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n000 = dot(hash33t(i+vec3(0,0,0),f)*2.0-1.0, t-vec3(0,0,0));\n float n100 = dot(hash33t(i+vec3(1,0,0),f)*2.0-1.0, t-vec3(1,0,0));\n float n010 = dot(hash33t(i+vec3(0,1,0),f)*2.0-1.0, t-vec3(0,1,0));\n float n110 = dot(hash33t(i+vec3(1,1,0),f)*2.0-1.0, t-vec3(1,1,0));\n float n001 = dot(hash33t(i+vec3(0,0,1),f)*2.0-1.0, t-vec3(0,0,1));\n float n101 = dot(hash33t(i+vec3(1,0,1),f)*2.0-1.0, t-vec3(1,0,1));\n float n011 = dot(hash33t(i+vec3(0,1,1),f)*2.0-1.0, t-vec3(0,1,1));\n float n111 = dot(hash33t(i+vec3(1,1,1),f)*2.0-1.0, t-vec3(1,1,1));\n float x00 = mix(n000,n100,u.x), x10 = mix(n010,n110,u.x);\n float x01 = mix(n001,n101,u.x), x11 = mix(n011,n111,u.x);\n return mix(mix(x00,x10,u.y), mix(x01,x11,u.y), u.z);\n}\n\nfloat perlin2(vec2 x, float f){\n vec2 p = x * f;\n vec2 i = floor(p); vec2 t = p - i;\n vec2 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n00 = dot(hash22t(i+vec2(0,0),f)*2.0-1.0, t-vec2(0,0));\n float n10 = dot(hash22t(i+vec2(1,0),f)*2.0-1.0, t-vec2(1,0));\n float n01 = dot(hash22t(i+vec2(0,1),f)*2.0-1.0, t-vec2(0,1));\n float n11 = dot(hash22t(i+vec2(1,1),f)*2.0-1.0, t-vec2(1,1));\n return mix(mix(n00,n10,u.x), mix(n01,n11,u.x), u.y);\n}\n\nfloat worley3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n float md = 1e9;\n for(int z=-1; z<=1; z++)\n for(int y=-1; y<=1; y++)\n for(int w=-1; w<=1; w++){\n vec3 o = vec3(float(w), float(y), float(z));\n vec3 h = hash33t(i + o, f);\n vec3 d = o + h - t;\n md = min(md, dot(d, d));\n }\n return saturate(sqrt(md));\n}\n\n\nin vec2 vUv;\nout vec4 outColor;\n\nvoid main(){\n vec2 q = vUv;\n vec2 w = vec2(perlin2(q, 3.0), perlin2(q + vec2(0.37, 0.11), 3.0));\n vec2 qw = q + w * 0.11;\n float c1 = perlin2(qw, 3.0) * 0.60 + perlin2(qw, 6.0) * 0.28 + perlin2(qw, 12.0) * 0.12;\n float c2 = perlin2(qw, 7.0) * 0.52 + perlin2(qw, 14.0) * 0.30 + perlin2(qw, 28.0) * 0.18;\n float ty = perlin2(q + vec2(5.1, 2.3), 2.0);\n float pr = perlin2(q + vec2(1.7, 8.2), 5.0) * 0.7 + perlin2(q + vec2(1.7, 8.2), 10.0) * 0.3;\n outColor = vec4(\n saturate(c1 * 1.55 + 0.5),\n saturate(c2 * 1.60 + 0.5),\n saturate(ty * 1.60 + 0.5),\n saturate(pr * 1.60 + 0.5)\n );\n}\n";
28
+ /** Curl field, 128² RG. Curl of a scalar fbm — divergence free, so it swirls rather than pushes. */
29
+ export declare const bakeCurlFrag = "\n\n#define PI 3.14159265359\n#define saturate(x) clamp(x, 0.0, 1.0)\nfloat remap(float v, float a, float b, float c, float d){\n return c + (v - a) * (d - c) / max(b - a, 1e-6);\n}\n\nvec3 hash33t(vec3 p, float f){\n p = mod(p, vec3(f));\n p = fract(p * vec3(0.1031, 0.1030, 0.0973));\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yxx) * p.zyx);\n}\nvec2 hash22t(vec2 p, float f){\n p = mod(p, vec2(f));\n vec3 q = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));\n q += dot(q, q.yzx + 19.19);\n return fract((q.xx + q.yz) * q.zy);\n}\n\nfloat perlin3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n vec3 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n000 = dot(hash33t(i+vec3(0,0,0),f)*2.0-1.0, t-vec3(0,0,0));\n float n100 = dot(hash33t(i+vec3(1,0,0),f)*2.0-1.0, t-vec3(1,0,0));\n float n010 = dot(hash33t(i+vec3(0,1,0),f)*2.0-1.0, t-vec3(0,1,0));\n float n110 = dot(hash33t(i+vec3(1,1,0),f)*2.0-1.0, t-vec3(1,1,0));\n float n001 = dot(hash33t(i+vec3(0,0,1),f)*2.0-1.0, t-vec3(0,0,1));\n float n101 = dot(hash33t(i+vec3(1,0,1),f)*2.0-1.0, t-vec3(1,0,1));\n float n011 = dot(hash33t(i+vec3(0,1,1),f)*2.0-1.0, t-vec3(0,1,1));\n float n111 = dot(hash33t(i+vec3(1,1,1),f)*2.0-1.0, t-vec3(1,1,1));\n float x00 = mix(n000,n100,u.x), x10 = mix(n010,n110,u.x);\n float x01 = mix(n001,n101,u.x), x11 = mix(n011,n111,u.x);\n return mix(mix(x00,x10,u.y), mix(x01,x11,u.y), u.z);\n}\n\nfloat perlin2(vec2 x, float f){\n vec2 p = x * f;\n vec2 i = floor(p); vec2 t = p - i;\n vec2 u = t*t*t*(t*(t*6.0-15.0)+10.0);\n float n00 = dot(hash22t(i+vec2(0,0),f)*2.0-1.0, t-vec2(0,0));\n float n10 = dot(hash22t(i+vec2(1,0),f)*2.0-1.0, t-vec2(1,0));\n float n01 = dot(hash22t(i+vec2(0,1),f)*2.0-1.0, t-vec2(0,1));\n float n11 = dot(hash22t(i+vec2(1,1),f)*2.0-1.0, t-vec2(1,1));\n return mix(mix(n00,n10,u.x), mix(n01,n11,u.x), u.y);\n}\n\nfloat worley3(vec3 x, float f){\n vec3 p = x * f;\n vec3 i = floor(p); vec3 t = p - i;\n float md = 1e9;\n for(int z=-1; z<=1; z++)\n for(int y=-1; y<=1; y++)\n for(int w=-1; w<=1; w++){\n vec3 o = vec3(float(w), float(y), float(z));\n vec3 h = hash33t(i + o, f);\n vec3 d = o + h - t;\n md = min(md, dot(d, d));\n }\n return saturate(sqrt(md));\n}\n\n\nin vec2 vUv;\nout vec4 outColor;\n\nfloat fld(vec2 q){ return perlin2(q, 6.0) * 0.6 + perlin2(q, 12.0) * 0.3 + perlin2(q, 24.0) * 0.15; }\nvoid main(){\n float e = 1.0 / 128.0;\n float dx = fld(vUv + vec2(e, 0.0)) - fld(vUv - vec2(e, 0.0));\n float dy = fld(vUv + vec2(0.0, e)) - fld(vUv - vec2(0.0, e));\n vec2 c = clamp(vec2(dy, -dx) / (2.0 * e) / 26.0, -1.0, 1.0);\n outColor = vec4(c * 0.5 + 0.5, 0.0, 1.0);\n}\n";
30
+ //# sourceMappingURL=noiseBake.glsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noiseBake.glsl.d.ts","sourceRoot":"","sources":["../../../src/shaders/glsl/noiseBake.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,UAAU,mtEA8DtB,CAAA;AAED,eAAO,MAAM,UAAU,2FAGtB,CAAA;AAsBD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,w+FAexB,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,cAAc,6pFAQ1B,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,o2FAkB3B,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,YAAY,8nFAWxB,CAAA"}