#include "hdrutils.hlsl" Texture2D inRTT; Texture2D inLum; Texture2D inBloom; SamplerState g_samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; }; struct v2p { float4 position : SV_POSITION; float2 texCoord : TEXCOORD0; }; float4 downscale2x2Luminencefp4( v2p input, uniform float2 texelSize // depends on size of source texture ) : SV_Target { float4 accum = float4(0.0f, 0.0f, 0.0f, 0.0f); float2 texOffset[4] = { -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5 }; for( int i = 0; i < 4; i++ ) { // Get colour from source accum += inRTT.Sample(g_samLinear, input.texCoord + texelSize * texOffset[i]); } // Adjust the accumulated amount by lum factor // Cannot use float3's here because it generates dependent texture errors because of swizzle float lum = dot(accum, LUMINENCE_FACTOR); // take average of 4 samples lum *= 0.25; return lum; } /* Downsample a 3x3 area * This shader is used multiple times on different source sizes, so texel size has to be configurable */ float4 downscale3x3fp4(v2p input, uniform float2 texelSize // depends on size of source texture ) : SV_Target { float4 accum = float4(0.0f, 0.0f, 0.0f, 0.0f); float2 texOffset[9] = { -1.0, -1.0, 0.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0 }; for( int i = 0; i < 9; i++ ) { // Get colour from source accum += inRTT.Sample(g_samLinear, input.texCoord + texelSize * texOffset[i]); } // take average of 9 samples accum *= 0.1111111111111111; return accum; } /* Downsample a 3x3 area from main RTT and perform a brightness pass */ float4 downscale3x3brightpassfp4(v2p input, uniform float2 texelSize // depends on size of source texture ) : SV_Target { float4 accum = float4(0.0f, 0.0f, 0.0f, 0.0f); float2 texOffset[9] = { -1.0, -1.0, 0.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0 }; for( int i = 0; i < 9; i++ ) { // Get colour from source accum += inRTT.Sample(g_samLinear, input.texCoord + texelSize * texOffset[i]); } // take average of 9 samples accum *= 0.1111111111111111; // Reduce bright and clamp accum = max(float4(0.0f, 0.0f, 0.0f, 1.0f), accum - BRIGHT_LIMITER); // Sample the luminence texture float4 lum = inLum.Sample(g_samLinear, float2(0.5f, 0.5f)); // Tone map result return toneMap(accum, lum.r); } /* Gaussian bloom, requires offsets and weights to be provided externally */ float4 bloomfp4(v2p input, uniform float2 sampleOffsets[15], uniform float4 sampleWeights[15] ) : SV_Target { float4 accum = float4(0.0f, 0.0f, 0.0f, 1.0f); float2 sampleUV; for( int i = 0; i < 15; i++ ) { // Sample from adjacent points, 7 each side and central sampleUV = input.texCoord + sampleOffsets[i]; accum += sampleWeights[i] * inRTT.Sample(g_samLinear, sampleUV); } return accum; } /* Final scene composition, with tone mapping */ float4 finalToneMappingfp4(v2p input ) : SV_Target { // Get main scene colour float4 sceneCol = inRTT.Sample(g_samLinear, input.texCoord); // Get luminence value float4 lum = inLum.Sample(g_samLinear, float2(0.5f, 0.5f)); // tone map this float4 toneMappedSceneCol = toneMap(sceneCol, lum.r); // Get bloom colour float4 bloom = inBloom.Sample(g_samLinear, input.texCoord); // Add scene & bloom return float4(toneMappedSceneCol.rgb + bloom.rgb, 1.0f); }