I’ve been working full time on improving my game engine and adding some awesome new features. I made some big optimizations, fixed a massive amount of bugs and and cleaned up the code so it’s easier to use. But I think the most noticeable improvement is the new deferred lighting system, it now supports normal mapping, specular, emissive and dynamic soft shadows and it runs amazingly smooth.
The biggest drag on my framerate was the terrain rendering because it was using a separate draw call for each tile. I always knew it was slow but it was way worse with the deferred rendering because there are about 5 passes of rendering the entire scene. This was resulting in hundreds of draw calls even though in most cases only a few textures were being used. The optimization is to dynamically build a vertex buffer for all the tiles in a patch when it’s streamed in. It creates a list of tri strips, one strip for each texture used in that patch. This sacrifices a small rebuild time when the player moves between patches for much higher framerate during normal play.
Another thing that was slowing down the lighting system was that every dynamic light needed the scene to be re-rendered from it’s position. I tried culling objects outside that light’s radius but it still was somewhat slow. The big optimization is to pre-render all the shadow casting objects in the entire scene to an extra large texture. Then for each dynamic light it just uses that texture rather then re-rendering everything. This makes each individual light much cheaper to update. The shadow map also gets blued slightly to help with some of the jaggies.
When I first implemented the lighting I had a problem with flickering, as the camera moved the lighting accumulation texture also moved causing it to alias and flicker. Increasing the texture resolution helps slightly but not nearly enough for the added cost. I finally settled on a solution that rounds the position of the lighting texture to the nearest pixel. Because the texture is no longer centered it needs to be slightly larger to cover up the shifting that happens on the edges of the screen. This looks effectively the same as having the texture be stationary in world space.
I currently have the max lights capped at 24 because that’s when it starts to drop below 60 on my PC and seems plenty enough to light a scene. I hope to be able to do much more lights with future optimizations. For lower end graphics settings reducing the texture sizes can make a big increase in frame rate. This project is fully open source so you can take a look at how it works under the hood.