@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,467 @@
1
+ import {
2
+ GLSL3,
3
+ Matrix4,
4
+ Uniform,
5
+ Vector2,
6
+ Vector3,
7
+ Vector4,
8
+ type BufferGeometry,
9
+ type Camera,
10
+ type Data3DTexture,
11
+ type DataArrayTexture,
12
+ type Group,
13
+ type Object3D,
14
+ type OrthographicCamera,
15
+ type PerspectiveCamera,
16
+ type Scene,
17
+ type Texture,
18
+ type WebGLRenderer
19
+ } from 'three'
20
+
21
+ import {
22
+ AtmosphereMaterialBase,
23
+ AtmosphereParameters,
24
+ type AtmosphereMaterialBaseUniforms
25
+ } from '@takram/three-atmosphere'
26
+ import {
27
+ parameters as atmosphereParameters,
28
+ functions
29
+ } from '@takram/three-atmosphere/shaders'
30
+ import {
31
+ assertType,
32
+ define,
33
+ defineExpression,
34
+ defineFloat,
35
+ defineInt,
36
+ Geodetic,
37
+ resolveIncludes,
38
+ unrollLoops
39
+ } from '@takram/three-geospatial'
40
+ import {
41
+ cascadedShadowMaps,
42
+ depth,
43
+ generators,
44
+ interleavedGradientNoise,
45
+ math,
46
+ raySphereIntersection,
47
+ turbo,
48
+ vogelDisk
49
+ } from '@takram/three-geospatial/shaders'
50
+
51
+ import { bayerOffsets } from './bayer'
52
+ import { defaults } from './qualityPresets'
53
+ import {
54
+ type AtmosphereUniforms,
55
+ type CloudLayerUniforms,
56
+ type CloudParameterUniforms
57
+ } from './uniforms'
58
+
59
+ import fragmentShader from './shaders/clouds.frag?raw'
60
+ import clouds from './shaders/clouds.glsl?raw'
61
+ import vertexShader from './shaders/clouds.vert?raw'
62
+ import parameters from './shaders/parameters.glsl?raw'
63
+ import types from './shaders/types.glsl?raw'
64
+
65
+ declare module 'three' {
66
+ interface Camera {
67
+ isPerspectiveCamera?: boolean
68
+ }
69
+ }
70
+
71
+ const vectorScratch = /*#__PURE__*/ new Vector3()
72
+ const geodeticScratch = /*#__PURE__*/ new Geodetic()
73
+
74
+ export interface CloudsMaterialParameters {
75
+ parameterUniforms: CloudParameterUniforms
76
+ layerUniforms: CloudLayerUniforms
77
+ atmosphereUniforms: AtmosphereUniforms
78
+ }
79
+
80
+ export interface CloudsMaterialUniforms
81
+ extends CloudParameterUniforms,
82
+ CloudLayerUniforms,
83
+ AtmosphereUniforms {
84
+ depthBuffer: Uniform<Texture | null>
85
+ viewMatrix: Uniform<Matrix4>
86
+ inverseProjectionMatrix: Uniform<Matrix4>
87
+ inverseViewMatrix: Uniform<Matrix4>
88
+ reprojectionMatrix: Uniform<Matrix4>
89
+ resolution: Uniform<Vector2>
90
+ cameraNear: Uniform<number>
91
+ cameraFar: Uniform<number>
92
+ cameraHeight: Uniform<number>
93
+ frame: Uniform<number>
94
+ temporalJitter: Uniform<Vector2>
95
+ targetUvScale: Uniform<Vector2>
96
+ mipLevelScale: Uniform<number>
97
+ stbnTexture: Uniform<Data3DTexture | null>
98
+
99
+ // Scattering
100
+ albedo: Uniform<Vector3>
101
+ skyIrradianceScale: Uniform<number>
102
+ groundIrradianceScale: Uniform<number>
103
+ powderScale: Uniform<number>
104
+ powderExponent: Uniform<number>
105
+
106
+ // Primary raymarch
107
+ maxIterationCount: Uniform<number>
108
+ minStepSize: Uniform<number>
109
+ maxStepSize: Uniform<number>
110
+ maxRayDistance: Uniform<number>
111
+ perspectiveStepScale: Uniform<number>
112
+ minDensity: Uniform<number>
113
+ minExtinction: Uniform<number>
114
+ minTransmittance: Uniform<number>
115
+
116
+ // Secondary raymarch
117
+ maxIterationCountToSun: Uniform<number>
118
+ maxIterationCountToGround: Uniform<number>
119
+ minSecondaryStepSize: Uniform<number>
120
+ secondaryStepScale: Uniform<number>
121
+
122
+ // Beer shadow map
123
+ shadowBuffer: Uniform<DataArrayTexture | null>
124
+ shadowTexelSize: Uniform<Vector2>
125
+ shadowIntervals: Uniform<Vector2[]>
126
+ shadowMatrices: Uniform<Matrix4[]>
127
+ shadowFar: Uniform<number>
128
+ maxShadowFilterRadius: Uniform<number>
129
+
130
+ // Shadow length
131
+ maxShadowLengthIterationCount: Uniform<number>
132
+ minShadowLengthStepSize: Uniform<number>
133
+ maxShadowLengthRayDistance: Uniform<number>
134
+
135
+ // Haze
136
+ hazeDensityScale: Uniform<number>
137
+ hazeExponent: Uniform<number>
138
+ }
139
+
140
+ export class CloudsMaterial extends AtmosphereMaterialBase {
141
+ declare uniforms: AtmosphereMaterialBaseUniforms & CloudsMaterialUniforms
142
+
143
+ temporalUpscale = true
144
+
145
+ private previousProjectionMatrix?: Matrix4
146
+ private previousViewMatrix?: Matrix4
147
+
148
+ constructor(
149
+ {
150
+ parameterUniforms,
151
+ layerUniforms,
152
+ atmosphereUniforms
153
+ }: CloudsMaterialParameters,
154
+ atmosphere = AtmosphereParameters.DEFAULT
155
+ ) {
156
+ super(
157
+ {
158
+ name: 'CloudsMaterial',
159
+ glslVersion: GLSL3,
160
+ vertexShader: resolveIncludes(vertexShader, {
161
+ atmosphere: {
162
+ parameters: atmosphereParameters,
163
+ functions
164
+ },
165
+ types
166
+ }),
167
+ fragmentShader: unrollLoops(
168
+ resolveIncludes(fragmentShader, {
169
+ core: {
170
+ depth,
171
+ math,
172
+ turbo,
173
+ generators,
174
+ raySphereIntersection,
175
+ cascadedShadowMaps,
176
+ interleavedGradientNoise,
177
+ vogelDisk
178
+ },
179
+ atmosphere: {
180
+ parameters: atmosphereParameters,
181
+ functions
182
+ },
183
+ types,
184
+ parameters,
185
+ clouds
186
+ })
187
+ ),
188
+ // prettier-ignore
189
+ uniforms: {
190
+ ...parameterUniforms,
191
+ ...layerUniforms,
192
+ ...atmosphereUniforms,
193
+
194
+ depthBuffer: new Uniform(null),
195
+ viewMatrix: new Uniform(new Matrix4()),
196
+ inverseProjectionMatrix: new Uniform(new Matrix4()),
197
+ inverseViewMatrix: new Uniform(new Matrix4()),
198
+ reprojectionMatrix: new Uniform(new Matrix4()),
199
+ resolution: new Uniform(new Vector2()),
200
+ cameraNear: new Uniform(0),
201
+ cameraFar: new Uniform(0),
202
+ cameraHeight: new Uniform(0),
203
+ frame: new Uniform(0),
204
+ temporalJitter: new Uniform(new Vector2()),
205
+ targetUvScale: new Uniform(new Vector2()),
206
+ mipLevelScale: new Uniform(1),
207
+ stbnTexture: new Uniform(null),
208
+
209
+ // Scattering
210
+ albedo: new Uniform(new Vector3()),
211
+ skyIrradianceScale: new Uniform(2.5),
212
+ groundIrradianceScale: new Uniform(3),
213
+ powderScale: new Uniform(0.8),
214
+ powderExponent: new Uniform(150),
215
+
216
+ // Primary raymarch
217
+ maxIterationCount: new Uniform(defaults.clouds.maxIterationCount),
218
+ minStepSize: new Uniform(defaults.clouds.minStepSize),
219
+ maxStepSize: new Uniform(defaults.clouds.maxStepSize),
220
+ maxRayDistance: new Uniform(defaults.clouds.maxRayDistance),
221
+ perspectiveStepScale: new Uniform(defaults.clouds.perspectiveStepScale),
222
+ minDensity: new Uniform(defaults.clouds.minDensity),
223
+ minExtinction: new Uniform(defaults.clouds.minExtinction),
224
+ minTransmittance: new Uniform(defaults.clouds.minTransmittance),
225
+
226
+ // Secondary raymarch
227
+ maxIterationCountToSun: new Uniform(defaults.clouds.maxIterationCountToSun),
228
+ maxIterationCountToGround: new Uniform(defaults.clouds.maxIterationCountToGround),
229
+ minSecondaryStepSize: new Uniform(defaults.clouds.minSecondaryStepSize),
230
+ secondaryStepScale: new Uniform(defaults.clouds.secondaryStepScale),
231
+
232
+ // Beer shadow map
233
+ shadowBuffer: new Uniform(null),
234
+ shadowTexelSize: new Uniform(new Vector2()),
235
+ shadowIntervals: new Uniform(
236
+ Array.from({ length: 4 }, () => new Vector2()) // Populate the max number of elements
237
+ ),
238
+ shadowMatrices: new Uniform(
239
+ Array.from({ length: 4 }, () => new Matrix4()) // Populate the max number of elements
240
+ ),
241
+ shadowFar: new Uniform(0),
242
+ maxShadowFilterRadius: new Uniform(6),
243
+ shadowLayerMask: new Uniform(new Vector4().setScalar(1)), // Disable mask
244
+
245
+ // Shadow length
246
+ maxShadowLengthIterationCount: new Uniform(defaults.clouds.maxShadowLengthIterationCount),
247
+ minShadowLengthStepSize: new Uniform(defaults.clouds.minShadowLengthStepSize),
248
+ maxShadowLengthRayDistance: new Uniform(defaults.clouds.maxShadowLengthRayDistance),
249
+
250
+ // Haze
251
+ hazeDensityScale: new Uniform(3e-5),
252
+ hazeExponent: new Uniform(1e-3)
253
+ } satisfies Partial<AtmosphereMaterialBaseUniforms> &
254
+ CloudsMaterialUniforms
255
+ },
256
+ atmosphere
257
+ )
258
+ }
259
+
260
+ override onBeforeRender(
261
+ renderer: WebGLRenderer,
262
+ scene: Scene,
263
+ camera: Camera,
264
+ geometry: BufferGeometry,
265
+ object: Object3D,
266
+ group: Group
267
+ ): void {
268
+ // Disable onBeforeRender in AtmosphereMaterialBase because we're rendering
269
+ // into fullscreen quad with another camera for the scene projection.
270
+
271
+ const uniforms = this.uniforms
272
+ uniforms.albedo.value.setScalar(
273
+ uniforms.scatteringCoefficient.value /
274
+ (uniforms.absorptionCoefficient.value +
275
+ uniforms.scatteringCoefficient.value)
276
+ )
277
+
278
+ const prevPowder = this.defines.POWDER != null
279
+ const nextPowder = this.uniforms.powderScale.value > 0
280
+ if (nextPowder !== prevPowder) {
281
+ if (nextPowder) {
282
+ this.defines.POWDER = '1'
283
+ } else {
284
+ delete this.defines.POWDER
285
+ }
286
+ this.needsUpdate = true
287
+ }
288
+
289
+ const prevGroundIrradiance = this.defines.GROUND_IRRADIANCE != null
290
+ const nextGroundIrradiance =
291
+ this.uniforms.groundIrradianceScale.value > 0 &&
292
+ this.uniforms.maxIterationCountToGround.value > 0
293
+ if (nextGroundIrradiance !== prevGroundIrradiance) {
294
+ if (nextPowder) {
295
+ this.defines.GROUND_IRRADIANCE = '1'
296
+ } else {
297
+ delete this.defines.GROUND_IRRADIANCE
298
+ }
299
+ this.needsUpdate = true
300
+ }
301
+ }
302
+
303
+ override copyCameraSettings(camera: Camera): void {
304
+ // Intentionally omit the call of super.
305
+
306
+ if (camera.isPerspectiveCamera === true) {
307
+ if (this.defines.PERSPECTIVE_CAMERA !== '1') {
308
+ this.defines.PERSPECTIVE_CAMERA = '1'
309
+ this.needsUpdate = true
310
+ }
311
+ } else {
312
+ if (this.defines.PERSPECTIVE_CAMERA != null) {
313
+ delete this.defines.PERSPECTIVE_CAMERA
314
+ this.needsUpdate = true
315
+ }
316
+ }
317
+
318
+ const uniforms = this.uniforms
319
+ uniforms.viewMatrix.value.copy(camera.matrixWorldInverse)
320
+ uniforms.inverseViewMatrix.value.copy(camera.matrixWorld)
321
+
322
+ const previousProjectionMatrix =
323
+ this.previousProjectionMatrix ?? camera.projectionMatrix
324
+ const previousViewMatrix =
325
+ this.previousViewMatrix ?? camera.matrixWorldInverse
326
+
327
+ const inverseProjectionMatrix = uniforms.inverseProjectionMatrix.value
328
+ const reprojectionMatrix = uniforms.reprojectionMatrix.value
329
+ if (this.temporalUpscale) {
330
+ const frame = uniforms.frame.value % 16
331
+ const resolution = uniforms.resolution.value
332
+ const offset = bayerOffsets[frame]
333
+ const dx = ((offset.x - 0.5) / resolution.x) * 4
334
+ const dy = ((offset.y - 0.5) / resolution.y) * 4
335
+ uniforms.temporalJitter.value.set(dx, dy)
336
+ uniforms.mipLevelScale.value = 0.25 // NOTE: Not exactly
337
+ inverseProjectionMatrix.copy(camera.projectionMatrix)
338
+ inverseProjectionMatrix.elements[8] += dx * 2
339
+ inverseProjectionMatrix.elements[9] += dy * 2
340
+ inverseProjectionMatrix.invert()
341
+
342
+ // Jitter the previous projection matrix with the current jitter.
343
+ reprojectionMatrix.copy(previousProjectionMatrix)
344
+ reprojectionMatrix.elements[8] += dx * 2
345
+ reprojectionMatrix.elements[9] += dy * 2
346
+ reprojectionMatrix.multiply(previousViewMatrix)
347
+ } else {
348
+ uniforms.temporalJitter.value.setScalar(0)
349
+ uniforms.mipLevelScale.value = 1
350
+ inverseProjectionMatrix.copy(camera.projectionMatrixInverse)
351
+ reprojectionMatrix
352
+ .copy(previousProjectionMatrix)
353
+ .multiply(previousViewMatrix)
354
+ }
355
+
356
+ assertType<PerspectiveCamera | OrthographicCamera>(camera)
357
+ uniforms.cameraNear.value = camera.near
358
+ uniforms.cameraFar.value = camera.far
359
+
360
+ const cameraPosition = camera.getWorldPosition(
361
+ uniforms.cameraPosition.value
362
+ )
363
+ const cameraPositionECEF = vectorScratch
364
+ .copy(cameraPosition)
365
+ .applyMatrix4(uniforms.inverseEllipsoidMatrix.value)
366
+ .sub(uniforms.ellipsoidCenter.value)
367
+
368
+ try {
369
+ uniforms.cameraHeight.value =
370
+ geodeticScratch.setFromECEF(cameraPositionECEF).height
371
+ } catch (error) {
372
+ // Abort when unable to project position to the ellipsoid surface.
373
+ }
374
+ }
375
+
376
+ // copyCameraSettings can be called multiple times within a frame. Only
377
+ // reliable way is to explicitly store the matrices.
378
+ copyReprojectionMatrix(camera: Camera): void {
379
+ this.previousProjectionMatrix ??= new Matrix4()
380
+ this.previousViewMatrix ??= new Matrix4()
381
+ this.previousProjectionMatrix.copy(camera.projectionMatrix)
382
+ this.previousViewMatrix.copy(camera.matrixWorldInverse)
383
+ }
384
+
385
+ setSize(
386
+ width: number,
387
+ height: number,
388
+ targetWidth?: number,
389
+ targetHeight?: number
390
+ ): void {
391
+ this.uniforms.resolution.value.set(width, height)
392
+ if (targetWidth != null && targetHeight != null) {
393
+ // The size of the high-resolution target buffer differs from the upscaled
394
+ // resolution, which is a multiple of 4. This must be corrected when
395
+ // reading from the depth buffer.
396
+ this.uniforms.targetUvScale.value.set(
397
+ width / targetWidth,
398
+ height / targetHeight
399
+ )
400
+ } else {
401
+ this.uniforms.targetUvScale.value.setScalar(1)
402
+ }
403
+
404
+ // Invalidate reprojection.
405
+ this.previousProjectionMatrix = undefined
406
+ this.previousViewMatrix = undefined
407
+ }
408
+
409
+ setShadowSize(width: number, height: number): void {
410
+ this.uniforms.shadowTexelSize.value.set(1 / width, 1 / height)
411
+ }
412
+
413
+ get depthBuffer(): Texture | null {
414
+ return this.uniforms.depthBuffer.value
415
+ }
416
+
417
+ set depthBuffer(value: Texture | null) {
418
+ this.uniforms.depthBuffer.value = value
419
+ }
420
+
421
+ @defineInt('DEPTH_PACKING')
422
+ depthPacking = 0
423
+
424
+ @defineExpression('LOCAL_WEATHER_CHANNELS', {
425
+ validate: value => /^[rgba]{4}$/.test(value)
426
+ })
427
+ localWeatherChannels = 'rgba'
428
+
429
+ @define('SHAPE_DETAIL')
430
+ shapeDetail: boolean = defaults.shapeDetail
431
+
432
+ @define('TURBULENCE')
433
+ turbulence: boolean = defaults.turbulence
434
+
435
+ @define('SHADOW_LENGTH')
436
+ shadowLength: boolean = defaults.lightShafts
437
+
438
+ @define('HAZE')
439
+ haze: boolean = defaults.haze
440
+
441
+ @defineInt('MULTI_SCATTERING_OCTAVES', { min: 1, max: 12 })
442
+ multiScatteringOctaves: number = defaults.clouds.multiScatteringOctaves
443
+
444
+ @define('ACCURATE_SUN_SKY_IRRADIANCE')
445
+ accurateSunSkyIrradiance: boolean = defaults.clouds.accurateSunSkyIrradiance
446
+
447
+ @define('ACCURATE_PHASE_FUNCTION')
448
+ accuratePhaseFunction: boolean = defaults.clouds.accuratePhaseFunction
449
+
450
+ @defineInt('SHADOW_CASCADE_COUNT', { min: 1, max: 4 })
451
+ shadowCascadeCount: number = defaults.shadow.cascadeCount
452
+
453
+ @defineInt('SHADOW_SAMPLE_COUNT', { min: 1, max: 16 })
454
+ shadowSampleCount = 8
455
+
456
+ // Ideally these should be uniforms, but perhaps due to the phase function
457
+ // is highly optimizable and used many times, defining them as macros
458
+ // improves fps by around 2-4, depending on the condition, though.
459
+ @defineFloat('SCATTER_ANISOTROPY_1')
460
+ scatterAnisotropy1 = 0.7
461
+
462
+ @defineFloat('SCATTER_ANISOTROPY_2')
463
+ scatterAnisotropy2 = -0.2
464
+
465
+ @defineFloat('SCATTER_ANISOTROPY_MIX')
466
+ scatterAnisotropyMix = 0.5
467
+ }