This is the first in what will be a series of articles talking about the tech we have built to create this game, Sparta3D. We have gotten a couple of requests to delve a bit deeper into the technical side of what makes our engine tick and how it’s creating this special look so here it is. The basics that we built Sparta 3D on is a couple of Techniques .
- Properly gamma corrected Linear Space lightning
- A Physically based lightning model.
- Deferred Rendering
- True Quadratic Light fall off
- Box projected cube maps
- Temporal multi resolution SSAO
- Bounced Light Solution
All of this also boils down to a couple if philosophies with the main thing being “In computer games most lighting is hard and harsh but in real life most of it is soft”, “While it’s easy to make a movie look good with yellow and teal a more full colored spectrum is more interesting” and “The basics of a good looking image is good lighting”. So all the we have done with the engine is focused on these things to allow a soft nice environment with lush colors and with a high quality lightning that doesn’t require to much artist work to look good. This does not necessarily make it a better or a worse engine. It makes it a better engine for our specific game. This is a bit of a test run to see how much technical depth we should go into here so we’ll gauge the interest, but let’s get started on the specifics.
One of the most important things when doing 3d rendering is to get your lighting calculations to work properly. If the lighting is off great artists can work hard to salvage something but it’s always gonna be an uphill battle. Since we won’t our artists to spend their time working on creating as high a quality as possible we don’t want to force them to fight the tech, we want the tech to help them fight their battles.
One of the issues when doing lightning is Gamma, this actually comes from how the monitor is displaying your image instead of from your code but you still will have to compensate for it. Due to how old CRT monitors worked a linear change in value for the RGB channels resulted in a non linear change in value on the screen. This might be a bit confusing so I’ going to explain it using some images created by John Hable
The blue line in the middle is a linear line straight upwards which would mean that brightness would follow the RGB values. However the red line is what actually happens when you try to output an image through a computer monitor and this is due to the old CRT monitors (which all modern LCD,TFT,LED etc mimics). So what we need to do to keep data looking correctly is to first apply the yellow curve before we send it to the monitor which will apply the red curve and they will cancel each other out and everything will work out ? Well as long as you don’t make any changes to the data like blending textures or performing lighting you don’t have to think about this. Because the artist created the texture on a Screen it is already over brightened with the yellow line to look correct, the same happens if you are making a digital photo it automatically applies the yellow line to make it look correct.
Like you see in this image from John Hable some transformations is performed the mathematical transformations for most screens can be approximated as Gamma 2.2. This means that the monitor takes your input value between 0 and 1 and raises it with 2.2 this is the red curve. While raising it with 0.45 is the yellow curve. So as you can clearly see here the camera over brightens the image before saving it to disk to compensate for the screens darkening.
So why do this matter to us ? Well what happens if yo would like to add together two images that we say have 50% brightness. Well this gives an RGB value of 187 in monitor space. If we add them together we would get a RGB value of 384. Way above the 256 of clear white we expected. However if we first apply the red line to get them back from an over brightened state to the blue line we would be adding 128 with 128 and create the expected 256 (capped at 255 as a max number), afterwards we will have to apply the yellow curve again to get back to what the monitor is exspected but sicne 255 maps to 1 and 1 raised with any power is still 1 everything works out. For extra information look at GPU Gems or John Hables webpage or for more in depth the Uncharted 2 Lightning presentation.
Working in XNA sadly Microsoft removed access to the hardware free gamma to linear and linear to gamma converters in going from XNA 3.1 to 4.0 so we actually have to make all these conversions in shader code which does cost some performance but not doing it was never an alternative visually. I will here link an example from the GPU-Gems article.
Booth these images were lit with a white light source of the same strength the left one uses linear space lighting and the right one does not. Notice the burn out areas on the right picture and also the yellowish tone (this is an artifact of making lightning in gamma space the specular will burn out to a surrounding color and not have the color of the light ). The left looks a lot more natural and error free, this technique allows us to experiment with a lot more and stronger light sources while still maintaining good balance in the image.
We’ll be back soon with a follow up article about our physically based shading solution but this article did already get longer than it was planned so we have to cut it of for now. On the same subject we are currently hard at work putting the finishing touches on and lighting two entirely new environments that will be quite different from the ones we have showed up in trailers and screenshots so far, we just want to polish it a bit more before we can start showing them off.