Tuesday, November 29, 2011

Deferred Lighting

First a quick update on stuff that's been going on since my last post here:
-I've been let go from my old job, looking for new one.


And now back to our topic at hand.
I always like to boast that I'm a graphics programmer, that there's little that can stop me in my way and even though I actually do believe that's true I don't have much to show for that. Be it because of work and being uninspired to program back at home, or because I've spent far too long retouching my engine and in the end I end up with a lot of hidden work and nothing visible, or because I was simply too lazy/distracted.

Well, since I lost my job I decided It's time to boost my portfolio a bit, and prove to everyone and to myself that I can actually be a good graphic programmer. To accomplish this I decided to work every day on a small demo of a certain feature I never implemented before. The first one being:

Deferred Lighting.

Of course my first reaction was grabbing as much as I could from the internet in terms of research papers and tutorials. The most helpful I found are these:

Creating a GLSL Library - This was a good way to quickly sketch out a simple per-fragment lighting shader and apply it to a model lit directly. I've used this before so I simply copied most of the code

Coding Labs Deferred Rendering Tutorial - This is what I needed, though I decided to skip the tutorial and learn directly from source code since I already understood the concepts and implementation, but I didn't know which opengl functions to use.

Normally Deferred rendering requires you to use the inverse of the modelview matrix and inverse of the projection matrix to get both the pixel position from projected screen space to camera-space, and to get the lights from world space to camera space, however the tutorial used a nasty inefficient hack to get the pixels in world space without the need for transformation: it simply recorded all x, y and z inside what in normal deferred lighing program would be a single-32bit float-value gbuffer.

However with lights I did another nasty hack: instead of using the gl_LightSource[i].position in my shader I simply replaced it with an array of vec4 screen-space light positions I calculated outside using the modelview matrix from the first pass and passed to the shader.

All of this just so I didn't have to write/find and de-obscure and test and debug a matrix inverse function.

In the end I spend between 4 to 8 hours on this (how mach depends if you count the research time) over the course of 2 days.

The results?
Here:



All in all it wasn't that bad but the code ended up a horrible conglomerate mess, most of which was shoved into a single main.cpp file.

If you're interested you can download the demo with the code here:
Deferred Shading Demo

Before you look at the source please note that this is terrible code, unoptimized and originally wasn't meant for viewing by other people, if I ever did the exact same demo again there would be ZERO similarity.

Right now I'm working on another experiment, namely importing a model with animation using Assimp (which I still have to learn) and then use that data in my animation tree (similar to the one UDK has), in the end add some IK, but this experiment is much larger than the deferred shading one, so it'll take probably about a week or so before I post here again.

Thanks for your attention!
Laters!
Spliter