@takram/three-clouds 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +1130 -0
  3. package/assets/local_weather.png +0 -0
  4. package/assets/shape.bin +1 -0
  5. package/assets/shape_detail.bin +1 -0
  6. package/assets/turbulence.png +0 -0
  7. package/build/index.cjs +583 -0
  8. package/build/index.cjs.map +1 -0
  9. package/build/index.js +728 -0
  10. package/build/index.js.map +1 -0
  11. package/build/r3f.cjs +2 -0
  12. package/build/r3f.cjs.map +1 -0
  13. package/build/r3f.js +205 -0
  14. package/build/r3f.js.map +1 -0
  15. package/build/shared.cjs +2189 -0
  16. package/build/shared.cjs.map +1 -0
  17. package/build/shared.js +3825 -0
  18. package/build/shared.js.map +1 -0
  19. package/package.json +77 -0
  20. package/src/CascadedShadowMaps.ts +288 -0
  21. package/src/CloudLayer.ts +85 -0
  22. package/src/CloudLayers.test.ts +61 -0
  23. package/src/CloudLayers.ts +181 -0
  24. package/src/CloudShape.ts +22 -0
  25. package/src/CloudShapeDetail.ts +22 -0
  26. package/src/CloudsEffect.ts +810 -0
  27. package/src/CloudsMaterial.ts +467 -0
  28. package/src/CloudsPass.ts +285 -0
  29. package/src/CloudsResolveMaterial.ts +108 -0
  30. package/src/DensityProfile.ts +38 -0
  31. package/src/LocalWeather.ts +21 -0
  32. package/src/PassBase.ts +28 -0
  33. package/src/Procedural3DTexture.ts +94 -0
  34. package/src/ProceduralTexture.ts +94 -0
  35. package/src/ShaderArrayPass.ts +32 -0
  36. package/src/ShadowMaterial.ts +141 -0
  37. package/src/ShadowPass.ts +185 -0
  38. package/src/ShadowResolveMaterial.ts +72 -0
  39. package/src/Turbulence.ts +21 -0
  40. package/src/bayer.ts +23 -0
  41. package/src/constants.ts +8 -0
  42. package/src/helpers/FrustumCorners.ts +138 -0
  43. package/src/helpers/setArrayRenderTargetLayers.ts +32 -0
  44. package/src/helpers/splitFrustum.ts +59 -0
  45. package/src/index.ts +14 -0
  46. package/src/qualityPresets.ts +117 -0
  47. package/src/r3f/CloudLayer.tsx +95 -0
  48. package/src/r3f/CloudLayers.tsx +54 -0
  49. package/src/r3f/Clouds.tsx +278 -0
  50. package/src/r3f/index.ts +2 -0
  51. package/src/shaders/catmullRomSampling.glsl +113 -0
  52. package/src/shaders/cloudShape.frag +78 -0
  53. package/src/shaders/cloudShapeDetail.frag +56 -0
  54. package/src/shaders/clouds.frag +996 -0
  55. package/src/shaders/clouds.glsl +190 -0
  56. package/src/shaders/clouds.vert +69 -0
  57. package/src/shaders/cloudsEffect.frag +11 -0
  58. package/src/shaders/cloudsResolve.frag +202 -0
  59. package/src/shaders/cloudsResolve.vert +10 -0
  60. package/src/shaders/localWeather.frag +83 -0
  61. package/src/shaders/parameters.glsl +64 -0
  62. package/src/shaders/perlin.glsl +211 -0
  63. package/src/shaders/shadow.frag +197 -0
  64. package/src/shaders/shadow.vert +16 -0
  65. package/src/shaders/shadowResolve.frag +76 -0
  66. package/src/shaders/shadowResolve.vert +10 -0
  67. package/src/shaders/structuredSampling.glsl +101 -0
  68. package/src/shaders/tileableNoise.glsl +88 -0
  69. package/src/shaders/turbulence.frag +51 -0
  70. package/src/shaders/types.glsl +18 -0
  71. package/src/shaders/varianceClipping.glsl +114 -0
  72. package/src/uniforms.ts +218 -0
  73. package/types/CascadedShadowMaps.d.ts +52 -0
  74. package/types/CloudLayer.d.ts +26 -0
  75. package/types/CloudLayers.d.ts +21 -0
  76. package/types/CloudShape.d.ts +5 -0
  77. package/types/CloudShapeDetail.d.ts +5 -0
  78. package/types/CloudsEffect.d.ts +170 -0
  79. package/types/CloudsMaterial.d.ts +86 -0
  80. package/types/CloudsPass.d.ts +44 -0
  81. package/types/CloudsResolveMaterial.d.ts +30 -0
  82. package/types/DensityProfile.d.ts +12 -0
  83. package/types/LocalWeather.d.ts +5 -0
  84. package/types/PassBase.d.ts +14 -0
  85. package/types/Procedural3DTexture.d.ts +20 -0
  86. package/types/ProceduralTexture.d.ts +24 -0
  87. package/types/ShaderArrayPass.d.ts +7 -0
  88. package/types/ShadowMaterial.d.ts +34 -0
  89. package/types/ShadowPass.d.ts +34 -0
  90. package/types/ShadowResolveMaterial.d.ts +20 -0
  91. package/types/Turbulence.d.ts +5 -0
  92. package/types/bayer.d.ts +4 -0
  93. package/types/constants.d.ts +6 -0
  94. package/types/helpers/FrustumCorners.d.ts +18 -0
  95. package/types/helpers/setArrayRenderTargetLayers.d.ts +3 -0
  96. package/types/helpers/splitFrustum.d.ts +9 -0
  97. package/types/index.d.ts +13 -0
  98. package/types/qualityPresets.d.ts +46 -0
  99. package/types/r3f/CloudLayer.d.ts +7 -0
  100. package/types/r3f/CloudLayers.d.ts +15 -0
  101. package/types/r3f/Clouds.d.ts +16 -0
  102. package/types/r3f/index.d.ts +2 -0
  103. package/types/uniforms.d.ts +66 -0
