User Tools

Site Tools


Deferred Rendering

The SRT Exporter can also output vertex and pixel shaders appropriate for use with a deferred rendering system. In comparison to a traditional forward rendering system, integration of SpeedTree into a given engine is actually greatly simplified. Because lighting is handled after the render targets are written, no agreement has to exist between the two systems. Only the format and content of the G-buffer need to agree.


Deferred Shader Templates

The templates are located in the [SpeedTree_Apps_Location]/Bin/Exporters/ShaderTemplates/ folder where [SpeedTree_Apps_Location] is the SpeedTree Apps installation location. There are four main templates used for deferred-rendering pipeline:

  • Template_3dGeometry_Vertex_Deferred.fx: Contains the vertex shader entry point for all tree & grass models rendered in 3D.
  • Template_3dGeometry_Pixel_Deferred.fx: Contains the pixel shader entry point for all tree & grass models rendered in 3D.
  • Template_Billboard_Vertex_Deferred.fx: Contains the vertex shader entry point for the 360-degree billboards.
  • Template_Billboard_Pixel_Deferred.fx: Contains the pixel shader entry point for the 360-degree billboards.

There are two other variations of these templates for 3D geometry: Template_3dGeometry_*_ShadowCast.fx and Template_3dGeometry_*_DepthPrepass.fx, and billboard geometry: Template_Billboard_*_ShadowCast.fx and Template_Billboard_*_DepthPrepass.fx.

The vertex shader templates are set up very much like their forward rendering counterparts, but the pixel shader is very different and less configurable. The forward rendering pixel shader template has a lot of code for efficient effect & lighting LOD (e.g. fading from per-pixel lighting to per-vertex), whereas the deferred pixel shading template contains no lighting code. It does, however, have some LOD behavior like fading or skipping the detail lookup, specular mask lookup, and transmission mask lookup.

Note: When using the SRT exporter to compile a set of deferred shaders, there will be other differences in the generated assets apart from the shaders themselves. The SRT file itself will contain different vertex buffer contents as the vertex declarations will be different from the forward rendering versions. Largely, they will contain less data since lighting is handled later. The hash names for the shaders will also be different.

G-Buffer

The SpeedTree reference application uses an example G-buffer to demonstrate what a complete pipeline might look like with a SpeedTree integration. We fully expect that your G-buffer configuration will not match with our example layout. But, the good news is, it's easy to configure it to match your own format. Specifically, the SpeedTree shader templates refer to Template_Gbuffer.fx, also located in [SpeedTree_Apps_Location]/Bin/Exporters/ShaderTemplates/. It contains a definition similar to the following (HLSL definition, also not including the depth/stencil buffer):

///////////////////////////////////////////////////////////////////////
//  Deferred pixel shader output
//
//	This is an example SpeedTree G-buffer only. You will needed to define
//	your own G-buffer format here and populate the targets by modifying
//	Template_3dGeometry_Pixel_Deferred.fx and Template_Billboard_Pixel_Deferred.fx.
 
struct SMultiRenderTargets
{
    float4  m_vRenderTarget0  : RENDER_TARGET0; // [rgb] = albedo.rgb, [a] = specular power
    float4  m_vRenderTarget1  : RENDER_TARGET1; // [rg] = packed normal UV, [b] = specular mask [a] = transmission mask
};

To modify what the deferred shader templates write to the G-buffer, modify the code at the end of Template_3dGeometry_Pixel_Deferred.fx and Template_Billboard_Pixel_Deferred.fx. Currently, each contains the code below. It should be a relatively simple matter to write anything you need, or even adding more render targets.

// assign outputs to designated render target slots
{
    // render target 0
    sOutput.m_vRenderTarget0.rgb = out_vAlbedo;
    sOutput.m_vRenderTarget0.a = out_fSpecularPower / 128.0;
 
    // render target 1
    sOutput.m_vRenderTarget1.rg = PackNormalIntoFloat2_Stereographic(out_vNormal);
    sOutput.m_vRenderTarget1.b = out_fSpecularMask;
    sOutput.m_vRenderTarget1.a = out_fTransmissionMask;
}