Optimisation when using many lights, most of which are off-screen

Aug 3, 2012 at 8:45 AM


First of all, thanks for creating Krypton.  I've found it really easy to integrate and easy to use!

Once I had it integrated with my tile engine I decided to stress test it and added over 65,000 lights to my map.  This sent the frame rate down to 1 fps, even though only 5 or 6 lights are on screen at once.  I had a dig around the code and came up with a decent optimisation:

In KryptonEngine.cs I changed the "Render light maps" loop in LightMapPrepare to this:

            // Render Light Maps
            foreach (var light in this.mLights)
                // Loop through each light within the view frustum
                Rectangle r = KryptonEngine.ScissorRectCreateForLight(light, lightMapMatrix, targetSize);
                if ( r.Intersects(GraphicsDevice.Viewport.Bounds) )
                    this.GraphicsDevice.Clear(ClearOptions.Stencil, Color.Black, 0, 0);
                    this.GraphicsDevice.ScissorRectangle = r;

                    light.Draw(this.RenderHelper, this.mHulls);

I know there was already a bounds check in there, but I see that you always set mBounds to minmax (as I see that the matrix maths in Matrix.set doesn't work).  So I changed the check to get the scissor rect and if this rect isn't actually on the viewport we skip rendering the light.

This little optimisation got me back up to 60fps, so I hope it's something you'd consider integrating back into Krypton.  Obviously it only helps the case where you have lots of lights which aren't on screen, but I'd hope this is the usual case for most people.

I added a toggle to my local code so I could turn the optimisation on and off and I don't see any differences so I don't think this change breaks anything.  I was using the latest version of the source code rather than latest stable, though this optimisation should work in either.