Skip to content

Commit 732b188

Browse files
committed
Removed light pool, used RGB object, much better light culling.
1 parent 97fd175 commit 732b188

1 file changed

Lines changed: 56 additions & 111 deletions

File tree

src/gameobjects/lights/LightsManager.js

Lines changed: 56 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
* @license {@link https://opensource.org/licenses/MIT|MIT License}
55
*/
66

7+
var CircleToRectangle = require('../../geom/intersects/CircleToRectangle');
78
var Class = require('../../utils/Class');
9+
var DistanceBetween = require('../../math/distance/DistanceBetween');
810
var Light = require('./Light');
911
var PointLight = require('../pointlight/PointLight');
12+
var RGB = require('../../display/RGB');
13+
var SpliceOne = require('../../utils/array/SpliceOne');
14+
var StableSort = require('../../utils/array/StableSort');
1015
var 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

Comments
 (0)