@@ -0,0 +1,181 @@
1
+ import { type Vector3, type Vector4 } from 'three'
2
+
3
+ import { CloudLayer, type CloudLayerLike } from './CloudLayer'
4
+ import { type DensityProfileLike } from './DensityProfile'
5
+
6
+ type NumericKey = keyof {
7
+ [P in keyof CloudLayer as number extends CloudLayer[P] ? P : never]: any
8
+ }
9
+
10
+ interface Entry {
11
+ value: number
12
+ flag: 0 | 1
13
+ }
14
+
15
+ // prettier-ignore
16
+ const entriesScratch: Entry[] = /*#__PURE__*/ Array.from(
17
+ { length: 8 },
18
+ () => ({ value: 0, flag: 0 })
19
+ )
20
+ // prettier-ignore
21
+ const intervalsScratch = /*#__PURE__*/ Array.from(
22
+ { length: 3 },
23
+ () => ({ min: 0, max: 0 })
24
+ )
25
+
26
+ function compareEntries(a: Entry, b: Entry): number {
27
+ return a.value !== b.value ? a.value - b.value : a.flag - b.flag
28
+ }
29
+
30
+ export class CloudLayers extends Array<CloudLayer> {
31
+ static readonly DEFAULT = /*#__PURE__*/ new CloudLayers([
32
+ {
33
+ channel: 'r',
34
+ altitude: 750,
35
+ height: 650,
36
+ densityScale: 0.2,
37
+ shapeAmount: 1,
38
+ shapeDetailAmount: 1,
39
+ weatherExponent: 1,
40
+ shapeAlteringBias: 0.35,
41
+ coverageFilterWidth: 0.6,
42
+ shadow: true
43
+ },
44
+ {
45
+ channel: 'g',
46
+ altitude: 1000,
47
+ height: 1200,
48
+ densityScale: 0.2,
49
+ shapeAmount: 1,
50
+ shapeDetailAmount: 1,
51
+ weatherExponent: 1,
52
+ shapeAlteringBias: 0.35,
53
+ coverageFilterWidth: 0.6,
54
+ shadow: true
55
+ },
56
+ {
57
+ channel: 'b',
58
+ altitude: 7500,
59
+ height: 500,
60
+ densityScale: 0.003,
61
+ shapeAmount: 0.4,
62
+ shapeDetailAmount: 0,
63
+ weatherExponent: 1,
64
+ shapeAlteringBias: 0.35,
65
+ coverageFilterWidth: 0.5
66
+ },
67
+ { channel: 'a' }
68
+ ])
69
+
70
+ constructor(options?: readonly CloudLayerLike[]) {
71
+ super(
72
+ new CloudLayer(options?.[0]),
73
+ new CloudLayer(options?.[1]),
74
+ new CloudLayer(options?.[2]),
75
+ new CloudLayer(options?.[3])
76
+ )
77
+ }
78
+
79
+ set(options?: readonly CloudLayerLike[]): this {
80
+ this[0].set(options?.[0])
81
+ this[1].set(options?.[1])
82
+ this[2].set(options?.[2])
83
+ this[3].set(options?.[3])
84
+ return this
85
+ }
86
+
87
+ reset(): this {
88
+ this[0].copy(CloudLayer.DEFAULT)
89
+ this[1].copy(CloudLayer.DEFAULT)
90
+ this[2].copy(CloudLayer.DEFAULT)
91
+ this[3].copy(CloudLayer.DEFAULT)
92
+ return this
93
+ }
94
+
95
+ clone(): CloudLayers {
96
+ return new CloudLayers(this)
97
+ }
98
+
99
+ copy(other: CloudLayers): this {
100
+ this[0].copy(other[0])
101
+ this[1].copy(other[1])
102
+ this[2].copy(other[2])
103
+ this[3].copy(other[3])
104
+ return this
105
+ }
106
+
107
+ get localWeatherChannels(): string {
108
+ return this[0].channel + this[1].channel + this[2].channel + this[3].channel
109
+ }
110
+
111
+ packValues<K extends NumericKey>(key: K, result: Vector4): Vector4 {
112
+ return result.set(this[0][key], this[1][key], this[2][key], this[3][key])
113
+ }
114
+
115
+ packSums<A extends NumericKey, B extends NumericKey>(
116
+ a: A,
117
+ b: B,
118
+ result: Vector4
119
+ ): Vector4 {
120
+ return result.set(
121
+ this[0][a] + this[0][b],
122
+ this[1][a] + this[1][b],
123
+ this[2][a] + this[2][b],
124
+ this[3][a] + this[3][b]
125
+ )
126
+ }
127
+
128
+ packDensityProfiles<K extends keyof DensityProfileLike>(
129
+ key: K,
130
+ result: Vector4
131
+ ): Vector4 {
132
+ return result.set(
133
+ this[0].densityProfile[key],
134
+ this[1].densityProfile[key],
135
+ this[2].densityProfile[key],
136
+ this[3].densityProfile[key]
137
+ )
138
+ }
139
+
140
+ // Redundant, but need to avoid creating garbage here as this runs every frame.
141
+ packIntervalHeights(minIntervals: Vector3, maxIntervals: Vector3): void {
142
+ for (let i = 0; i < 4; ++i) {
143
+ const layer = this[i]
144
+ let entry = entriesScratch[i]
145
+ entry.value = layer.altitude
146
+ entry.flag = 0
147
+ entry = entriesScratch[i + 4]
148
+ entry.value = layer.altitude + layer.height
149
+ entry.flag = 1
150
+ }
151
+ entriesScratch.sort(compareEntries)
152
+
153
+ // Reference: https://dilipkumar.medium.com/interval-coding-pattern-068c36197cf5
154
+ let intervalIndex = 0
155
+ let balance = 0
156
+ for (let entryIndex = 0; entryIndex < entriesScratch.length; ++entryIndex) {
157
+ const { value, flag } = entriesScratch[entryIndex]
158
+ if (balance === 0 && entryIndex > 0) {
159
+ const interval = intervalsScratch[intervalIndex++]
160
+ interval.min = entriesScratch[entryIndex - 1].value
161
+ interval.max = value
162
+ }
163
+ balance += flag === 0 ? 1 : -1
164
+ }
165
+ for (; intervalIndex < 3; ++intervalIndex) {
166
+ const interval = intervalsScratch[intervalIndex]
167
+ interval.min = 0
168
+ interval.max = 0
169
+ }
170
+
171
+ let interval = intervalsScratch[0]
172
+ minIntervals.x = interval.min
173
+ maxIntervals.x = interval.max
174
+ interval = intervalsScratch[1]
175
+ minIntervals.y = interval.min
176
+ maxIntervals.y = interval.max
177
+ interval = intervalsScratch[2]
178
+ minIntervals.z = interval.min
179
+ maxIntervals.z = interval.max
180
+ }
181
+ }
@@ -0,0 +1,22 @@
1
+ import { resolveIncludes } from '@takram/three-geospatial'
2
+ import { math } from '@takram/three-geospatial/shaders'
3
+
4
+ import { CLOUD_SHAPE_TEXTURE_SIZE } from './constants'
5
+ import { Procedural3DTextureBase } from './Procedural3DTexture'
6
+
7
+ import fragmentShader from './shaders/cloudShape.frag?raw'
8
+ import perlin from './shaders/perlin.glsl?raw'
9
+ import tileableNoise from './shaders/tileableNoise.glsl?raw'
10
+
11
+ export class CloudShape extends Procedural3DTextureBase {
12
+ constructor() {
13
+ super({
14
+ size: CLOUD_SHAPE_TEXTURE_SIZE,
15
+ fragmentShader: resolveIncludes(fragmentShader, {
16
+ core: { math },
17
+ perlin,
18
+ tileableNoise
19
+ })
20
+ })
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ import { resolveIncludes } from '@takram/three-geospatial'
2
+ import { math } from '@takram/three-geospatial/shaders'
3
+
4
+ import { CLOUD_SHAPE_DETAIL_TEXTURE_SIZE } from './constants'
5
+ import { Procedural3DTextureBase } from './Procedural3DTexture'
6
+
7
+ import fragmentShader from './shaders/cloudShapeDetail.frag?raw'
8
+ import perlin from './shaders/perlin.glsl?raw'
9
+ import tileableNoise from './shaders/tileableNoise.glsl?raw'
10
+
11
+ export class CloudShapeDetail extends Procedural3DTextureBase {
12
+ constructor() {
13
+ super({
14
+ size: CLOUD_SHAPE_DETAIL_TEXTURE_SIZE,
15
+ fragmentShader: resolveIncludes(fragmentShader, {
16
+ core: { math },
17
+ perlin,
18
+ tileableNoise
19
+ })
20
+ })
21
+ }
22
+ }