Deferred Rendering

8 January, 2014

Main Image

The Blinn-Phong shading model is used to evaluate the lighting on each pixel. This is done in 3 passes and uses a GBuffer. The GBuffer has the Normal (XYZ, 1), Position (XYZ, 1), Light Buffer(RGB, A) & Final Buffer (RGB, A).

Pass 1

Input: Position, Normal and Matrices of the vertices
Output: Position & Normal Buffers (Render Targets)

struct PSInput 
{ 
 float4 PositionSS : SV_Position; 
 float2 TexCoord : TEXCOORD; 
 float3 NormalWS : NORMAL; 
 float3 PositionWS : POSITION; 
}; 

struct PSOutput 
{ 
 float4 Normal : SV_TARGET0; 
 float4 Position : SV_TARGET1; 
}; 

// G-Buffer pixel shader for light prepass deferred //rendering 
PSOutput PSMain( in PSInput input )
{ 
 // Output our G-Buffer values 
 PSOutput output; 
 output.Normal = float4( input.NormalWS, 1.0f ); 
 output.Position = float4( input.PositionWS, 1.0f ); 
 
 return output; 
}

Pass 2

Input: Normal & Position buffers as 2D textures
Output: Final Colour of light to light buffer

// Calculates the lighting term for a single G-Buffer //texel 
float4 CalcLighting( in float3 normal, in float3 position, in float specularPower )
{ 
 // Calculate the diffuse term 
 float3 L = 0; 
 float attenuation = 1.0f; 
 
 // Base the the light vector on the light position 
 L = LightPos - position; 
 
 // Calculate attenuation based on distance from the //light source 
 float dist = length ( L ); 
 attenuation = max( 0, 1.0f - (dist / LightRange.x )); 
 L /= dist;

 float nDotL = saturate( dot( normal, L ) ); 
 float3 diffuse = nDotL * LightColor * attenuation; 
 
 // Calculate the specular term 
 float3 V = CameraPos - position; 
 float3 H = normalize( L + V ); 
 
 // Final value is diffuse RGB
 return float4(diffuse, 1.0f);
}

Pass 3

Input: Vertex Matrices, Vertex Position, Texture Coordinates + Texture, Light Buffer
Output: Final Colour of the pixel

// Pixel shader for final pass of light prepass deferred rendering 
float4 PSMain( in PSInput input ) : SV_TARGET0 
{ 
 // Sample the diffuse map 
 float3 diffuseAlbedo = DiffuseMap.Sample(AnisoSampler, input.TexCoord ).rgb; 
 
 // Determine our indices for sampling the textures
 //based on the current screen position 
 int3 sampleIndices = int3( input.ScreenPos.xy, 0 ); 
 
 // Sample the light target 
 float4 lighting = LightTexture.Load( sampleIndices ); 
 
 // Apply the diffuse and specular albedo to the //lighting value 
 float3 diffuse = lighting.xyz * diffuseAlbedo; 
 float3 specular = lighting.w * SpecularAlbedo; 
 
 // Final output is the sum of diffuse
 return float4(diffuse, 1.0f);
}

FBX Loading

The Autodesk FBX SDK was used. These were the features I implemented in my FBX Importer:

  • Vertices
  • Index Array
  • All meshes
  • UV
  • Material (Texture file + Settings)
  • Joints + Pose (not used)
  • Camera Position
  • Lights (Position + Colour + Intensity)