//========== Copyright (c) Valve Corporation, All rights reserved. ==========// // STATIC: "BLOOMTYPE" "0..1" // DYNAMIC: "FLOAT_BACK_BUFFER" "0..1" [ps20b] [ps30] [PC] // DYNAMIC: "FLOAT_BACK_BUFFER" "0..0" [ps20b] [XBOX] #include "common_ps_fxc.h" sampler TexSampler : register( s0 ); float4 params : register( c0 ); float4 params2 : register( c1 ); #define g_flBloomExp params2.x #define g_flBloomSaturation params2.y struct PS_INPUT { float2 coordTap0 : TEXCOORD0; float2 coordTap1 : TEXCOORD1; float2 coordTap2 : TEXCOORD2; float2 coordTap3 : TEXCOORD3; }; float4 Shape( float4 cColor ) { #if ( BLOOMTYPE == 0 ) { float flLum = dot( cColor.xyz, params.xyz ); cColor.rgb = pow( cColor.xyz, params.w ) * flLum; } #endif #if ( BLOOMTYPE == 1 ) { float flScale = 1.55f; // Color scale float flBias = -0.09f; // Color bias float flBrightnessClamp = 0.59f; // After scale and bias, clamp RGB values brighter than this float flExp = g_flBloomExp; cColor.rgb = pow( saturate( min( flBrightnessClamp, ( cColor.rgb * flScale ) + flBias ) ), flExp ); } #endif return cColor; } float4 main( PS_INPUT i ) : COLOR { float4 s0, s1, s2, s3; // Sample 4 taps s0 = tex2D( TexSampler, i.coordTap0 ); s1 = tex2D( TexSampler, i.coordTap1 ); s2 = tex2D( TexSampler, i.coordTap2 ); s3 = tex2D( TexSampler, i.coordTap3 ); #if ( FLOAT_BACK_BUFFER == 1 ) { // for float HDR mode, match the color space of the int render pass, to get identical bloom results s0.rgb = SrgbLinearToGamma( saturate( s0.rgb ) ); s1.rgb = SrgbLinearToGamma( saturate( s1.rgb ) ); s2.rgb = SrgbLinearToGamma( saturate( s2.rgb ) ); s3.rgb = SrgbLinearToGamma( saturate( s3.rgb ) ); } #endif float4 avgColor = ( s0 + s1 + s2 + s3 ) * 0.25f; float fAvgLuminance = dot( avgColor.rgb, float3( 0.299, 0.587, 0.114 ) ); avgColor = Shape( avgColor ); // Saturation #if ( BLOOMTYPE == 1 ) { avgColor.rgb = lerp( dot( params.rgb, avgColor.rgb ), avgColor.rgb, g_flBloomSaturation ); } #endif avgColor.a = fAvgLuminance; return FinalOutput( avgColor, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); }