@@ -13,6 +13,7 @@ import {
13
13
SHADOWUPDATE_NONE , SHADOWUPDATE_REALTIME , SHADOWUPDATE_THISFRAME ,
14
14
LIGHTSHAPE_PUNCTUAL
15
15
} from './constants.js' ;
16
+ import { ShadowRenderer } from './renderer/shadow-renderer.js' ;
16
17
17
18
var spotCenter = new Vec3 ( ) ;
18
19
var spotEndPoint = new Vec3 ( ) ;
@@ -28,30 +29,46 @@ const directionalCascades = [
28
29
[ new Vec4 ( 0 , 0 , 0.5 , 0.5 ) , new Vec4 ( 0 , 0.5 , 0.5 , 0.5 ) , new Vec4 ( 0.5 , 0 , 0.5 , 0.5 ) , new Vec4 ( 0.5 , 0.5 , 0.5 , 0.5 ) ]
29
30
] ;
30
31
31
- // Class storing rendering related private information
32
+ // Class storing shadow rendering related private information
32
33
class LightRenderData {
33
- constructor ( camera , face , lightType ) {
34
+ constructor ( device , camera , face , light ) {
35
+
36
+ // light this data belongs to
37
+ this . light = light ;
34
38
35
39
// camera this applies to. Only used by directional light, as directional shadow map
36
40
// is culled and rendered for each camera. Local lights' shadow is culled and rendered one time
37
41
// and shared between cameras (even though it's not strictly correct and we can get shadows
38
42
// from a mesh that is not visible by the camera)
39
43
this . camera = camera ;
40
44
45
+ // camera used to cull / render the shadow map
46
+ this . shadowCamera = ShadowRenderer . createShadowCamera ( device , light . _shadowType , light . _type , face ) ;
47
+
41
48
// face index, value is based on light type:
42
49
// - spot: always 0
43
50
// - omni: cubemap face, 0..5
44
51
// - directional: 0 for simple shadows, cascade index for cascaded shadow map
45
52
this . face = face ;
46
53
47
- // shadow camera settings, only used by directional lights
48
- this . position = lightType === LIGHTTYPE_DIRECTIONAL ? new Vec3 ( ) : null ;
49
- this . orthoHeight = 0 ;
50
- this . farClip = 0 ;
51
-
52
54
// visible shadow casters
53
55
this . visibleCasters = [ ] ;
54
56
}
57
+
58
+ // returns shadow buffer currently attached to the shadow camera
59
+ get shadowBuffer ( ) {
60
+ const rt = this . shadowCamera . renderTarget ;
61
+ if ( rt ) {
62
+ const light = this . light ;
63
+ if ( light . _type === LIGHTTYPE_OMNI ) {
64
+ return rt . colorBuffer ;
65
+ }
66
+
67
+ return light . _isPcf && light . device . webgl2 ? rt . depthBuffer : rt . colorBuffer ;
68
+ }
69
+
70
+ return null ;
71
+ }
55
72
}
56
73
57
74
/**
@@ -116,22 +133,21 @@ class Light {
116
133
this . _outerConeAngleCos = Math . cos ( this . _outerConeAngle * Math . PI / 180 ) ;
117
134
118
135
// Shadow mapping resources
119
- this . _shadowCamera = null ;
136
+ this . _shadowMap = null ;
120
137
this . _shadowMatrix = new Mat4 ( ) ;
138
+ this . _rendererParams = [ ] ;
139
+
140
+ // Shadow mapping properties
121
141
this . shadowDistance = 40 ;
122
142
this . _shadowResolution = 1024 ;
123
143
this . shadowBias = - 0.0005 ;
124
144
this . _normalOffsetBias = 0.0 ;
125
145
this . shadowUpdateMode = SHADOWUPDATE_REALTIME ;
146
+ this . _isVsm = false ;
147
+ this . _isPcf = true ;
126
148
127
149
this . _scene = null ;
128
150
this . _node = null ;
129
- this . _rendererParams = [ ] ;
130
-
131
- this . _isVsm = false ;
132
- this . _isPcf = true ;
133
- this . _cacheShadowMap = false ;
134
- this . _isCachedShadowMap = false ;
135
151
136
152
// private rendering data
137
153
this . _renderData = [ ] ;
@@ -145,6 +161,24 @@ class Light {
145
161
this . _renderData = null ;
146
162
}
147
163
164
+ // destroys shadow map related resources, called when shadow properties change and resources
165
+ // need to be recreated
166
+ _destroyShadowMap ( ) {
167
+
168
+ this . _renderData . length = 0 ;
169
+
170
+ if ( this . _shadowMap ) {
171
+ if ( ! this . _shadowMap . cached ) {
172
+ this . _shadowMap . destroy ( ) ;
173
+ }
174
+ this . _shadowMap = null ;
175
+ }
176
+
177
+ if ( this . shadowUpdateMode === SHADOWUPDATE_NONE ) {
178
+ this . shadowUpdateMode = SHADOWUPDATE_THISFRAME ;
179
+ }
180
+ }
181
+
148
182
// returns LightRenderData with matching camera and face
149
183
getRenderData ( camera , face ) {
150
184
@@ -157,7 +191,7 @@ class Light {
157
191
}
158
192
159
193
// create new one
160
- const rd = new LightRenderData ( camera , face , this . _type ) ;
194
+ const rd = new LightRenderData ( this . device , camera , face , this ) ;
161
195
this . _renderData . push ( rd ) ;
162
196
return rd ;
163
197
}
@@ -225,6 +259,17 @@ class Light {
225
259
this . cascades = directionalCascades [ value - 1 ] ;
226
260
}
227
261
262
+ get shadowMap ( ) {
263
+ return this . _shadowMap ;
264
+ }
265
+
266
+ set shadowMap ( shadowMap ) {
267
+ if ( this . _shadowMap !== shadowMap ) {
268
+ this . _destroyShadowMap ( ) ;
269
+ this . _shadowMap = shadowMap ;
270
+ }
271
+ }
272
+
228
273
getColor ( ) {
229
274
return this . _color ;
230
275
}
@@ -317,54 +362,16 @@ class Light {
317
362
this . _updateFinalColor ( ) ;
318
363
}
319
364
320
- get shadowMap ( ) {
321
-
322
- if ( this . _shadowCamera ) {
323
- const rt = this . _shadowCamera . renderTarget ;
324
- if ( this . _type === LIGHTTYPE_OMNI ) {
325
- return rt . colorBuffer ;
326
- }
327
-
328
- return this . _isPcf && this . device . webgl2 ? rt . depthBuffer : rt . colorBuffer ;
329
- }
330
-
331
- return null ;
332
- }
333
-
334
- _destroyShadowMap ( ) {
335
- if ( this . _shadowCamera ) {
336
- if ( ! this . _isCachedShadowMap ) {
337
- var rt = this . _shadowCamera . renderTarget ;
338
- var i ;
339
- if ( rt ) {
340
- if ( rt . length ) {
341
- for ( i = 0 ; i < rt . length ; i ++ ) {
342
- rt [ i ] . destroyTextureBuffers ( ) ;
343
- rt [ i ] . destroy ( ) ;
344
- }
345
- } else {
346
- rt . destroyTextureBuffers ( ) ;
347
- rt . destroy ( ) ;
348
- }
349
- }
350
- }
351
- this . _shadowCamera . renderTarget = null ;
352
- this . _shadowCamera = null ;
353
- this . _shadowCubeMap = null ;
354
- if ( this . shadowUpdateMode === SHADOWUPDATE_NONE ) {
355
- this . shadowUpdateMode = SHADOWUPDATE_THISFRAME ;
356
- }
357
- }
358
- }
359
-
360
365
updateShadow ( ) {
361
366
if ( this . shadowUpdateMode !== SHADOWUPDATE_REALTIME ) {
362
367
this . shadowUpdateMode = SHADOWUPDATE_THISFRAME ;
363
368
}
364
369
}
365
370
366
371
layersDirty ( ) {
367
- this . _scene . layers . _dirtyLights = true ;
372
+ if ( this . _scene ?. layers ) {
373
+ this . _scene . layers . _dirtyLights = true ;
374
+ }
368
375
}
369
376
370
377
updateKey ( ) {
@@ -401,7 +408,7 @@ class Light {
401
408
}
402
409
403
410
if ( key !== this . key && this . _scene !== null ) {
404
- // TODO: most of the changes to the key should not invalidate the composition,
411
+ // TODO: most of the changes to the key should not invalidate the composition,
405
412
// probably only _type and _castShadows
406
413
this . layersDirty ( ) ;
407
414
}
@@ -430,7 +437,7 @@ class Light {
430
437
return this . _shape ;
431
438
}
432
439
433
- set shape ( value = LIGHTSHAPE_PUNCTUAL ) {
440
+ set shape ( value ) {
434
441
if ( this . _shape === value )
435
442
return ;
436
443
@@ -490,27 +497,28 @@ class Light {
490
497
}
491
498
492
499
set castShadows ( value ) {
493
- if ( this . _castShadows === value )
494
- return ;
495
-
496
- this . _castShadows = value ;
497
- this . updateKey ( ) ;
500
+ if ( this . _castShadows !== value ) {
501
+ this . _castShadows = value ;
502
+ this . _destroyShadowMap ( ) ;
503
+ this . layersDirty ( ) ;
504
+ this . updateKey ( ) ;
505
+ }
498
506
}
499
507
500
508
get shadowResolution ( ) {
501
509
return this . _shadowResolution ;
502
510
}
503
511
504
512
set shadowResolution ( value ) {
505
- if ( this . _shadowResolution === value )
506
- return ;
507
-
508
- if ( this . _type === LIGHTTYPE_OMNI ) {
509
- value = Math . min ( value , this . device . maxCubeMapSize ) ;
510
- } else {
511
- value = Math . min ( value , this . device . maxTextureSize ) ;
513
+ if ( this . _shadowResolution !== value ) {
514
+ if ( this . _type === LIGHTTYPE_OMNI ) {
515
+ value = Math . min ( value , this . device . maxCubeMapSize ) ;
516
+ } else {
517
+ value = Math . min ( value , this . device . maxTextureSize ) ;
518
+ }
519
+ this . _shadowResolution = value ;
520
+ this . _destroyShadowMap ( ) ;
512
521
}
513
- this . _shadowResolution = value ;
514
522
}
515
523
516
524
get vsmBlurSize ( ) {
0 commit comments