@@ -20,38 +20,179 @@ const _lightOrientationMatrix = new Matrix4();
20
20
const _lightOrientationMatrixInverse = new Matrix4 ( ) ;
21
21
const _up = new Vector3 ( 0 , 1 , 0 ) ;
22
22
23
+ /**
24
+ * An implementation of Cascade Shadow Maps (CSM).
25
+ *
26
+ * This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
27
+ * use {@link CSMShadowNode} instead.
28
+ */
23
29
export class CSM {
24
30
31
+ /**
32
+ * Constructs a new CSM instance.
33
+ *
34
+ * @param {CSM~Data } data - The CSM data.
35
+ */
25
36
constructor ( data ) {
26
37
38
+ /**
39
+ * The scene's camera.
40
+ *
41
+ * @type {Camera }
42
+ */
27
43
this . camera = data . camera ;
44
+
45
+ /**
46
+ * The parent object, usually the scene.
47
+ *
48
+ * @type {Object3D }
49
+ */
28
50
this . parent = data . parent ;
51
+
52
+ /**
53
+ * The number of cascades.
54
+ *
55
+ * @type {number }
56
+ * @default 3
57
+ */
29
58
this . cascades = data . cascades || 3 ;
59
+
60
+ /**
61
+ * The maximum far value.
62
+ *
63
+ * @type {number }
64
+ * @default 100000
65
+ */
30
66
this . maxFar = data . maxFar || 100000 ;
67
+
68
+ /**
69
+ * The frustum split mode.
70
+ *
71
+ * @type {('practical'|'uniform'|'logarithmic'|'custom') }
72
+ * @default 'practical'
73
+ */
31
74
this . mode = data . mode || 'practical' ;
75
+
76
+ /**
77
+ * The shadow map size.
78
+ *
79
+ * @type {number }
80
+ * @default 2048
81
+ */
32
82
this . shadowMapSize = data . shadowMapSize || 2048 ;
83
+
84
+ /**
85
+ * The shadow bias.
86
+ *
87
+ * @type {number }
88
+ * @default 0.000001
89
+ */
33
90
this . shadowBias = data . shadowBias || 0.000001 ;
91
+
92
+ /**
93
+ * The light direction.
94
+ *
95
+ * @type {Vector3 }
96
+ */
34
97
this . lightDirection = data . lightDirection || new Vector3 ( 1 , - 1 , 1 ) . normalize ( ) ;
98
+
99
+ /**
100
+ * The light intensity.
101
+ *
102
+ * @type {number }
103
+ * @default 3
104
+ */
35
105
this . lightIntensity = data . lightIntensity || 3 ;
106
+
107
+ /**
108
+ * The light near value.
109
+ *
110
+ * @type {number }
111
+ * @default 1
112
+ */
36
113
this . lightNear = data . lightNear || 1 ;
114
+
115
+ /**
116
+ * The light far value.
117
+ *
118
+ * @type {number }
119
+ * @default 2000
120
+ */
37
121
this . lightFar = data . lightFar || 2000 ;
122
+
123
+ /**
124
+ * The light margin.
125
+ *
126
+ * @type {number }
127
+ * @default 200
128
+ */
38
129
this . lightMargin = data . lightMargin || 200 ;
130
+
131
+ /**
132
+ * Custom split callback when using `mode='custom'`.
133
+ *
134
+ * @type {Function }
135
+ */
39
136
this . customSplitsCallback = data . customSplitsCallback ;
137
+
138
+ /**
139
+ * Whether to fade between cascades or not.
140
+ *
141
+ * @type {boolean }
142
+ * @default false
143
+ */
40
144
this . fade = false ;
145
+
146
+ /**
147
+ * The main frustum.
148
+ *
149
+ * @type {CSMFrustum }
150
+ */
41
151
this . mainFrustum = new CSMFrustum ( { webGL : true } ) ;
152
+
153
+ /**
154
+ * An array of frustums representing the cascades.
155
+ *
156
+ * @type {Array<CSMFrustum> }
157
+ */
42
158
this . frustums = [ ] ;
159
+
160
+ /**
161
+ * An array of numbers in the range `[0,1]` the defines how the
162
+ * mainCSM frustum should be split up.
163
+ *
164
+ * @type {Array<number> }
165
+ */
43
166
this . breaks = [ ] ;
44
167
168
+ /**
169
+ * An array of directional lights which cast the shadows for
170
+ * the different cascades. There is one directional light for each
171
+ * cascade.
172
+ *
173
+ * @type {Array<DirectionalLight> }
174
+ */
45
175
this . lights = [ ] ;
176
+
177
+ /**
178
+ * A Map holding enhanced material shaders.
179
+ *
180
+ * @type {Map<Material,Object> }
181
+ */
46
182
this . shaders = new Map ( ) ;
47
183
48
- this . createLights ( ) ;
184
+ this . _createLights ( ) ;
49
185
this . updateFrustums ( ) ;
50
- this . injectInclude ( ) ;
186
+ this . _injectInclude ( ) ;
51
187
52
188
}
53
189
54
- createLights ( ) {
190
+ /**
191
+ * Creates the directional lights of this CSM instance.
192
+ *
193
+ * @private
194
+ */
195
+ _createLights ( ) {
55
196
56
197
for ( let i = 0 ; i < this . cascades ; i ++ ) {
57
198
@@ -72,7 +213,12 @@ export class CSM {
72
213
73
214
}
74
215
75
- initCascades ( ) {
216
+ /**
217
+ * Inits the cascades according to the scene's camera and breaks configuration.
218
+ *
219
+ * @private
220
+ */
221
+ _initCascades ( ) {
76
222
77
223
const camera = this . camera ;
78
224
camera . updateProjectionMatrix ( ) ;
@@ -81,7 +227,12 @@ export class CSM {
81
227
82
228
}
83
229
84
- updateShadowBounds ( ) {
230
+ /**
231
+ * Updates the shadow bounds of this CSM instance.
232
+ *
233
+ * @private
234
+ */
235
+ _updateShadowBounds ( ) {
85
236
86
237
const frustums = this . frustums ;
87
238
for ( let i = 0 ; i < frustums . length ; i ++ ) {
@@ -130,7 +281,13 @@ export class CSM {
130
281
131
282
}
132
283
133
- getBreaks ( ) {
284
+ /**
285
+ * Computes the breaks of this CSM instance based on the scene's camera, number of cascades
286
+ * and the selected split mode.
287
+ *
288
+ * @private
289
+ */
290
+ _getBreaks ( ) {
134
291
135
292
const camera = this . camera ;
136
293
const far = Math . min ( camera . far , this . maxFar ) ;
@@ -197,6 +354,10 @@ export class CSM {
197
354
198
355
}
199
356
357
+ /**
358
+ * Updates the CSM. This method must be called in your animation loop before
359
+ * calling `renderer.render()`.
360
+ */
200
361
update ( ) {
201
362
202
363
const camera = this . camera ;
@@ -243,13 +404,23 @@ export class CSM {
243
404
244
405
}
245
406
246
- injectInclude ( ) {
407
+ /**
408
+ * Injects the CSM shader enhancements into the built-in materials.
409
+ *
410
+ * @private
411
+ */
412
+ _injectInclude ( ) {
247
413
248
414
ShaderChunk . lights_fragment_begin = CSMShader . lights_fragment_begin ;
249
415
ShaderChunk . lights_pars_begin = CSMShader . lights_pars_begin ;
250
416
251
417
}
252
418
419
+ /**
420
+ * Applications must call this method for all materials that should be affected by CSM.
421
+ *
422
+ * @param {Material } material - The material to setup for CSM support.
423
+ */
253
424
setupMaterial ( material ) {
254
425
255
426
material . defines = material . defines || { } ;
@@ -269,7 +440,7 @@ export class CSM {
269
440
material . onBeforeCompile = function ( shader ) {
270
441
271
442
const far = Math . min ( scope . camera . far , scope . maxFar ) ;
272
- scope . getExtendedBreaks ( breaksVec2 ) ;
443
+ scope . _getExtendedBreaks ( breaksVec2 ) ;
273
444
274
445
shader . uniforms . CSM_cascades = { value : breaksVec2 } ;
275
446
shader . uniforms . cameraNear = { value : scope . camera . near } ;
@@ -283,7 +454,12 @@ export class CSM {
283
454
284
455
}
285
456
286
- updateUniforms ( ) {
457
+ /**
458
+ * Updates the CSM uniforms.
459
+ *
460
+ * @private
461
+ */
462
+ _updateUniforms ( ) {
287
463
288
464
const far = Math . min ( this . camera . far , this . maxFar ) ;
289
465
const shaders = this . shaders ;
@@ -293,7 +469,7 @@ export class CSM {
293
469
if ( shader !== null ) {
294
470
295
471
const uniforms = shader . uniforms ;
296
- this . getExtendedBreaks ( uniforms . CSM_cascades . value ) ;
472
+ this . _getExtendedBreaks ( uniforms . CSM_cascades . value ) ;
297
473
uniforms . cameraNear . value = this . camera . near ;
298
474
uniforms . shadowFar . value = far ;
299
475
@@ -315,7 +491,13 @@ export class CSM {
315
491
316
492
}
317
493
318
- getExtendedBreaks ( target ) {
494
+ /**
495
+ * Computes the extended breaks for the CSM uniforms.
496
+ *
497
+ * @private
498
+ * @param {Array<Vector2> } target - The target array that holds the extended breaks.
499
+ */
500
+ _getExtendedBreaks ( target ) {
319
501
320
502
while ( target . length < this . breaks . length ) {
321
503
@@ -336,15 +518,21 @@ export class CSM {
336
518
337
519
}
338
520
521
+ /**
522
+ * Applications must call this method every time they change camera or CSM settings.
523
+ */
339
524
updateFrustums ( ) {
340
525
341
- this . getBreaks ( ) ;
342
- this . initCascades ( ) ;
343
- this . updateShadowBounds ( ) ;
344
- this . updateUniforms ( ) ;
526
+ this . _getBreaks ( ) ;
527
+ this . _initCascades ( ) ;
528
+ this . _updateShadowBounds ( ) ;
529
+ this . _updateUniforms ( ) ;
345
530
346
531
}
347
532
533
+ /**
534
+ * Applications must call this method when they remove the CSM usage from their scene.
535
+ */
348
536
remove ( ) {
349
537
350
538
for ( let i = 0 ; i < this . lights . length ; i ++ ) {
@@ -356,6 +544,10 @@ export class CSM {
356
544
357
545
}
358
546
547
+ /**
548
+ * Frees the GPU-related resources allocated by this instance. Call this
549
+ * method whenever this instance is no longer used in your app.
550
+ */
359
551
dispose ( ) {
360
552
361
553
const shaders = this . shaders ;
@@ -382,3 +574,22 @@ export class CSM {
382
574
}
383
575
384
576
}
577
+
578
+ /**
579
+ * Constructor data of `CSM`.
580
+ *
581
+ * @typedef {Object } CSM~Data
582
+ * @property {Camera } camera - The scene's camera.
583
+ * @property {Object3D } parent - The parent object, usually the scene.
584
+ * @property {number } [cascades=3] - The number of cascades.
585
+ * @property {number } [maxFar=100000] - The maximum far value.
586
+ * @property {('practical'|'uniform'|'logarithmic'|'custom') } [mode='practical'] - The frustum split mode.
587
+ * @property {Function } [customSplitsCallback] - Custom split callback when using `mode='custom'`.
588
+ * @property {number } [shadowMapSize=2048] - The shadow map size.
589
+ * @property {number } [shadowBias=0.000001] - The shadow bias.
590
+ * @property {Vector3 } [lightDirection] - The light direction.
591
+ * @property {number } [lightIntensity=3] - The light intensity.
592
+ * @property {number } [lightNear=1] - The light near value.
593
+ * @property {number } [lightNear=2000] - The light far value.
594
+ * @property {number } [lightMargin=200] - The light margin.
595
+ **/
0 commit comments