1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-01-09 18:48:51 +08:00
hl2sdk/materialsystem/stdshaders/Engine_Post_ps2x.fxc
Scott Ehlert fdd0bbf277 SDK sync.
2012-07-06 20:35:59 -05:00

441 lines
17 KiB
Plaintext

//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
// FIXMEL4DTOMAINMERGE
// Need to re-enable bloom and disable other L4D-only features in here and the cpp file.
// STATIC: "TOOL_MODE" "0..1"
// STATIC: "DEPTH_BLUR_ENABLE" "0..1"
// DYNAMIC: "AA_ENABLE" "0..0" [PC]
// DYNAMIC: "AA_ENABLE" "0..1" [XBOX]
// DYNAMIC: "COL_CORRECT_NUM_LOOKUPS" "0..3"
// DYNAMIC: "CONVERT_FROM_LINEAR" "0..1" [ps20b] [ps30] [PC]
// DYNAMIC: "CONVERT_TO_LINEAR" "0..1" [ps20b] [ps30] [PC]
// DYNAMIC: "CONVERT_FROM_LINEAR" "0..0" [ps20b] [XBOX]
// DYNAMIC: "CONVERT_TO_LINEAR" "0..0" [ps20b] [XBOX]
// SKIP: ( $CONVERT_FROM_LINEAR == 0 ) && ( $CONVERT_TO_LINEAR == 1 )
// SKIP: ( $TOOL_MODE == 0 ) && ( $CONVERT_TO_LINEAR == 1 )
// DYNAMIC: "NOISE_ENABLE" "0..1" [ps20b] [ps30]
// DYNAMIC: "VIGNETTE_ENABLE" "0..1" [ps20b] [ps30]
// DYNAMIC: "LOCAL_CONTRAST_ENABLE" "0..1" [ps20b] [ps30]
// DYNAMIC: "BLURRED_VIGNETTE_ENABLE" "0..1" [ps20b] [ps30]
// DYNAMIC: "VOMIT_ENABLE" "0..1"
// SKIP: ( $LOCAL_CONTRAST_ENABLE == 0 ) && ( $BLURRED_VIGNETTE_ENABLE == 1 )
// DYNAMIC: "TV_GAMMA" "0..1" [ps20b] [PC]
// DYNAMIC: "DESATURATEENABLE" "0..1" [ps20b] [PC]
// SKIP: ( $TOOL_MODE == 0 ) && $TV_GAMMA
// SKIP: ( $TOOL_MODE == 0 ) && $DESATURATEENABLE
#include "common_ps_fxc.h"
sampler BaseTextureSampler : register( s0 );
sampler FBTextureSampler : register( s1 );
sampler ColorCorrectionVolumeTexture0 : register( s2 );
sampler ColorCorrectionVolumeTexture1 : register( s3 );
sampler ColorCorrectionVolumeTexture2 : register( s4 );
sampler ColorCorrectionVolumeTexture3 : register( s5 );
sampler NoiseSampler : register( s6 );
sampler VignetteSampler : register( s7 );
sampler ScreenEffectSampler : register( s8 ); // used for vomit/paint screen particle effects
float4 psTapOffs_Packed : register( c0 ); // psTapOffs_packed contains 1-pixel offsets: ( +dX, 0, +dY, -dX )
float4 tweakables : register( c1 ); // (x - AA strength/unused) (y - reduction of 1-pixel-line blur)
// (z - edge threshold multipler) (w - tap offset multiplier)
float4 uvTransform : register( c2 ); // Transform BaseTexture UVs for use with the FBTexture
float ColorCorrectionDefaultWeight : register( c3 );
float4 ColorCorrectionVolumeWeights : register( c4 );
// Bloom & Depth Blur parameters
// x: bloom amount; multiply bloom downscale buffer by this value and add to base color
// y: bloom lerp amount; lerp between base color and blurred bloom buffer with this factor (allows for color bleeding in dark areas)
// z: depth blur focal plane distance. Value is in dest alpha space [0,1], not world units.
// w: depth blur scale value; scale distance from focal plane by this amount
float4 BloomParameters : register( c5 );
#define g_flBloomAmount ( BloomParameters.x )
#define g_flBloomLerpFactor ( BloomParameters.y )
#define g_flDepthBlurFocalDistance ( BloomParameters.z )
#define g_flDepthBlurScale ( BloomParameters.w )
float g_flNoiseScalar : register( c6 );
float g_flTime : register( c7 );
float4 g_vLocalContrastParams : register( c8 );
#define g_flLocalContrastStrength g_vLocalContrastParams.x
#define g_flLocalContrastMidToneMask g_vLocalContrastParams.y
#define g_flBlurredVignetteStrength g_vLocalContrastParams.z
float4 g_vLocalContrastVignetteParams : register( c9 );
#define g_flLocalContrastVignetteStart g_vLocalContrastVignetteParams.x
#define g_flLocalContrastVignetteEnd g_vLocalContrastVignetteParams.y
#define g_flLocalContrastEdgeStrength g_vLocalContrastVignetteParams.z
float g_flFadeToBlackStrength : register( c10 );
float4 g_vVomitColor[2] : register( c11 );
#define g_flVomitRefractStrength g_vVomitColor[0].a
float4 g_vViewportTransform : register( c13 );
float4 g_vInvViewportTransform : register( c14 );
float4 g_vViewFadeColor : register( c15 );
float2 g_c16 : register( c16 );
#define g_flDesaturation g_c16.x
#define g_flFadeMode2 g_c16.y
float Luminance( float3 cColor )
{
float3 tmpv = { 0.2125, 0.7154, 0.0721 };
float flLuminance = dot( cColor.rgb, tmpv.rgb );
return flLuminance;
}
float4 GetBloomColor( float2 bloomUV )
{
return tex2D( BaseTextureSampler, bloomUV );
}
float4 PerformColorCorrection( float4 outColor )
{
if (COL_CORRECT_NUM_LOOKUPS > 0)
{
// NOTE: This code requires the color correction texture to be 32 units to be correct.
// This code will cause (0,0,0) to be read from 0.5f/32
// and (1,1,1) to be read from 31.5f/32
float4 offsetOutColor = outColor*(31.0f/32.0f) + (0.5f/32.0f);
outColor.rgb = outColor.rgb * ColorCorrectionDefaultWeight;
outColor.rgb += tex3D( ColorCorrectionVolumeTexture0, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.x;
if (COL_CORRECT_NUM_LOOKUPS > 1)
{
outColor.rgb += tex3D( ColorCorrectionVolumeTexture1, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.y;
if (COL_CORRECT_NUM_LOOKUPS > 2)
{
outColor.rgb += tex3D( ColorCorrectionVolumeTexture2, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.z;
if (COL_CORRECT_NUM_LOOKUPS > 3)
{
outColor.rgb += tex3D( ColorCorrectionVolumeTexture3, offsetOutColor.rgb ) * ColorCorrectionVolumeWeights.w;
}
}
}
}
return outColor;
}
float3 PerformVomitBlend( float3 vRefractParams, float3 vFullResColor, float3 vBlurredColor )
{
float3 vVomitColor = lerp( g_vVomitColor[0].rgb, g_vVomitColor[1].rgb, vRefractParams.z ); // vomit tint
vFullResColor.rgb *= lerp( float3( 1, 1, 1 ), vVomitColor, vRefractParams.z ); // vomit tint full-res buffer
vFullResColor.rgb = lerp ( vFullResColor.rgb, vVomitColor.rgb * vBlurredColor.rgb, vRefractParams.z );
return vFullResColor.rgb;
}
float2 PerformUVTransform( float2 bloomUVs )
{
// NOTE: 'wz' is used since 'zw' is not a valid swizzle for ps20 shaders
return bloomUVs*uvTransform.wz + uvTransform.xy;
}
// Apply TV Gamma for movie layoff specific to 360 TV movie playback path
float3 SrgbGammaToTvGamma( float3 cInput )
{
float3 cLinear = SrgbGammaToLinear( cInput );
return pow( cLinear, 1.0f / 2.5f );
}
struct PS_INPUT
{
float2 baseTexCoord : TEXCOORD0;
};
float4 main( PS_INPUT i ) : COLOR
{
float4 fbTexCoord = 0;
#if !defined( SHADER_MODEL_PS_2_0 )
{
fbTexCoord.xy = PerformUVTransform( i.baseTexCoord );
fbTexCoord.zw = i.baseTexCoord;
}
#else
{
fbTexCoord.xy = PerformUVTransform( i.baseTexCoord );
}
#endif
float4 cBloomBlurredLum = GetBloomColor( i.baseTexCoord ); // bloom color and blurred luminance in alpha
float4 vVomitRefractParams;
#if ( VOMIT_ENABLE == 1 )
{
// perturb texture coordinate
vVomitRefractParams = tex2D( ScreenEffectSampler, i.baseTexCoord );
fbTexCoord = fbTexCoord + g_flVomitRefractStrength * ( vVomitRefractParams.xyxy - 0.5 );
#if !defined( SHADER_MODEL_PS_2_0 )
{
// screen coords -> viewport coords
float4 vNormalizedTexCoord = g_vViewportTransform.xyxy * fbTexCoord + g_vViewportTransform.zwzw;
// mirrored repeat texcoord math doesn't fit into 2.0
vNormalizedTexCoord = min( 2.0 - vNormalizedTexCoord, abs( vNormalizedTexCoord ) );
// viewport coords -> screen coords
fbTexCoord = g_vInvViewportTransform.xyxy * vNormalizedTexCoord + g_vInvViewportTransform.zwzw;
cBloomBlurredLum = GetBloomColor( fbTexCoord.zw ); // fetch again with perturbed texcoords
}
#else
{
cBloomBlurredLum = GetBloomColor( fbTexCoord.xy ); // fetch again with perturbed texcoords
}
#endif
}
#endif
float4 rawColor = tex2D( FBTextureSampler, fbTexCoord.xy ).rgba;
float3 baseColor = rawColor.rgb;
float depthValue = rawColor.a;
#if ( CONVERT_FROM_LINEAR == 1 )
{
baseColor.rgb = SrgbLinearToGamma( baseColor.rgb );
}
#endif
float4 outColor = float4( baseColor, 1 );
#if ( AA_ENABLE == 1 )
{
float3 up;
float3 dn;
float3 lf;
float3 rt;
float3 uplf;
float3 uprt;
float3 dnlf;
float3 dnrt;
#if defined( _X360 )
asm
{
tfetch2D up.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 0.0, OffsetY = -1.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D dn.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 0.0, OffsetY = 1.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D lf.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = -1.0, OffsetY = 0.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D rt.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 1.0, OffsetY = 0.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D uplf.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = -1.0, OffsetY = -1.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D uprt.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 1.0, OffsetY = -1.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D dnlf.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = -1.0, OffsetY = 1.0, MagFilter = point, MinFilter = point, MipFilter = point
tfetch2D dnrt.xyz, fbTexCoord.xy, FBTextureSampler, OffsetX = 1.0, OffsetY = 1.0, MagFilter = point, MinFilter = point, MipFilter = point
};
#else
{
// psTapOffs_packed contains 1-pixel offsets: ( +dX, 0, +dY, -dX )
float4 texelDelta = psTapOffs_Packed.xyzw;
dn = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.yz ).rgb; // ( 0,+1)
rt = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.xy ).rgb; // (+1, 0)
up = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.yz ).rgb; // ( 0,-1)
lf = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.xy ).rgb; // (-1, 0)
dnlf = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.wz ).rgb; // (-1,+1)
uprt = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.wz ).rgb; // (+1,-1)
texelDelta.y = texelDelta.z; // Can't quite get all 8 sample offsets from a single float4 with the allowed swizzles!
uplf = tex2D( FBTextureSampler, fbTexCoord.xy + texelDelta.xy ).rgb; // (+1,+1)
dnrt = tex2D( FBTextureSampler, fbTexCoord.xy - texelDelta.xy ).rgb; // (-1,-1)
}
#endif
// Generate the edge mask
float flBaseLum = Luminance( baseColor.rgb );
float flEdge = saturate( abs( Luminance( dn.rgb ) - flBaseLum ) - 0.1 );
flEdge += saturate( abs( Luminance( up.rgb ) - flBaseLum ) - 0.1 );
flEdge += saturate( abs( Luminance( lf.rgb ) - flBaseLum ) - 0.1 );
flEdge += saturate( abs( Luminance( rt.rgb ) - flBaseLum ) - 0.1 );
flEdge *= 5.0;
#if defined( _X360 )
flEdge *= 4.0; // Magic number to compensate for 360 gamma space
#endif
// Average full 3x3 neighborhood of pixels giving more weight to the center sample
float3 vBlurColor = ( baseColor.rgb * 4.0f ) + up.rgb + dn.rgb + lf.rgb + rt.rgb + dnrt.rgb + uprt.rgb + dnlf.rgb + uplf.rgb;
vBlurColor.rgb *= 0.0833333; // 1.0 / 12.0
// Lerp between crisp and blurry pixel based on edge mask
outColor.rgb = lerp( baseColor.rgb, vBlurColor.rgb, saturate( flEdge ) );
}
#endif
#if ( VOMIT_ENABLE == 1 )
{
outColor.rgb = PerformVomitBlend( vVomitRefractParams.xyz, outColor.rgb, cBloomBlurredLum.aaa );
}
#endif
#if ( LOCAL_CONTRAST_ENABLE == 1 )
{
float fMask = 1.0;
// Extract midtones and limit contrast enhancement there
// TODO: This can probably go away for perf.
//float fBrightness = dot( outColor.rgb, float3( 0.3, 0.59, 0.11 ) );
// bell-shaped mask
//fMask = smoothstep( 0.5 - g_flLocalContrastMidToneMask, 0.5, fBrightness );
//fMask *= smoothstep( 0.5 + g_flLocalContrastMidToneMask, 0.5, fBrightness );
//fMask = smoothstep( 1.0, 0.5, fBrightness );
/*
// unsharp mask on luminance only
// This is the technically correct way, going to YUV, applying contrast to Y, and converting back to RGB
float3 outColorYUV;
outColorYUV.x = dot( outColor.rgb, float3( 0.299, 0.587, 0.114 ) );
outColorYUV.y = dot( outColor.rgb, float3( -0.14713, -0.28886, 0.436 ) );
outColorYUV.z = dot( outColor.rgb, float3( 0.615, -0.51499, -0.10001 ) );
outColorYUV.x = outColorYUV.x + g_flLocalContrastStrength * fMask * ( outColorYUV.x - cBloomBlurredLum.aaa );
outColor.r = dot( outColorYUV.xyz, float3( 1.0, 0.0, 1.13983 ) );
outColor.g = dot( outColorYUV.xyz, float3( 1.0, -0.39465, -0.58060 ) );
outColor.b = dot( outColorYUV.xyz, float3( 1.0, 2.03211, 0.0 ) );
*/
// This applies the delta contrast derived from the luminance to all color channels. The difference to the
// correct way is imperceptible.
float fLuminance = dot( outColor.rgb, float3( 0.299, 0.587, 0.114 ) );
float fContrastLum = fLuminance + g_flLocalContrastStrength * ( fLuminance - cBloomBlurredLum.a );
// Mask off pixels that got very bright, to control super-contrast
//fMask = 1.0 - smoothstep( 0.3, 1.0, fContrastLum );
float2 vCenterDir = ( 2.0 * i.baseTexCoord.xy ) - 1.0;
float fMyVignette = smoothstep( g_flLocalContrastVignetteStart, g_flLocalContrastVignetteEnd, length( vCenterDir ) );
float fMyVignette2 = fMyVignette;
fMyVignette = lerp( g_flLocalContrastStrength, g_flLocalContrastEdgeStrength, fMyVignette );
fMask = fMyVignette;
// If the mask is positive, only brighten pixels. If the mask is negative, don't let it get less than -1.0.
//outColor.rgb += fMask * ( fLuminance - cBloomBlurredLum.aaa );
outColor.rgb += max( fMask * ( fLuminance - cBloomBlurredLum.aaa ), -1.0 + step( 0.0, fMask ) ); // Selective clamp to positive adds 4 instructions
#if ( BLURRED_VIGNETTE_ENABLE == 1 )
outColor.rgb = lerp( outColor.rgb, cBloomBlurredLum.aaa, fMyVignette2 * g_flBlurredVignetteStrength );
#endif
}
#endif
// Composite bloom and full-screen + depth blur effects
#if ( DEPTH_BLUR_ENABLE )
{
float blurFactor = g_flBloomLerpFactor + abs( depthValue - g_flDepthBlurFocalDistance ) * g_flDepthBlurScale;
blurFactor = clamp( blurFactor, 0, 1 );
outColor.rgb = lerp( outColor.rgb, cBloomBlurredLum.rgb, blurFactor );
outColor.rgb += g_flBloomAmount * cBloomBlurredLum.rgb;
}
#else
{
outColor.rgb += g_flBloomAmount * cBloomBlurredLum.rgb;
}
#endif
// Used to be FADE_TYPE 0..2 combo
float3 vFadeDestColor = lerp( g_vViewFadeColor.rgb, g_vViewFadeColor.rgb * outColor.rgb, g_flFadeMode2 );
outColor.rgb = lerp( outColor.rgb, vFadeDestColor.rgb, g_vViewFadeColor.a );
#if ( DESATURATEENABLE )
{
float flLum = saturate( dot( outColor.rgb, float3( 0.3f, 0.59f, 0.11f) ) );
outColor.rgb = lerp( saturate( outColor.rgb ), flLum.xxx, saturate( g_flDesaturation ) );
}
#else
{
outColor = PerformColorCorrection( outColor ); // Color correction
}
#endif
// Vignette
#if ( VIGNETTE_ENABLE == 1 )
{
// Vignette
float2 vUv = i.baseTexCoord.xy;
//float2 vTmp = ( vUv.xy * 2.0 ) - 1.0;
float flVignette;
#if defined( _X360 )
{
// Make title safe and deal with different gamma space
//flVignette = 1.0 - pow( abs( vTmp.x ), 4.0f );
//flVignette *= 1.0 - pow( abs( vTmp.y ), 4.0f );
//flVignette = 1.0 - ( 1.0 - flVignette ) * ( ( saturate( ( 1.0 - vUv.y ) - 0.1 ) / 0.9 ) );
// This tex2D solves the 3 lines of math above
flVignette = tex2D( VignetteSampler, vUv.xy ).g; // Green is for the 360
flVignette = saturate( flVignette * 0.75 + 0.26 );
}
#else
{
//flVignette = 1.0 - pow( abs( vTmp.x ), 6.0f );
//flVignette *= 1.0 - pow( abs( vTmp.y ), 6.0f );
//flVignette = 1.0 - ( 1.0 - flVignette ) * ( ( saturate( ( 1.0 - vUv.y ) - 0.3 ) / 0.7 ) );
// This tex2D solves the 3 lines of math above
flVignette = tex2D( VignetteSampler, vUv.xy ).r; // Red is for the PC
flVignette = saturate( flVignette * 0.55 + 0.46 );
}
#endif
outColor.rgb *= flVignette;
}
#endif
// Noise
#if ( NOISE_ENABLE == 1 )
{
// Additive Noise
float2 vUv0 = i.baseTexCoord.xy * 10.0 + g_flTime;
float2 vUv1 = i.baseTexCoord.yx * 20.0 - g_flTime;
float2 vNoiseTexelUv;
vNoiseTexelUv.x = tex2D( NoiseSampler, vUv0.xy ).g;
vNoiseTexelUv.y = tex2D( NoiseSampler, vUv1.xy ).g;
float flNoiseTexel = tex2D( NoiseSampler, vNoiseTexelUv.xy ).g;
float3 vTmp = { 0.2125f, 0.7154f, 0.0721f };
float flLuminance = saturate( dot( outColor.rgb, vTmp.rgb ) );
#if defined( _X360 )
{
// 360
float flNoiseScalar = 0.2f + 1.0f * ( saturate( pow( 1.0 - flLuminance, 64.0 ) ) );
outColor.rgb += ( ( flNoiseTexel * 0.3f ) - 0.15f ) * g_flNoiseScalar * flNoiseScalar;
}
#else
{
// PC
float flNoiseScalar = 0.2f + 0.8f * ( saturate( pow( 1.0 - flLuminance, 12.0 ) ) );
outColor.rgb += ( ( flNoiseTexel * 0.3f ) - 0.15f ) * g_flNoiseScalar * flNoiseScalar;
}
#endif
}
#endif
// Fade to black
outColor.rgb = lerp( outColor.rgb, 0.0, g_flFadeToBlackStrength );
#if TV_GAMMA
{
// Used for SFM to record movies in native TV gamma space
outColor.rgb = SrgbGammaToTvGamma( outColor.rgb );
}
#endif
#if ( CONVERT_TO_LINEAR == 1 )
{
// If we have a float back buffer, we want to remain in linear space after this shader
outColor.rgb = SrgbGammaToLinear( outColor.rgb );
}
#endif
return FinalOutput( outColor, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE );
}