44 * @license {@link https://opensource.org/licenses/MIT|MIT License }
55 */
66
7+ var CircleToRectangle = require ( '../../geom/intersects/CircleToRectangle' ) ;
78var Class = require ( '../../utils/Class' ) ;
9+ var DistanceBetween = require ( '../../math/distance/DistanceBetween' ) ;
810var Light = require ( './Light' ) ;
911var PointLight = require ( '../pointlight/PointLight' ) ;
12+ var RGB = require ( '../../display/RGB' ) ;
13+ var SpliceOne = require ( '../../utils/array/SpliceOne' ) ;
14+ var StableSort = require ( '../../utils/array/StableSort' ) ;
1015var Utils = require ( '../../renderer/webgl/Utils' ) ;
1116
1217/**
@@ -32,18 +37,6 @@ var LightsManager = new Class({
3237
3338 function LightsManager ( )
3439 {
35- /**
36- * The pool of Lights.
37- *
38- * Used to recycle removed Lights for a more efficient use of memory.
39- *
40- * @name Phaser.GameObjects.LightsManager#lightPool
41- * @type {Phaser.GameObjects.Light[] }
42- * @default []
43- * @since 3.0.0
44- */
45- this . lightPool = [ ] ;
46-
4740 /**
4841 * The Lights in the Scene.
4942 *
@@ -54,26 +47,14 @@ var LightsManager = new Class({
5447 */
5548 this . lights = [ ] ;
5649
57- /**
58- * Lights that have been culled from a Camera's viewport.
59- *
60- * Lights in this list will not be rendered.
61- *
62- * @name Phaser.GameObjects.LightsManager#culledLights
63- * @type {Phaser.GameObjects.Light[] }
64- * @default []
65- * @since 3.0.0
66- */
67- this . culledLights = [ ] ;
68-
6950 /**
7051 * The ambient color.
7152 *
7253 * @name Phaser.GameObjects.LightsManager#ambientColor
73- * @type {{ r: number, g: number, b: number } }
74- * @since 3.0 .0
54+ * @type {Phaser.Display.RGB }
55+ * @since 3.50 .0
7556 */
76- this . ambientColor = { r : 0.1 , g : 0.1 , b : 0.1 } ;
57+ this . ambientColor = new RGB ( 0.1 , 0.1 , 0.1 ) ;
7758
7859 /**
7960 * Whether the Lights Manager is enabled.
@@ -95,6 +76,16 @@ var LightsManager = new Class({
9576 * @since 3.15.0
9677 */
9778 this . maxLights = - 1 ;
79+
80+ /**
81+ * The number of lights that the LightPipeline processed in the _previous_ frame.
82+ *
83+ * @name Phaser.GameObjects.LightsManager#visibleLights
84+ * @type {number }
85+ * @readonly
86+ * @since 3.50.0
87+ */
88+ this . visibleLights = 0 ;
9889 } ,
9990
10091 addPointLight : function ( x , y , color , radius , intensity )
@@ -138,77 +129,59 @@ var LightsManager = new Class({
138129 } ,
139130
140131 /**
141- * Cull any Lights that aren't visible to the given Camera.
132+ * Get all lights that can be seen by the given Camera.
142133 *
143- * Culling Lights improves performance by ensuring that only Lights within a Camera's viewport are rendered .
134+ * It will automatically cull lights that are outside the world view of the Camera .
144135 *
145- * @method Phaser.GameObjects.LightsManager#cull
146- * @since 3.0.0
136+ * If more lights are returned than supported by the pipeline, the lights are then culled
137+ * based on the distance from the center of the camera. Only those closest are rendered.
138+ *
139+ * @method Phaser.GameObjects.LightsManager#getLights
140+ * @since 3.50.0
147141 *
148142 * @param {Phaser.Cameras.Scene2D.Camera } camera - The Camera to cull Lights for.
149143 *
150144 * @return {Phaser.GameObjects.Light[] } The culled Lights.
151145 */
152- cull : function ( camera )
146+ getLights : function ( camera )
153147 {
154148 var lights = this . lights ;
155- var culledLights = this . culledLights ;
156- var length = lights . length ;
157- var cameraCenterX = camera . x + camera . width / 2.0 ;
158- var cameraCenterY = camera . y + camera . height / 2.0 ;
159- var cameraRadius = ( camera . width + camera . height ) / 2.0 ;
160- var point = { x : 0 , y : 0 } ;
161- var cameraMatrix = camera . matrix ;
162- var viewportHeight = this . systems . game . renderer . height ;
163-
164- culledLights . length = 0 ;
165-
166- for ( var i = 0 ; i < length && culledLights . length < this . maxLights ; i ++ )
167- {
168- var light = lights [ i ] ;
149+ var worldView = camera . worldView ;
169150
170- cameraMatrix . transformPoint ( light . x , light . y , point ) ;
151+ var visibleLights = [ ] ;
171152
172- // We'll just use bounding spheres to test if lights should be rendered
173- var dx = cameraCenterX - ( point . x - ( camera . scrollX * light . scrollFactorX * camera . zoom ) ) ;
174- var dy = cameraCenterY - ( viewportHeight - ( point . y - ( camera . scrollY * light . scrollFactorY ) * camera . zoom ) ) ;
175- var distance = Math . sqrt ( dx * dx + dy * dy ) ;
153+ for ( var i = 0 ; i < lights . length ; i ++ )
154+ {
155+ var light = lights [ i ] ;
176156
177- if ( distance < light . radius + cameraRadius )
157+ if ( light . willRender ( camera ) && CircleToRectangle ( light , worldView ) )
178158 {
179- culledLights . push ( lights [ i ] ) ;
159+ visibleLights . push ( {
160+ light : light ,
161+ distance : DistanceBetween ( light . x , light . y , worldView . centerX , worldView . centerY )
162+ } ) ;
180163 }
181164 }
182165
183- return culledLights ;
184- } ,
185-
186- /**
187- * Iterate over each Light with a callback.
188- *
189- * @method Phaser.GameObjects.LightsManager#forEachLight
190- * @since 3.0.0
191- *
192- * @param {LightForEach } callback - The callback that is called with each Light.
193- *
194- * @return {Phaser.GameObjects.LightsManager } This Lights Manager object.
195- */
196- forEachLight : function ( callback )
197- {
198- if ( ! callback )
166+ if ( visibleLights > this . maxLights )
199167 {
200- return ;
201- }
168+ // We've got too many lights, so sort by distance from camera and cull those far away
169+ // This isn't ideal because it doesn't factor in the radius of the lights, but it'll do for now
170+ // and is significantly better than we had before!
202171
203- var lights = this . lights ;
204- var length = lights . length ;
172+ StableSort ( visibleLights , this . sortByDistance ) ;
205173
206- for ( var i = 0 ; i < length ; i ++ )
207- {
208- callback ( lights [ i ] ) ;
174+ visibleLights = visibleLights . slice ( 0 , this . maxLights ) ;
209175 }
210176
211- return this ;
177+ this . visibleLights = visibleLights . length ;
178+
179+ return visibleLights ;
180+ } ,
181+
182+ sortByDistance : function ( a , b )
183+ {
184+ return ( a . distance < b . distance ) ;
212185 } ,
213186
214187 /**
@@ -225,9 +198,7 @@ var LightsManager = new Class({
225198 {
226199 var color = Utils . getFloatsFromUintRGB ( rgb ) ;
227200
228- this . ambientColor . r = color [ 0 ] ;
229- this . ambientColor . g = color [ 1 ] ;
230- this . ambientColor . b = color [ 2 ] ;
201+ this . ambientColor . set ( color [ 0 ] , color [ 1 ] , color [ 2 ] ) ;
231202
232203 return this ;
233204 } ,
@@ -242,7 +213,7 @@ var LightsManager = new Class({
242213 */
243214 getMaxVisibleLights : function ( )
244215 {
245- return 10 ;
216+ return this . maxLights ;
246217 } ,
247218
248219 /**
@@ -276,29 +247,13 @@ var LightsManager = new Class({
276247 {
277248 if ( x === undefined ) { x = 0 ; }
278249 if ( y === undefined ) { y = 0 ; }
279- if ( radius === undefined ) { radius = 100 ; }
250+ if ( radius === undefined ) { radius = 128 ; }
280251 if ( rgb === undefined ) { rgb = 0xffffff ; }
281252 if ( intensity === undefined ) { intensity = 1 ; }
282253
283- var color = null ;
284- var light = null ;
285-
286- color = Utils . getFloatsFromUintRGB ( rgb ) ;
287-
288- light = null ;
289-
290- var pool = this . lightPool ;
254+ var color = Utils . getFloatsFromUintRGB ( rgb ) ;
291255
292- if ( pool . length > 0 )
293- {
294- light = pool . pop ( ) ;
295-
296- light . set ( x , y , radius , color [ 0 ] , color [ 1 ] , color [ 2 ] , intensity ) ;
297- }
298- else
299- {
300- light = new Light ( x , y , radius , color [ 0 ] , color [ 1 ] , color [ 2 ] , intensity ) ;
301- }
256+ var light = new Light ( x , y , radius , color [ 0 ] , color [ 1 ] , color [ 2 ] , intensity ) ;
302257
303258 this . lights . push ( light ) ;
304259
@@ -321,8 +276,7 @@ var LightsManager = new Class({
321276
322277 if ( index >= 0 )
323278 {
324- this . lightPool . push ( light ) ;
325- this . lights . splice ( index , 1 ) ;
279+ SpliceOne ( this . lights , index ) ;
326280 }
327281
328282 return this ;
@@ -339,13 +293,6 @@ var LightsManager = new Class({
339293 */
340294 shutdown : function ( )
341295 {
342- while ( this . lights . length > 0 )
343- {
344- this . lightPool . push ( this . lights . pop ( ) ) ;
345- }
346-
347- this . ambientColor = { r : 0.1 , g : 0.1 , b : 0.1 } ;
348- this . culledLights . length = 0 ;
349296 this . lights . length = 0 ;
350297 } ,
351298
@@ -360,8 +307,6 @@ var LightsManager = new Class({
360307 destroy : function ( )
361308 {
362309 this . shutdown ( ) ;
363-
364- this . lightPool . length = 0 ;
365310 }
366311
367312} ) ;
0 commit comments