I hope lolz123 does not mind me posting this here:
For those interested in better LTBL2 performance and lights that can be switched on/off:I've made a few small changes in the LTBL2 code by adding two boolean member variables (_isAwake and _isTurnedOn) aswell as appropiate get/set/toggle methods to the QuadtreeOccupant object.
Both the occluders aswell as the lights are initialized as both awake and on by default (so nothing changed in the behaviour of LTBL2 unless you manually switch them off/make them sleep).
namespace ltbl {
class QuadtreeOccupant {
public:
bool _isAwake;
bool _isTurnedOn;
QuadtreeOccupant()
: _pQuadtreeNode(nullptr), _pQuadtree(nullptr), _isAwake(true), _isTurnedOn(true)
{}
bool isAwake();
void setAwake(bool);
void toggleAwake();
void setTurnedOn(bool);
bool isTurnedOn();
void toggleTurnedOn();
};
}
And then each time in the code when i found LTBL2 looping through all the Quadtree occupants (occluders and light objects) to do shadow/light calculations or rendering i inserted a single if-statement that first checks if the occluder/lightobject is actually active AND switched on before actually doing AABB-checks, any shadow calculations or any rendering.
Example in the render method:
void LightDirectionEmission::render(const sf::View &view, sf::RenderTexture &lightTempTexture, sf::RenderTexture &antumbraTempTexture, const std::vector<QuadtreeOccupant*> &shapes, sf::Shader &unshadowShader, float shadowExtension) {
lightTempTexture.setView(view);
LightSystem::clear(lightTempTexture, sf::Color::White);
// Mask off light shape (over-masking - mask too much, reveal penumbra/antumbra afterwards)
for (int i = 0; i < shapes.size(); i++) {
LightShape* pLightShape = static_cast<LightShape*>(shapes[i]);
//Check if Light is awake and turned on
if (pLightShape->isAwake() && pLightShape->isTurnedOn()) {
//...
// Down here comes all the calculate/render stuff, which only gets done if light is awake and on
//...
What's the advantage?Turning lights/shadows on and offWell, first of all you can turn lights and occluders(and thus shadows) on and off by using the
void setTurnedOn(bool);
void toggleTurnedOn();
methods, without having to delete the lights/occluders just to turn the light off or remove the shadow casting occluder. You can use for example light switches in your game that have a pointer/reference to the light object and by activating the switch you invoke the
toggleTurnedOn() method of the pointed-to light.
Performance boost by putting offscreen/not-in-same-room LTBL2-objects to sleepIn addition to that, you can put your lights and occluders to sleep (similar to sleep/awake in Box2d) by using the
void setAwake(bool);
void toggleAwake();.
methods.
These methods allow LTBL2 to skip calculations for the light/occluder without modifying whether the light/shadow, from the game world perspective, is switched on or off (by a light switch in the level, for example).
How would we use that? Lets say you have a game with several rooms or zones, which all have light objects. It'd be very inefficient if the game calculates and AABB-checks
all the lights of your loaded level if you are not in the same room/zone of the light/occluder, regardless whether they are switched on or off (by switches in the level).
For that there is the "
setAwake(bool)" method:
If you leave a room or zone then, on room/zone change, you could invoke a method that loops through all the lights/occluders in said room/zone and setAwake(false) for each of it. In the now new entered room/zone you would then loop through all occluders/lights and invoke setAwake(true) on each.
That way only the lights/occluders that are in the players zone/room get calculated/AABB-checked/rendered.
Example code:
Lets say we have another class (Lightswitch) with a pointer to a LTBL2 light, then we can use it light this
// creates a light, by default it's on and awake
ltbl::LightPointEmission* light1 = new ltbl::LightPointEmission(); // creates a light
//create a lightswitch and make it point to the light
Lightswitch switch1;
switch1.pointedToLight = light1;
//now we can turn it on and off
switch1.pointedToLight->toggleTurnedOn();
//lets say we have a room or zone object that has a vector of LTBL2-lights
//when we leave the room/zone we can put them all to sleep
for (ltbl::LightPointEmission* light : getCurrentRoom()->getLights()) {
light->setAwake(false);
}
In short:By using these modifications your game
-allows turning on/off of lights/occluders without having to constantly create/delete them
-the game keeps memorized which lights are turned on and off, since you don't create/destroy them all the time but just turn them off/on
-can get a huge performance boost by putting out-of-zone/out-of-room LTBL2 objects to sleep via setAwake(false) and only setAwake(true) if they are near the player/in the same zone or room as the player.
You can download the modified version here
https://www.dropbox.com/s/amk8v17btth6lmq/ltbl2_toggleable.zip?dl=0Feel free to leave feedback or any errors (i couldn't find any, it's only about 15~20 lines of code that i added).