diff options
Diffstat (limited to 'mp/src/materialsystem/stdshaders/common_ps_fxc.h')
| -rw-r--r-- | mp/src/materialsystem/stdshaders/common_ps_fxc.h | 1608 |
1 files changed, 804 insertions, 804 deletions
diff --git a/mp/src/materialsystem/stdshaders/common_ps_fxc.h b/mp/src/materialsystem/stdshaders/common_ps_fxc.h index d4a47ea5..fca6511f 100644 --- a/mp/src/materialsystem/stdshaders/common_ps_fxc.h +++ b/mp/src/materialsystem/stdshaders/common_ps_fxc.h @@ -1,804 +1,804 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Common pixel shader code
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-#ifndef COMMON_PS_FXC_H_
-#define COMMON_PS_FXC_H_
-
-#include "common_fxc.h"
-
-// Put global skip commands here. . make sure and check that the appropriate vars are defined
-// so these aren't used on the wrong shaders!
-
-// --------------------------------------------------------------------------------
-// HDR should never be enabled if we don't aren't running in float or integer HDR mode.
-// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED
-// --------------------------------------------------------------------------------
-// We don't ever write water fog to dest alpha if we aren't doing water fog.
-// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA
-// --------------------------------------------------------------------------------
-// We don't need fog in the pixel shader if we aren't in float fog mode2
-// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0
-// --------------------------------------------------------------------------------
-// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer.
-// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0
-// --------------------------------------------------------------------------------
-// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW.
-// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT
-// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST
-// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH
-// --------------------------------------------------------------------------------
-// Ditch flashlight depth when flashlight is disabled
-// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW
-// --------------------------------------------------------------------------------
-
-// System defined pixel shader constants
-
-#if defined( _X360 )
-const bool g_bHighQualityShadows : register( b0 );
-#endif
-
-// NOTE: w == 1.0f / (Dest alpha compressed depth range).
-const float4 g_LinearFogColor : register( c29 );
-#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w)
-
-// Linear and gamma light scale values
-const float4 cLightScale : register( c30 );
-#define LINEAR_LIGHT_SCALE (cLightScale.x)
-#define LIGHT_MAP_SCALE (cLightScale.y)
-#define ENV_MAP_SCALE (cLightScale.z)
-#define GAMMA_LIGHT_SCALE (cLightScale.w)
-
-// Flashlight constants
-#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
- const float4 cFlashlightColor : register( c28 );
- const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused
- #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0
-#endif
-
-#define HDR_INPUT_MAP_SCALE 16.0f
-
-#define TONEMAP_SCALE_NONE 0
-#define TONEMAP_SCALE_LINEAR 1
-#define TONEMAP_SCALE_GAMMA 2
-
-#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader
-#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits)
-#define PIXEL_FOG_TYPE_HEIGHT 1
-
-// If you change these, make the corresponding change in hardwareconfig.cpp
-#define NVIDIA_PCF_POISSON 0
-#define ATI_NOPCF 1
-#define ATI_NO_PCF_FETCH4 2
-
-struct LPREVIEW_PS_OUT
-{
- float4 color : COLOR0;
- float4 normal : COLOR1;
- float4 position : COLOR2;
- float4 flags : COLOR3;
-};
-
-/*
-// unused
-HALF Luminance( HALF3 color )
-{
- return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) );
-}
-*/
-
-/*
-// unused
-HALF LuminanceScaled( HALF3 color )
-{
- return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) );
-}
-*/
-
-/*
-// unused
-HALF AvgColor( HALF3 color )
-{
- return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) );
-}
-*/
-
-/*
-// unused
-HALF4 DiffuseBump( sampler lightmapSampler,
- float2 lightmapTexCoord1,
- float2 lightmapTexCoord2,
- float2 lightmapTexCoord3,
- HALF3 normal )
-{
- HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 );
- HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 );
- HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 );
-
- HALF3 diffuseLighting;
- diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 +
- saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 +
- saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3;
-
- return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) );
-}
-*/
-
-
-/*
-// unused
-HALF Fresnel( HALF3 normal,
- HALF3 eye,
- HALF2 scaleBias )
-{
- HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye );
- fresnel = pow( fresnel, HALF_CONSTANT(5.0f) );
-
- return fresnel * scaleBias.x + scaleBias.y;
-}
-*/
-
-/*
-// unused
-HALF4 GetNormal( sampler normalSampler,
- float2 normalTexCoord )
-{
- HALF4 normal = tex2D( normalSampler, normalTexCoord );
- normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f);
-
- return normal;
-}
-*/
-
-// Needs to match NormalDecodeMode_t enum in imaterialsystem.h
-#define NORM_DECODE_NONE 0
-#define NORM_DECODE_ATI2N 1
-#define NORM_DECODE_ATI2N_ALPHA 2
-
-float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler )
-{
- float4 normalTexel = tex2D( NormalSampler, tc );
- float4 result;
-
- if ( nDecompressionMode == NORM_DECODE_NONE )
- {
- result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a );
- }
- else if ( nDecompressionMode == NORM_DECODE_ATI2N )
- {
- result.xy = normalTexel.xy * 2.0f - 1.0f;
- result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
- result.a = 1.0f;
- }
- else // ATI2N plus ATI1N for alpha
- {
- result.xy = normalTexel.xy * 2.0f - 1.0f;
- result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
- result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel
- }
-
- return result;
-}
-
-float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode )
-{
- return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler );
-}
-
-
-HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input )
-{
-// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;
- return texCUBE( normalizeSampler, input );
-}
-
-/*
-HALF4 EnvReflect( sampler envmapSampler,
- sampler normalizeSampler,
- HALF3 normal,
- float3 eye,
- HALF2 fresnelScaleBias )
-{
- HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye );
- HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias );
- HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye );
- return texCUBE( envmapSampler, reflect );
-}
-*/
-
-float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )
-{
-// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp
- float flDepthFromWater = flWaterZ - flWorldPosZ;
-
- // if flDepthFromWater < 0, then set it to 0
- // This is the equivalent of moving the vert to the water surface if it's above the water surface
- // We'll do this with the saturate at the end instead.
-// flDepthFromWater = max( 0.0f, flDepthFromWater );
-
- // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer
- // to the vert is actually underwater.
- float flDepthFromEye = flEyePosZ - flWorldPosZ;
- float f = saturate(flDepthFromWater * (1.0/flDepthFromEye));
-
- // $tmp.w is now the distance that we see through water.
- return saturate(f * flProjPosZ * flFogOORange);
-}
-
-float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange )
-{
-#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
- return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) );
-#else
- return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots.
-#endif
-}
-
-float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )
-{
- float retVal;
- if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
- {
- retVal = 0.0f;
- }
- if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters
- {
- retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );
- }
- else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog
- {
- retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );
- }
-
- return retVal;
-}
-
-//g_FogParams not defined by default, but this is the same layout for every shader that does define it
-#define g_FogEndOverRange g_FogParams.x
-#define g_WaterZ g_FogParams.y
-#define g_FogMaxDensity g_FogParams.z
-#define g_FogOORange g_FogParams.w
-
-float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE )
-{
- if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b
- {
-# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
- pixelFogFactor = saturate( pixelFogFactor );
- return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
-# else
- return vShaderColor;
-# endif
- }
- else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
- {
- return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );
- }
- else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
- {
- return vShaderColor;
- }
-}
-
-
-#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) )
-sampler1D GammaTableSampler : register( s15 );
-
-float3 SRGBOutput( const float3 vShaderColor )
-{
- //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15.
- float3 result;
- result.r = tex1D( GammaTableSampler, vShaderColor.r ).r;
- result.g = tex1D( GammaTableSampler, vShaderColor.g ).r;
- result.b = tex1D( GammaTableSampler, vShaderColor.b ).r;
- return result;
-}
-
-#else
-
-float3 SRGBOutput( const float3 vShaderColor )
-{
- return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader
-}
-
-#endif
-
-
-float SoftParticleDepth( float flDepth )
-{
- return flDepth * OO_DESTALPHA_DEPTH_RANGE;
-}
-
-
-float DepthToDestAlpha( const float flProjZ )
-{
-#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
- return SoftParticleDepth( flProjZ );
-#else
- return 1.0f;
-#endif
-}
-
-
-float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )
-{
- float4 result;
- if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
- {
- result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE;
- }
- else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
- {
- result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE;
- }
- else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )
- {
- result.rgb = vShaderColor.rgb;
- }
-
- if( bWriteDepthToDestAlpha )
- result.a = DepthToDestAlpha( flProjZ );
- else
- result.a = vShaderColor.a;
-
- result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );
-
-#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
- result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion
-#endif
-
- return result;
-}
-
-LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE )
-{
- LPREVIEW_PS_OUT result;
- result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE );
- result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb );
- result.normal.a = vShaderColor.normal.a;
-
- result.position.rgb = SRGBOutput( vShaderColor.position.rgb );
- result.position.a = vShaderColor.position.a;
-
- result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb );
- result.flags.a = vShaderColor.flags.a;
-
- return result;
-}
-
-
-
-
-float RemapValClamped( float val, float A, float B, float C, float D)
-{
- float cVal = (val - A) / (B - A);
- cVal = saturate( cVal );
-
- return C + (D - C) * cVal;
-}
-
-
-//===================================================================================//
-// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI)
-//===================================================================================//
-// INPUT:
-// inTexCoord:
-// the texcoord for the height/displacement map before parallaxing
-//
-// vParallax:
-// Compute initial parallax displacement direction:
-// float2 vParallaxDirection = normalize( vViewTS.xy );
-// float fLength = length( vViewTS );
-// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z;
-// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight;
-//
-// vNormal:
-// tangent space normal
-//
-// vViewW:
-// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition );
-//
-// OUTPUT:
-// the new texcoord after parallaxing
-float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal,
- float3 vViewW, sampler HeightMapSampler )
-{
- const int nMinSamples = 8;
- const int nMaxSamples = 50;
-
- // Normalize the incoming view vector to avoid artifacts:
-// vView = normalize( vView );
- vViewW = normalize( vViewW );
-// vLight = normalize( vLight );
-
- // Change the number of samples per ray depending on the viewing angle
- // for the surface. Oblique angles require smaller step sizes to achieve
- // more accurate precision
- int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) );
-
- float4 cResultColor = float4( 0, 0, 0, 1 );
-
- //===============================================//
- // Parallax occlusion mapping offset computation //
- //===============================================//
- float fCurrHeight = 0.0;
- float fStepSize = 1.0 / (float) nNumSteps;
- float fPrevHeight = 1.0;
- float fNextHeight = 0.0;
-
- int nStepIndex = 0;
-// bool bCondition = true;
-
- float2 dx = ddx( inTexCoord );
- float2 dy = ddy( inTexCoord );
-
- float2 vTexOffsetPerStep = fStepSize * vParallax;
-
- float2 vTexCurrentOffset = inTexCoord;
- float fCurrentBound = 1.0;
-
- float x = 0;
- float y = 0;
- float xh = 0;
- float yh = 0;
-
- float2 texOffset2 = 0;
-
- bool bCondition = true;
- while ( bCondition == true && nStepIndex < nNumSteps )
- {
- vTexCurrentOffset -= vTexOffsetPerStep;
-
- fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r;
-
- fCurrentBound -= fStepSize;
-
- if ( fCurrHeight > fCurrentBound )
- {
- x = fCurrentBound;
- y = fCurrentBound + fStepSize;
- xh = fCurrHeight;
- yh = fPrevHeight;
-
- texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;
-
- bCondition = false;
- }
- else
- {
- nStepIndex++;
- fPrevHeight = fCurrHeight;
- }
-
- } // End of while ( bCondition == true && nStepIndex > -1 )#else
-
- fCurrentBound -= fStepSize;
-
- float fParallaxAmount;
- float numerator = (x * (y - yh) - y * (x - xh));
- float denomenator = ((y - yh) - (x - xh));
- // avoid NaN generation
- if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) )
- {
- fParallaxAmount = 0.0f;
- }
- else
- {
- fParallaxAmount = numerator / denomenator;
- }
-
- float2 vParallaxOffset = vParallax * (1 - fParallaxAmount );
-
- // Sample the height at the next possible step:
- fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r;
-
- // Original offset:
- float2 texSampleBase = inTexCoord - vParallaxOffset;
-
- return texSampleBase;
-
-#if 0
- cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight );
-
- float fBound = 1.0 - fStepSize * nStepIndex;
- if ( fNextHeight < fCurrentBound )
-// if( 0 )
- {
- //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor )
- //cResultColor.rgb = float3(1,0,0);
- DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
- DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
- DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
- DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
-
- cResultColor.rgb /= 5;
-// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f );
- } // End of if ( fNextHeight < fCurrentBound )
-
-#if DOSHADOWS
- {
- //============================================//
- // Soft shadow and self-occlusion computation //
- //============================================//
- // Compute the blurry shadows (note that this computation takes into
- // account self-occlusion for shadow computation):
- float sh0 = tex2D( sNormalMap, texSampleBase).w;
- float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening;
- float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening;
- float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening;
- float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening;
- float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening;
- float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening;
- float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening;
-
- // Compute the actual shadow strength:
- float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );
-
- cResultColor.rgb *= fShadow * 0.6 + 0.4;
- }
-#endif
-
- return cResultColor;
-#endif
-}
-
-
-//======================================//
-// HSL Color space conversion routines //
-//======================================//
-
-#define HUE 0
-#define SATURATION 1
-#define LIGHTNESS 2
-
-// Convert from RGB to HSL color space
-float4 RGBtoHSL( float4 inColor )
-{
- float h, s;
- float flMax = max( inColor.r, max( inColor.g, inColor.b ) );
- float flMin = min( inColor.r, min( inColor.g, inColor.b ) );
-
- float l = (flMax + flMin) / 2.0f;
-
- if (flMax == flMin) // achromatic case
- {
- s = h = 0;
- }
- else // chromatic case
- {
- // Next, calculate the hue
- float delta = flMax - flMin;
-
- // First, calculate the saturation
- if (l < 0.5f) // If we're in the lower hexcone
- {
- s = delta/(flMax + flMin);
- }
- else
- {
- s = delta/(2 - flMax - flMin);
- }
-
- if ( inColor.r == flMax )
- {
- h = (inColor.g - inColor.b)/delta; // color between yellow and magenta
- }
- else if ( inColor.g == flMax )
- {
- h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow
- }
- else // blue must be max
- {
- h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan
- }
-
- h *= 60.0f;
-
- if (h < 0.0f)
- {
- h += 360.0f;
- }
-
- h /= 360.0f;
- }
-
- return float4 (h, s, l, 1.0f);
-}
-
-float HueToRGB( float v1, float v2, float vH )
-{
- float fResult = v1;
-
- vH = fmod (vH + 1.0f, 1.0f);
-
- if ( ( 6.0f * vH ) < 1.0f )
- {
- fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH );
- }
- else if ( ( 2.0f * vH ) < 1.0f )
- {
- fResult = ( v2 );
- }
- else if ( ( 3.0f * vH ) < 2.0f )
- {
- fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );
- }
-
- return fResult;
-}
-
-// Convert from HSL to RGB color space
-float4 HSLtoRGB( float4 hsl )
-{
- float r, g, b;
- float h = hsl[HUE];
- float s = hsl[SATURATION];
- float l = hsl[LIGHTNESS];
-
- if ( s == 0 )
- {
- r = g = b = l;
- }
- else
- {
- float v1, v2;
-
- if ( l < 0.5f )
- v2 = l * ( 1.0f + s );
- else
- v2 = ( l + s ) - ( s * l );
-
- v1 = 2 * l - v2;
-
- r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) );
- g = HueToRGB( v1, v2, h );
- b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) );
- }
-
- return float4( r, g, b, 1.0f );
-}
-
-
-// texture combining modes for combining base and detail/basetexture2
-#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode
-#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend
-#define TCOMBINE_DETAIL_OVER_BASE 2
-#define TCOMBINE_FADE 3 // straight fade between base and detail.
-#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail
-#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting
-#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6
-#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail
-#define TCOMBINE_MULTIPLY 8
-#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base
-#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump
-#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11
-
-float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode,
- float fBlendFactor )
-{
- if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS)
- {
- float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a);
- baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor);
- }
- if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2)
- baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor);
- if ( combine_mode == TCOMBINE_RGB_ADDITIVE )
- baseColor.rgb += fBlendFactor * detailColor.rgb;
- if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE )
- {
- float fblend=fBlendFactor * detailColor.a;
- baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend);
- }
- if ( combine_mode == TCOMBINE_FADE )
- {
- baseColor = lerp( baseColor, detailColor, fBlendFactor);
- }
- if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL )
- {
- float fblend=fBlendFactor * (1-baseColor.a);
- baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend );
- baseColor.a = detailColor.a;
- }
- if ( combine_mode == TCOMBINE_MULTIPLY )
- {
- baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor);
- }
-
- if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA )
- {
- baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor );
- }
- if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP )
- {
- baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 );
- }
- return baseColor;
-}
-
-float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x)
-{
- return f1+(f2-f1)*(x-i1)/(i2-i1);
-}
-
-float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode,
- float fBlendFactor )
-{
- if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM )
- lit_baseColor += fBlendFactor * detailColor.rgb;
- if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE )
- {
- // fade in an unusual way - instead of fading out color, remap an increasing band of it from
- // 0..1
- //if (fBlendFactor > 0.5)
- // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) );
- //else
- // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5);
-
- float f = fBlendFactor - 0.5;
- float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor;
- float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult;
- lit_baseColor += saturate(fMult * detailColor.rgb + fAdd);
- }
- return lit_baseColor;
-}
-
-//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader
-float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants )
-{
-# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b
- {
- float flFeatheredAlpha;
- float2 flDepths;
-#define flSceneDepth flDepths.x
-#define flSpriteDepth flDepths.y
-
-# if ( defined( _X360 ) )
- {
- //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors
- asm {
- tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point
- };
-
-# if( !defined( REVERSE_DEPTH_ON_X360 ) )
- flSceneDepth = 1.0f - flSceneDepth;
-# endif
-
- //get the sprite depth into the same range as the texture depth
- flSpriteDepth = fProjZ / fProjW;
-
- //unproject to get at the pre-projection z. This value is much more linear than depth
- flDepths = vDepthBlendConstants.z / flDepths;
- flDepths = vDepthBlendConstants.y - flDepths;
-
- flFeatheredAlpha = flSceneDepth - flSpriteDepth;
- flFeatheredAlpha *= vDepthBlendConstants.x;
- flFeatheredAlpha = saturate( flFeatheredAlpha );
- }
-# else
- {
- flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer
- flSpriteDepth = SoftParticleDepth( fProjZ );
-
- flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x;
- flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering.
- flFeatheredAlpha = saturate( flFeatheredAlpha );
- }
-# endif
-
-#undef flSceneDepth
-#undef flSpriteDepth
-
- return flFeatheredAlpha;
- }
-# else
- {
- return 1.0f;
- }
-# endif
-}
-
-#endif //#ifndef COMMON_PS_FXC_H_
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Common pixel shader code +// +// $NoKeywords: $ +// +//=============================================================================// +#ifndef COMMON_PS_FXC_H_ +#define COMMON_PS_FXC_H_ + +#include "common_fxc.h" + +// Put global skip commands here. . make sure and check that the appropriate vars are defined +// so these aren't used on the wrong shaders! + +// -------------------------------------------------------------------------------- +// HDR should never be enabled if we don't aren't running in float or integer HDR mode. +// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED +// -------------------------------------------------------------------------------- +// We don't ever write water fog to dest alpha if we aren't doing water fog. +// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA +// -------------------------------------------------------------------------------- +// We don't need fog in the pixel shader if we aren't in float fog mode2 +// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0 +// -------------------------------------------------------------------------------- +// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer. +// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0 +// -------------------------------------------------------------------------------- +// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW. +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST +// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH +// -------------------------------------------------------------------------------- +// Ditch flashlight depth when flashlight is disabled +// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW +// -------------------------------------------------------------------------------- + +// System defined pixel shader constants + +#if defined( _X360 ) +const bool g_bHighQualityShadows : register( b0 ); +#endif + +// NOTE: w == 1.0f / (Dest alpha compressed depth range). +const float4 g_LinearFogColor : register( c29 ); +#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w) + +// Linear and gamma light scale values +const float4 cLightScale : register( c30 ); +#define LINEAR_LIGHT_SCALE (cLightScale.x) +#define LIGHT_MAP_SCALE (cLightScale.y) +#define ENV_MAP_SCALE (cLightScale.z) +#define GAMMA_LIGHT_SCALE (cLightScale.w) + +// Flashlight constants +#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) + const float4 cFlashlightColor : register( c28 ); + const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused + #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0 +#endif + +#define HDR_INPUT_MAP_SCALE 16.0f + +#define TONEMAP_SCALE_NONE 0 +#define TONEMAP_SCALE_LINEAR 1 +#define TONEMAP_SCALE_GAMMA 2 + +#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader +#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits) +#define PIXEL_FOG_TYPE_HEIGHT 1 + +// If you change these, make the corresponding change in hardwareconfig.cpp +#define NVIDIA_PCF_POISSON 0 +#define ATI_NOPCF 1 +#define ATI_NO_PCF_FETCH4 2 + +struct LPREVIEW_PS_OUT +{ + float4 color : COLOR0; + float4 normal : COLOR1; + float4 position : COLOR2; + float4 flags : COLOR3; +}; + +/* +// unused +HALF Luminance( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) ); +} +*/ + +/* +// unused +HALF LuminanceScaled( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) ); +} +*/ + +/* +// unused +HALF AvgColor( HALF3 color ) +{ + return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); +} +*/ + +/* +// unused +HALF4 DiffuseBump( sampler lightmapSampler, + float2 lightmapTexCoord1, + float2 lightmapTexCoord2, + float2 lightmapTexCoord3, + HALF3 normal ) +{ + HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 ); + HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 ); + HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 ); + + HALF3 diffuseLighting; + diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 + + saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 + + saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3; + + return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) ); +} +*/ + + +/* +// unused +HALF Fresnel( HALF3 normal, + HALF3 eye, + HALF2 scaleBias ) +{ + HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye ); + fresnel = pow( fresnel, HALF_CONSTANT(5.0f) ); + + return fresnel * scaleBias.x + scaleBias.y; +} +*/ + +/* +// unused +HALF4 GetNormal( sampler normalSampler, + float2 normalTexCoord ) +{ + HALF4 normal = tex2D( normalSampler, normalTexCoord ); + normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f); + + return normal; +} +*/ + +// Needs to match NormalDecodeMode_t enum in imaterialsystem.h +#define NORM_DECODE_NONE 0 +#define NORM_DECODE_ATI2N 1 +#define NORM_DECODE_ATI2N_ALPHA 2 + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler ) +{ + float4 normalTexel = tex2D( NormalSampler, tc ); + float4 result; + + if ( nDecompressionMode == NORM_DECODE_NONE ) + { + result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a ); + } + else if ( nDecompressionMode == NORM_DECODE_ATI2N ) + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = 1.0f; + } + else // ATI2N plus ATI1N for alpha + { + result.xy = normalTexel.xy * 2.0f - 1.0f; + result.z = sqrt( 1.0f - dot(result.xy, result.xy) ); + result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel + } + + return result; +} + +float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode ) +{ + return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler ); +} + + +HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input ) +{ +// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f; + return texCUBE( normalizeSampler, input ); +} + +/* +HALF4 EnvReflect( sampler envmapSampler, + sampler normalizeSampler, + HALF3 normal, + float3 eye, + HALF2 fresnelScaleBias ) +{ + HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye ); + HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias ); + HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye ); + return texCUBE( envmapSampler, reflect ); +} +*/ + +float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange ) +{ +// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp + float flDepthFromWater = flWaterZ - flWorldPosZ; + + // if flDepthFromWater < 0, then set it to 0 + // This is the equivalent of moving the vert to the water surface if it's above the water surface + // We'll do this with the saturate at the end instead. +// flDepthFromWater = max( 0.0f, flDepthFromWater ); + + // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer + // to the vert is actually underwater. + float flDepthFromEye = flEyePosZ - flWorldPosZ; + float f = saturate(flDepthFromWater * (1.0/flDepthFromEye)); + + // $tmp.w is now the distance that we see through water. + return saturate(f * flProjPosZ * flFogOORange); +} + +float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange ) +{ +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) ); +#else + return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots. +#endif +} + +float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float retVal; + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + retVal = 0.0f; + } + if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters + { + retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + } + else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog + { + retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + } + + return retVal; +} + +//g_FogParams not defined by default, but this is the same layout for every shader that does define it +#define g_FogEndOverRange g_FogParams.x +#define g_WaterZ g_FogParams.y +#define g_FogMaxDensity g_FogParams.z +#define g_FogOORange g_FogParams.w + +float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE ) +{ + if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b + { +# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + pixelFogFactor = saturate( pixelFogFactor ); + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog +# else + return vShaderColor; +# endif + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + { + return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + } + else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE ) + { + return vShaderColor; + } +} + + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) ) +sampler1D GammaTableSampler : register( s15 ); + +float3 SRGBOutput( const float3 vShaderColor ) +{ + //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15. + float3 result; + result.r = tex1D( GammaTableSampler, vShaderColor.r ).r; + result.g = tex1D( GammaTableSampler, vShaderColor.g ).r; + result.b = tex1D( GammaTableSampler, vShaderColor.b ).r; + return result; +} + +#else + +float3 SRGBOutput( const float3 vShaderColor ) +{ + return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader +} + +#endif + + +float SoftParticleDepth( float flDepth ) +{ + return flDepth * OO_DESTALPHA_DEPTH_RANGE; +} + + +float DepthToDestAlpha( const float flProjZ ) +{ +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + return SoftParticleDepth( flProjZ ); +#else + return 1.0f; +#endif +} + + +float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f ) +{ + float4 result; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE ) + { + result.rgb = vShaderColor.rgb; + } + + if( bWriteDepthToDestAlpha ) + result.a = DepthToDestAlpha( flProjZ ); + else + result.a = vShaderColor.a; + + result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE ); + +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion +#endif + + return result; +} + +LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE ) +{ + LPREVIEW_PS_OUT result; + result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE ); + result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb ); + result.normal.a = vShaderColor.normal.a; + + result.position.rgb = SRGBOutput( vShaderColor.position.rgb ); + result.position.a = vShaderColor.position.a; + + result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb ); + result.flags.a = vShaderColor.flags.a; + + return result; +} + + + + +float RemapValClamped( float val, float A, float B, float C, float D) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + + return C + (D - C) * cVal; +} + + +//===================================================================================// +// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI) +//===================================================================================// +// INPUT: +// inTexCoord: +// the texcoord for the height/displacement map before parallaxing +// +// vParallax: +// Compute initial parallax displacement direction: +// float2 vParallaxDirection = normalize( vViewTS.xy ); +// float fLength = length( vViewTS ); +// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z; +// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight; +// +// vNormal: +// tangent space normal +// +// vViewW: +// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition ); +// +// OUTPUT: +// the new texcoord after parallaxing +float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal, + float3 vViewW, sampler HeightMapSampler ) +{ + const int nMinSamples = 8; + const int nMaxSamples = 50; + + // Normalize the incoming view vector to avoid artifacts: +// vView = normalize( vView ); + vViewW = normalize( vViewW ); +// vLight = normalize( vLight ); + + // Change the number of samples per ray depending on the viewing angle + // for the surface. Oblique angles require smaller step sizes to achieve + // more accurate precision + int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) ); + + float4 cResultColor = float4( 0, 0, 0, 1 ); + + //===============================================// + // Parallax occlusion mapping offset computation // + //===============================================// + float fCurrHeight = 0.0; + float fStepSize = 1.0 / (float) nNumSteps; + float fPrevHeight = 1.0; + float fNextHeight = 0.0; + + int nStepIndex = 0; +// bool bCondition = true; + + float2 dx = ddx( inTexCoord ); + float2 dy = ddy( inTexCoord ); + + float2 vTexOffsetPerStep = fStepSize * vParallax; + + float2 vTexCurrentOffset = inTexCoord; + float fCurrentBound = 1.0; + + float x = 0; + float y = 0; + float xh = 0; + float yh = 0; + + float2 texOffset2 = 0; + + bool bCondition = true; + while ( bCondition == true && nStepIndex < nNumSteps ) + { + vTexCurrentOffset -= vTexOffsetPerStep; + + fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r; + + fCurrentBound -= fStepSize; + + if ( fCurrHeight > fCurrentBound ) + { + x = fCurrentBound; + y = fCurrentBound + fStepSize; + xh = fCurrHeight; + yh = fPrevHeight; + + texOffset2 = vTexCurrentOffset - vTexOffsetPerStep; + + bCondition = false; + } + else + { + nStepIndex++; + fPrevHeight = fCurrHeight; + } + + } // End of while ( bCondition == true && nStepIndex > -1 )#else + + fCurrentBound -= fStepSize; + + float fParallaxAmount; + float numerator = (x * (y - yh) - y * (x - xh)); + float denomenator = ((y - yh) - (x - xh)); + // avoid NaN generation + if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) ) + { + fParallaxAmount = 0.0f; + } + else + { + fParallaxAmount = numerator / denomenator; + } + + float2 vParallaxOffset = vParallax * (1 - fParallaxAmount ); + + // Sample the height at the next possible step: + fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r; + + // Original offset: + float2 texSampleBase = inTexCoord - vParallaxOffset; + + return texSampleBase; + +#if 0 + cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight ); + + float fBound = 1.0 - fStepSize * nStepIndex; + if ( fNextHeight < fCurrentBound ) +// if( 0 ) + { + //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor ) + //cResultColor.rgb = float3(1,0,0); + DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor ); + + cResultColor.rgb /= 5; +// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f ); + } // End of if ( fNextHeight < fCurrentBound ) + +#if DOSHADOWS + { + //============================================// + // Soft shadow and self-occlusion computation // + //============================================// + // Compute the blurry shadows (note that this computation takes into + // account self-occlusion for shadow computation): + float sh0 = tex2D( sNormalMap, texSampleBase).w; + float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening; + float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening; + float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening; + float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening; + float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening; + float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening; + float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening; + + // Compute the actual shadow strength: + float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 ); + + cResultColor.rgb *= fShadow * 0.6 + 0.4; + } +#endif + + return cResultColor; +#endif +} + + +//======================================// +// HSL Color space conversion routines // +//======================================// + +#define HUE 0 +#define SATURATION 1 +#define LIGHTNESS 2 + +// Convert from RGB to HSL color space +float4 RGBtoHSL( float4 inColor ) +{ + float h, s; + float flMax = max( inColor.r, max( inColor.g, inColor.b ) ); + float flMin = min( inColor.r, min( inColor.g, inColor.b ) ); + + float l = (flMax + flMin) / 2.0f; + + if (flMax == flMin) // achromatic case + { + s = h = 0; + } + else // chromatic case + { + // Next, calculate the hue + float delta = flMax - flMin; + + // First, calculate the saturation + if (l < 0.5f) // If we're in the lower hexcone + { + s = delta/(flMax + flMin); + } + else + { + s = delta/(2 - flMax - flMin); + } + + if ( inColor.r == flMax ) + { + h = (inColor.g - inColor.b)/delta; // color between yellow and magenta + } + else if ( inColor.g == flMax ) + { + h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow + } + else // blue must be max + { + h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan + } + + h *= 60.0f; + + if (h < 0.0f) + { + h += 360.0f; + } + + h /= 360.0f; + } + + return float4 (h, s, l, 1.0f); +} + +float HueToRGB( float v1, float v2, float vH ) +{ + float fResult = v1; + + vH = fmod (vH + 1.0f, 1.0f); + + if ( ( 6.0f * vH ) < 1.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH ); + } + else if ( ( 2.0f * vH ) < 1.0f ) + { + fResult = ( v2 ); + } + else if ( ( 3.0f * vH ) < 2.0f ) + { + fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f ); + } + + return fResult; +} + +// Convert from HSL to RGB color space +float4 HSLtoRGB( float4 hsl ) +{ + float r, g, b; + float h = hsl[HUE]; + float s = hsl[SATURATION]; + float l = hsl[LIGHTNESS]; + + if ( s == 0 ) + { + r = g = b = l; + } + else + { + float v1, v2; + + if ( l < 0.5f ) + v2 = l * ( 1.0f + s ); + else + v2 = ( l + s ) - ( s * l ); + + v1 = 2 * l - v2; + + r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) ); + g = HueToRGB( v1, v2, h ); + b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) ); + } + + return float4( r, g, b, 1.0f ); +} + + +// texture combining modes for combining base and detail/basetexture2 +#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode +#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend +#define TCOMBINE_DETAIL_OVER_BASE 2 +#define TCOMBINE_FADE 3 // straight fade between base and detail. +#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting +#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6 +#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail +#define TCOMBINE_MULTIPLY 8 +#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base +#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump +#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11 + +float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS) + { + float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a); + baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor); + } + if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2) + baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor); + if ( combine_mode == TCOMBINE_RGB_ADDITIVE ) + baseColor.rgb += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE ) + { + float fblend=fBlendFactor * detailColor.a; + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend); + } + if ( combine_mode == TCOMBINE_FADE ) + { + baseColor = lerp( baseColor, detailColor, fBlendFactor); + } + if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL ) + { + float fblend=fBlendFactor * (1-baseColor.a); + baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend ); + baseColor.a = detailColor.a; + } + if ( combine_mode == TCOMBINE_MULTIPLY ) + { + baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor); + } + + if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA ) + { + baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor ); + } + if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP ) + { + baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 ); + } + return baseColor; +} + +float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x) +{ + return f1+(f2-f1)*(x-i1)/(i2-i1); +} + +float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode, + float fBlendFactor ) +{ + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM ) + lit_baseColor += fBlendFactor * detailColor.rgb; + if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE ) + { + // fade in an unusual way - instead of fading out color, remap an increasing band of it from + // 0..1 + //if (fBlendFactor > 0.5) + // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) ); + //else + // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5); + + float f = fBlendFactor - 0.5; + float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor; + float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult; + lit_baseColor += saturate(fMult * detailColor.rgb + fAdd); + } + return lit_baseColor; +} + +//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader +float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants ) +{ +# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b + { + float flFeatheredAlpha; + float2 flDepths; +#define flSceneDepth flDepths.x +#define flSpriteDepth flDepths.y + +# if ( defined( _X360 ) ) + { + //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors + asm { + tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point + }; + +# if( !defined( REVERSE_DEPTH_ON_X360 ) ) + flSceneDepth = 1.0f - flSceneDepth; +# endif + + //get the sprite depth into the same range as the texture depth + flSpriteDepth = fProjZ / fProjW; + + //unproject to get at the pre-projection z. This value is much more linear than depth + flDepths = vDepthBlendConstants.z / flDepths; + flDepths = vDepthBlendConstants.y - flDepths; + + flFeatheredAlpha = flSceneDepth - flSpriteDepth; + flFeatheredAlpha *= vDepthBlendConstants.x; + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# else + { + flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer + flSpriteDepth = SoftParticleDepth( fProjZ ); + + flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x; + flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering. + flFeatheredAlpha = saturate( flFeatheredAlpha ); + } +# endif + +#undef flSceneDepth +#undef flSpriteDepth + + return flFeatheredAlpha; + } +# else + { + return 1.0f; + } +# endif +} + +#endif //#ifndef COMMON_PS_FXC_H_ |