Having forward rendering done in my own 3D engine, I planned to look into deferred shading. The major change to my code was to rendering scene objects into separated render targets called G-Buffer. Then, G-Buffers will be composed by the post processor in screen space for each light.
The three G-Buffers I used in my project were albedo, normal and world position buffers. Albedo buffer has a format of R8G8B8A8 while normal and world position buffers are R32G32B32A32_FLOAT. Both normal and world position buffers can be optimized by using a more compact format of render target. I leave the optimization to my future work. So far they work fine with my demo.
The shaders will be changed to outputting geometry information to each G-Buffer. In a pixel shader, output structure looks this:
struct OUTPUT_PIXEL
{
float4 Albedo : SV_Target0;
float4 WorldPos : SV_Target1;
float4 Normal : SV_Target2;
};
Semantic SV_Target[n] represents the render target pixels will be written onto. Then, geometry information will be output to the structure, just as passing information from vertex shaders to pixel shaders:
OUTPUT_PIXEL main(OUTPUT_VERTEX Input) : SV_TARGET
{
OUTPUT_PIXEL Out = (OUTPUT_PIXEL)0;
Out.Albedo = DiffuseTexture.Sample(Sampler, Input.UV0);
Out.WorldPos = float4(Input.PosW, 1);
Out.Normal = float4(Input.NormalW, 1);
Setting up multiple render targets is just as setting a single one. ID3D11DeviceContext::OMSetRenderTargets takes render target numbers and an array of render targets as first and second parameter. Use all G-Buffers as render target and draw objects with deferred shader.
Following is G-Buffers from one frame of my demo:
(Albedo, from diffuse texture color)
(Position in world space)
For light rendering, each light takes one render pass with deferred light pass shader. The light will be calculated in the same way as being done in forward shading, except getting all necessary geometry information from G-Buffers. Since lighting information is in addition to mesh surface color, an additive blending on light pass gives correct result.
In my demo, I have 100 lighting moving around the city. This basic approach may end up running very slow, but we got all the points so far.
(City with 100 dynamic lighting)
‘Creating the G-Buffer’ from ‘Catalin ZZ’: http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/
‘ID3D11DeviceContext::OMGetRenderTargets method’ from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476460(v=vs.85).aspx
‘Semantics’ from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx