Building and Integrating a Lighting system for a better Player Experience -- Owen Meyers

     One of the main tricks in a level designer's toolbag is the idea of light leading the way. Shortly after rooms were created and functioning within our game, the next problem to tackle was rooms. We needed a way to easily telegraph to the player which doors were duds and which could actually open. We also needed to show that a door was locked or unlocked, as all of a room's doors are locked until every enemy within is killed. This required a lighting system that could be easily accessed from multiple places, and which would also upload its data quickly and easily to the GPU. The lights also needed to be as lightweight as possible to not affect framerate too terribly.

    The first problem to tackle was the lighting manager. This needed to simply be a black box to access the underlying lights that are in the scene. Doing something as simple as changing the spotlights above a door from red to green up to something as complex as making a light flicker, could be done through the light manager. All that was needed was the light in the room, and for the system accessing it to know what light it was modifying. To make things even easier, I decided to extract the objects out as a pointer, thus allowing for systems outside of this one to request an update for it to happen. If a system, such as the Level Manager, wanted to request that the lights be turned green, it wouldn't need to send a message. Instead, it would turn the light green, and the light manager would already have the update, since they both shared a pointer. This made the system significantly easier to utilize, as well as significantly simpler.

    The second problem to tackle was ensuring the lights were lightweight on the GPU. This was solved in 2 ways. Firstly, I made the executive decision to limit the number of lights per room to 16. This is because all 16 lights in the buffer would be processed, as branching on the GPU is a bad idea. To explain fully, the loop that was processing the lights was hardcoded to 16, and then marked as unroll so that it wouldn't actually be a for loop. Instead, all of the instructions for doing an action 16 times would simply be written out by the compiler. Secondly, I made the lights branchless. To do this, I treated every light as a spotlight, but if it was a point light, it would simply be a spotlight with an angle of 180 degrees (corresponding to a cone that is expanded to a sphere). This ensured that there wouldn't be any slow branching code, and instead the entire lighting system was distilled into a list of 15-ish instructions repeated 16 times in the whole pixel shader. The result is consistent framerate, regardless of the number of active lights in the room.

Red lights to denote that the doors are locked. Notice that only 3 doors are illuminated. This is because this room only connects to 3 rooms.


Green spotlight that designates an unlocked door. Notice that the other doors are not illuminated.


Comments

Popular posts from this blog

Adding assets to every enemy -- Owen Meyers

Sphere to AABB collision