Shadow Mapping: Point Lights

Success! After having implemented shadow mapping for directional and spot lights, the engine now supports point lights aswell. As usual the code is a bit quick’n dirty and needs some serious cleanup. Nevertheless I’m already very pleased with the perfomance in the unoptimized state. The following video was captured with 4 fully dynamic, shadow casting point lights. FPS was around 70 on my pretty low tech PC: AMD Athlon X2 4450e (2,3Ghz Dual-Core), ATI HD4670. Even CPU usage was very low, so it’s definetly GPU bound. This leaves a lot of room for CPU stuff like game state handling, physics, culling, resource loading, sound and so on…

 

Shadow Mapping: Spot Light

I finished implementing shadow mapping for spot lights today. It’s only the first try, but it already looks pretty nice. I’m sure with some tweaks in the future it will be really good. Here is a screenshot of a single spot light. Blue line is the direction of the light and red lines are the lights view frustum. Bottom right is the shadow map used for the light.

Basic Shadow Mapping

Another step forward: Basic shadow mapping implementation is done. Up to now it’s only working for directional lights and still very hacky. It definetly needs a few optimizations and cleanups, but it’s still a nice start. I have tweaked my demo application a bit and added one directional light which is spinning around the center of the scene.

 

Deferred Shading: Demo

I build a little demo scene and captured a video. It has 4 fully dynamic point lights:

 

Furthermore the engine now supports directional, point and spot lights. All of them integrated into the scene graph and very easy to use. Next up are optimizations and shadow implementation.

Deferred Shading: First prototype

I finally did it! After several days testing, reasearching the net, going through tons of 3D math and uncounted frustrating hours, I have the first working prototype of the deferred renderer running. My main problems was a bug in my normals and mainly reconstructing the view space position from the depth buffer. Especially the on the last one was suprisingly tricky and forced me to dig through matrix math stuff again.

Nevertheless I have all main problems tackled and hopefully can do some nice things now. For the moment a screenshot of the prototype. It has 3 lights active and is fully deferred rendered.

Deferred Shading: G-Buffer

Another quick update on the deferred shading progress. I finished prototyping the G-Buffer. Here is the layout:

GL_R32F  |                       Depth                       |
GL_RG16F |         NormalX         |         NormalY         |
GL_RGBA8 |   ColorR   |   ColorG   |   ColorB   | MaterialID |
GL_RGBA8 | SpecularR  | SpecularG  | SpecularB  | Shininess  |

And now a screenshot. On the left you can see the 4 buffers, starting from the bottom: Depth, Color, Normal and Specular.

The main render is still done with default rendering. I’ll implement the deferred shading pass next.

 

Shader fun

Lately I updated the engine renderer to use core OpenGL 3 only. While there are still some things to work out the engine is now running completely on shaders. This allowed me to do implement some amazing things.

1. Completly flexible vertex formats.

Adding a new vertex definition is pretty easy now. First you need to typedef a struct for storing the vertices:

typedef struct myVertexType
{
  F32V3 position;
  F32V3 normal;
  F32V2 texCoord0;
  F32 blendFactor;
} myVertexType_t;

The next step is to create a definition for the vertex type:

nxVertexAttribute_t myVertexDef[] = {
  { nxVertex::Position, 3 },
  { nxVertex::Normal, 3 },
  { nxVertex::TexCoord0, 2 },
  { SID("BlendFactor"), 1 },
  { nxVertex::End, sizeof(myVertexType_t) }
};

And that’s it. This can be done completly seperated from the engine. So no engine recompiles needed!

The first 3 attribute names (nxVertex::Position, …) are predefined in the engine and automatically linked to all shaders. “BlendFactor” is a custom attribute name which must match to the corresponding name and type in the shader (“in float BlendFactor”). The numbers after the names are the size of the attribute in 4 byte steps. The last element “nxVertex::End” is to tell the engine that the definition is complete. “sizeof(…)” is the stride of the vertex type.

2. Framebuffer Objects

To get the real power out of shaders, framebuffer objects are a must have. So I implemented them into the engine and started to play around with them for a bit. Up to now I can create FBO’s and attach textures to them, which are used as render buffers. Then the FBO can be activated and used for rendering. After that the attached texture can be used as input for further shading passes or used for normal texture mapping. This allows some very interesting effects like mirror surfaces, enivormental mapping or procedural texture generation.

I created a basic demo which first renders the scene into a FBO. In the next pass the textures from the FBO are blended into the scene. The two textures used as buffers in the FBO are color and depth:

3. Next: Deferred Shading

The whole thing of this OpenGL 3, shader, FBO thing is that it allows the implementation of deferred shading. I really liked the idea behind this technique when I first read about it and now it’s the time to implement it by myself. Some links if you’re interested in the topic:

Deferred Shading Tutorial (PDF)

Deferred Shading – Wikipedia

That’s it for now. I’ll post some more pics if I have something nice to look at.