This week I've been working on the lighting for the game, so that the lighting goes beyond shadows from the sun, and takes into account multiple bounces.
Lighting is an important part of a compelling experience. If the game isn't lit well, it feels really flat and uninteresting. Since Guns of Theory is built on the Unity engine, you'd think this would be easily solved using their in-editor baking solution. The problem is that Unity does not do well with dynamically loaded content. I designed this game to be as moddable as possible, which means players can make their own maps and load them into the game at runtime, add new modes and swap models out. Since all this action is happening outside the editor, Unity's model loading and lightmapping functionality becomes moot, and I have to come up with my own stuff.
Having roughly solved the model loading problem, I have come to a simple solution for lighting as well. The algorithm for light baking is pretty straightforward:
- For each cell of a volume around the level:
- Take 6 screenshots at the position of the cell correlating to the directions of the 6 sides of a cube
- Get the average colour of each render and store the colour in a 3D texture (6 3D textures corresponding to the 6 directions)
- Pass the textures to the graphics card
- For more light bounces, let the level geometry sample the textures, and repeat the entire process
This process was simple to code, but takes some time to render every cell in the volume. A 64x32x32 volume can take 15 minutes on my little laptop. However, once the textures are created, the sampling of the textures is blazing fast, simply get an interpolated sample of the 3 textures that are relevant to a given fragment based on the global normal and global position.
This solution is not only great for static walls and floors, but works with dynamic objects as well, like the character model or physics objects, since all geometry samples a volume instead of a flat map. This means that your HUD gun will be brightened by the light bouncing off the walls and floor, or from the lava pit on the edges of the level, and characters can hide in the deep shadows of closets and nooks. This solution also means that secondary light sources other than the sun can be simulated by having very bright materials in the lights that don't necessarily have to be regularly shaped.
I am now looking into reusing the renders from the algorithm and putting them into cube maps that can be sampled by geometry for specular effects. This would be great for guns, as they could be roughly reflecting their environment, and may even work for walls and floors to add some glossiness.
I've been closely watching progress on real-time global illumination solutions. There's some really promising stuff, especially voxel cone tracing. Voxel cone tracing was going to be featured in Unreal Engine 4, but I believe that feature has been buried for concerns about it not working on modern hardware. It's also been achieved on Unity during the DX11 competition, which I'm really excited about. Before we have fast enough hardware, however, I think the solution I have come up with will suffice. If the cone tracing solution comes out on the asset store I'll definitely have to pick it up for super computer users to try.