====== Deferred rendering ====== The SpeedTree SDK comes with example deferred rendering shaders (as well as forward). In comparison to a traditional forward rendering system, integration of SpeedTree into a given engine can be much easier since 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. ===== Example 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 it's easy to configure it to match your own format. Specific details of the example G-buffer are best illustrated in ''[SDK Install Path]/SampleForest/Shaders/Include/gbuffer_example.h''. The example uses two color channels: struct SExampleGBuffer { float4 m_vRenderTarget0 ST_RENDER_TARGET0; float4 m_vRenderTarget1 ST_RENDER_TARGET1; }; A packing and unpacking function are provided, each operating with these components: struct SGBufferComponents { float3 m_vColor; float m_fOpacity; float3 m_vNormal; float m_fGloss; float3 m_vSubsurface; float m_fAO; int m_iGeometryType; }; The packing function: void PackGBuffer(ST_REFVAR(SExampleGBuffer) sGBuffer, SGBufferComponents sIn) { // render target 0 float3 vAdjustedSubsurface = saturate(sIn.m_vSubsurface); float fSubsurfaceScale = max(vAdjustedSubsurface.r, max(vAdjustedSubsurface.g, vAdjustedSubsurface.b)); vAdjustedSubsurface /= max(1.0e-5, fSubsurfaceScale); sGBuffer.m_vRenderTarget0 = float4(Utility_PackInteger2(float2(sIn.m_vColor.r, vAdjustedSubsurface.r), float2(64, 4)) / 256, Utility_PackInteger2(float2(sIn.m_vColor.g, vAdjustedSubsurface.g), float2(64, 4)) / 256, Utility_PackInteger2(float2(sIn.m_vColor.b, vAdjustedSubsurface.b), float2(64, 4)) / 256, sIn.m_fOpacity); // render target 1 sGBuffer.m_vRenderTarget1.rg = Utility_PackNormalIntoFloat2_Spheremap(sIn.m_vNormal); sGBuffer.m_vRenderTarget1.b = Utility_PackInteger2(float2(fSubsurfaceScale, sIn.m_fAO), float2(16, 16)) / 256; sGBuffer.m_vRenderTarget1.a = Utility_PackInteger2(float2(sIn.m_fGloss, float(sIn.m_iGeometryType) / ST_GEOMETRY_TYPE_MAX), float2(32, 8)) / 256; } The unpacking function: void UnpackGBuffer(ST_REFVAR(SGBufferComponents) sOut, SExampleGBuffer sGBuffer) { float2 vColorR = Utility_UnpackInteger2(sGBuffer.m_vRenderTarget0.r * 256, float2(64, 4)); float2 vColorG = Utility_UnpackInteger2(sGBuffer.m_vRenderTarget0.g * 256, float2(64, 4)); float2 vColorB = Utility_UnpackInteger2(sGBuffer.m_vRenderTarget0.b * 256, float2(64, 4)); float2 vUnpack1 = Utility_UnpackInteger2(sGBuffer.m_vRenderTarget1.b * 256, float2(16, 16)); float2 vUnpack2 = Utility_UnpackInteger2(sGBuffer.m_vRenderTarget1.a * 256, float2(32, 8)); sOut.m_vColor = float3(vColorR.x, vColorG.x, vColorB.x); sOut.m_fOpacity = sGBuffer.m_vRenderTarget0.a; sOut.m_vNormal = Utility_UnpackNormalFromFloat2_Spheremap(sGBuffer.m_vRenderTarget1.xy); sOut.m_fGloss = vUnpack2.x; sOut.m_vSubsurface = float3(vColorR.y, vColorG.y, vColorB.y) * vUnpack1.x; sOut.m_fAO = vUnpack1.y; sOut.m_iGeometryType = int(round(vUnpack2.y * ST_GEOMETRY_TYPE_MAX)); }