diff --git a/mp/src/materialsystem/stdshaders/BlurFilterX.cpp b/mp/src/materialsystem/stdshaders/BlurFilterX.cpp new file mode 100644 index 00000000..f462423a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilterX.cpp @@ -0,0 +1,122 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "BlurFilter_vs20.inc" +#include "BlurFilter_ps20.inc" +#include "BlurFilter_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( BlurFilterX, "Help for BlurFilterX", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "BlurFilterX_DX80"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Render targets are pegged as sRGB on POSIX, so just force these reads and writes + bool bForceSRGBReadAndWrite = IsOSX() && g_pHardwareConfig->CanDoSRGBReadFromRTs(); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bForceSRGBReadAndWrite ); + pShaderShadow->EnableSRGBWrite( bForceSRGBReadAndWrite ); + + // Pre-cache shaders + blurfilter_vs20_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "BlurFilter_vs20", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20b ); +#ifndef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( APPROX_SRGB_ADAPTER, bForceSRGBReadAndWrite ); +#endif + SET_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + float v[4]; + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + int width = src_texture->GetActualWidth(); + float dX = 1.0f / width; + + // Tap offsets + v[0] = 1.3366f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = 3.4295f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = 5.4264f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + + v[0] = 7.4359f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + v[0] = 9.4436f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 1, v, 1 ); + v[0] = 11.4401f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 2, v, 1 ); + v[0] = v[1] = v[2] = v[3] = 1.0; + pShaderAPI->SetPixelShaderConstant( 3, v, 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/BlurFilterX_dx80.cpp b/mp/src/materialsystem/stdshaders/BlurFilterX_dx80.cpp new file mode 100644 index 00000000..6eecfef2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilterX_dx80.cpp @@ -0,0 +1,86 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( BlurFilterX, BlurFilterX_DX80 ) + +BEGIN_VS_SHADER_FLAGS( BlurFilterX_DX80, "Help for BlurFilterX_DX80", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + { + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Pre-cache shaders + pShaderShadow->SetVertexShader( "BlurFilter_vs11", 0 ); + pShaderShadow->SetPixelShader( "BlurFilter_ps11", 0 ); + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER3, BASETEXTURE, -1 ); + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture=params[BASETEXTURE]->GetTextureValue(); + int width = src_texture->GetActualWidth(); + float dX = 2.0f / width; + + // 4 Tap offsets, expected from pixel center + float v[4][4]; + v[0][0] = -1.5f * dX; + v[0][1] = 0; + v[1][0] = -0.5f * dX; + v[1][1] = 0; + v[2][0] = 0.5f * dX; + v[2][1] = 0; + v[3][0] = 1.5f * dX; + v[3][1] = 0; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &v[0][0], 4 ); + + v[0][0] = v[0][1] = v[0][2] = v[0][3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 1, v[0], 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/BlurFilterY.cpp b/mp/src/materialsystem/stdshaders/BlurFilterY.cpp new file mode 100644 index 00000000..57db29c0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilterY.cpp @@ -0,0 +1,136 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "BlurFilter_vs20.inc" +#include "BlurFilter_ps20.inc" +#include "BlurFilter_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( BlurFilterY, "Help for BlurFilterY", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( FRAMETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( !( params[BLOOMAMOUNT]->IsDefined() ) ) + { + params[BLOOMAMOUNT]->SetFloatValue( 1.0 ); + } + } + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "BlurFilterY_DX80"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Render targets are pegged as sRGB on POSIX, so just force these reads and writes + bool bForceSRGBReadAndWrite = IsOSX() && g_pHardwareConfig->CanDoSRGBReadFromRTs(); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bForceSRGBReadAndWrite ); + pShaderShadow->EnableSRGBWrite( bForceSRGBReadAndWrite ); + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + SET_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20b ); +#ifndef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( APPROX_SRGB_ADAPTER, bForceSRGBReadAndWrite ); +#endif + SET_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + int height = src_texture->GetActualWidth(); + float dY = 1.0f / height; +// dY *= 0.4; + float v[4]; + + // Tap offsets + v[0] = 0.0f; + v[1] = 1.3366f * dY; + v[2] = 0; + v[3] = 0; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = 0.0f; + v[1] = 3.4295f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = 0.0f; + v[1] = 5.4264f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + + v[0] = 0.0f; + v[1] = 7.4359f * dY; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + v[0] = 0.0f; + v[1] = 9.4436f * dY; + pShaderAPI->SetPixelShaderConstant( 1, v, 1 ); + v[0] = 0.0f; + v[1] = 11.4401f * dY; + pShaderAPI->SetPixelShaderConstant( 2, v, 1 ); + + v[0]=v[1]=v[2]=params[BLOOMAMOUNT]->GetFloatValue(); + + pShaderAPI->SetPixelShaderConstant( 3, v, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/BlurFilterY_dx80.cpp b/mp/src/materialsystem/stdshaders/BlurFilterY_dx80.cpp new file mode 100644 index 00000000..5e01d608 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilterY_dx80.cpp @@ -0,0 +1,91 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( BlurFilterY, BlurFilterY_DX80 ) + +BEGIN_VS_SHADER_FLAGS( BlurFilterY_DX80, "Help for BlurFilterY_DX80", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( FRAMETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if ( !( params[BLOOMAMOUNT]->IsDefined() ) ) + params[BLOOMAMOUNT]->SetFloatValue(1.0); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + { + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Pre-cache shaders + pShaderShadow->SetVertexShader( "BlurFilter_vs11", 0 ); + pShaderShadow->SetPixelShader( "BlurFilter_ps11", 0 ); + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER3, BASETEXTURE, -1 ); + + int width, height; + pShaderAPI->GetBackBufferDimensions( width, height ); + + // The temp buffer is 1/4 back buffer size + float dY = 2.0f / height; + + // 4 Tap offsets, expected from pixel center + float v[4][4]; + v[0][0] = 0; + v[0][1] = -1.5f * dY; + v[1][0] = 0; + v[1][1] = -0.5f * dY; + v[2][0] = 0; + v[2][1] = 0.5f * dY; + v[3][0] = 0; + v[3][1] = 1.5f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &v[0][0], 4 ); + + v[0][0] = v[0][1] = v[0][2] = params[BLOOMAMOUNT]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, v[0], 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/BlurFilter_ps11.psh b/mp/src/materialsystem/stdshaders/BlurFilter_ps11.psh new file mode 100644 index 00000000..6bc9bc57 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilter_ps11.psh @@ -0,0 +1,18 @@ +ps.1.1 + +// 1221 filter constants +def c0, 0.1667f, 0.1667f, 0.1667f, 0.3333f + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0.rgb, t0, c0 +mad r0.rgb, t1, c0.a, r0 +mad r0.rgb, t2, c0.a, r0 +mad r0.rgb, t3, c0, r0 + +mul r0.rgb, r0, c1 + +mov r0.a, t0.a + diff --git a/mp/src/materialsystem/stdshaders/BlurFilter_ps2x.fxc b/mp/src/materialsystem/stdshaders/BlurFilter_ps2x.fxc new file mode 100644 index 00000000..bfd082b3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilter_ps2x.fxc @@ -0,0 +1,91 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "APPROX_SRGB_ADAPTER" "0..1" [ps20b] [PC] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; + float2 coordTap1Neg : TEXCOORD4; + float2 coordTap2Neg : TEXCOORD5; + float2 coordTap3Neg : TEXCOORD6; +}; + +float2 psTapOffs[3] : register( c0 ); +float3 scale_factor : register( c3 ); + +float4 SampleTexture( sampler texSampler, float2 uv ) +{ + float4 cSample = tex2D( texSampler, uv ); + + #if ( APPROX_SRGB_ADAPTER ) + { + cSample.rgb = max( cSample.rgb, float3( 0.00001f, 0.00001f, 0.00001f ) ); // rsqrt doesn't like inputs of zero + + float3 ooSQRT; // + ooSQRT.r = rsqrt( cSample.r ); // + ooSQRT.g = rsqrt( cSample.g ); // Approximate linear-to-sRGB conversion + ooSQRT.b = rsqrt( cSample.b ); // + cSample.rgb *= ooSQRT.rgb; // + } + #endif + + return cSample; +} + +float4 main( PS_INPUT i ) : COLOR +{ + float4 s0, s1, s2, s3, s4, s5, s6, color; + + // Sample taps with coordinates from VS + s0 = SampleTexture( TexSampler, i.coordTap0 ); + s1 = SampleTexture( TexSampler, i.coordTap1 ); + s2 = SampleTexture( TexSampler, i.coordTap2 ); + s3 = SampleTexture( TexSampler, i.coordTap3 ); + s4 = SampleTexture( TexSampler, i.coordTap1Neg ); + s5 = SampleTexture( TexSampler, i.coordTap2Neg ); + s6 = SampleTexture( TexSampler, i.coordTap3Neg ); + + color = s0 * 0.2013f; + color += ( s1 + s4 ) * 0.2185f; + color += ( s2 + s5 ) * 0.0821f; + color += ( s3 + s6 ) * 0.0461f; + + // Compute tex coords for other taps + float2 coordTap4 = i.coordTap0 + psTapOffs[0]; + float2 coordTap5 = i.coordTap0 + psTapOffs[1]; + float2 coordTap6 = i.coordTap0 + psTapOffs[2]; + float2 coordTap4Neg = i.coordTap0 - psTapOffs[0]; + float2 coordTap5Neg = i.coordTap0 - psTapOffs[1]; + float2 coordTap6Neg = i.coordTap0 - psTapOffs[2]; + + // Sample the taps + s1 = SampleTexture( TexSampler, coordTap4 ); + s2 = SampleTexture( TexSampler, coordTap5 ); + s3 = SampleTexture( TexSampler, coordTap6 ); + s4 = SampleTexture( TexSampler, coordTap4Neg ); + s5 = SampleTexture( TexSampler, coordTap5Neg ); + s6 = SampleTexture( TexSampler, coordTap6Neg ); + + color += ( s1 + s4 ) * 0.0262f; + color += ( s2 + s5 ) * 0.0162f; + color += ( s3 + s6 ) * 0.0102f; + color.xyz*=scale_factor.xyz; + + #if ( APPROX_SRGB_ADAPTER ) + { + color.xyz *= color.xyz; // Approximate sRGB-to-linear conversion + } + #endif + + return color; + //return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/mp/src/materialsystem/stdshaders/BlurFilter_vs11.fxc b/mp/src/materialsystem/stdshaders/BlurFilter_vs11.fxc new file mode 100644 index 00000000..0a213522 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilter_vs11.fxc @@ -0,0 +1,34 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float2 vsTapOffs[4] : register ( SHADER_SPECIFIC_CONST_0 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + + o.coordTap0 = v.vBaseTexCoord + vsTapOffs[0]; + o.coordTap1 = v.vBaseTexCoord + vsTapOffs[1]; + o.coordTap2 = v.vBaseTexCoord + vsTapOffs[2]; + o.coordTap3 = v.vBaseTexCoord + vsTapOffs[3]; + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/BlurFilter_vs20.fxc b/mp/src/materialsystem/stdshaders/BlurFilter_vs20.fxc new file mode 100644 index 00000000..3c37fa74 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/BlurFilter_vs20.fxc @@ -0,0 +1,39 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; + float2 coordTap1Neg : TEXCOORD4; + float2 coordTap2Neg : TEXCOORD5; + float2 coordTap3Neg : TEXCOORD6; +}; + +float2 vsTapOffs[3] : register ( SHADER_SPECIFIC_CONST_0 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + o.coordTap0 = v.vBaseTexCoord; + o.coordTap1 = v.vBaseTexCoord + vsTapOffs[0]; + o.coordTap2 = v.vBaseTexCoord + vsTapOffs[1]; + o.coordTap3 = v.vBaseTexCoord + vsTapOffs[2]; + o.coordTap1Neg = v.vBaseTexCoord - vsTapOffs[0]; + o.coordTap2Neg = v.vBaseTexCoord - vsTapOffs[1]; + o.coordTap3Neg = v.vBaseTexCoord - vsTapOffs[2]; + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/Cable.psh b/mp/src/materialsystem/stdshaders/Cable.psh new file mode 100644 index 00000000..a73b1130 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Cable.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; See the vertex shader for info +; +; This shader takes: +; t0 = normal map +; t1 = base texture +; v0 = directional light color +; t2 = directional light direction (biased into 0-1) +; c0 = percent of dirlight to add as ambient +; +; Output: +; (t0 dot t1) * v0 +;------------------------------------------------------------------------------ + +tex t0 ; Get the 3-vector from the normal map +tex t1 ; Interpret tcoord t1 as color data. +texcoord t2 + +dp3 r1, t0_bx2, t2_bx2 ; r1 = normalMap dot dirLightDir +add r0, r1, c0 ; + 0.5 + +mul r1, v0, r0 ; scale the dot product by the dirlight's actual color +mul r0.rgb, r1, t1 + ; scale by the texture color + +mul r0.a, t1.a, v0.a diff --git a/mp/src/materialsystem/stdshaders/Cable.vsh b/mp/src/materialsystem/stdshaders/Cable.vsh new file mode 100644 index 00000000..857a2e3b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Cable.vsh @@ -0,0 +1,117 @@ +vs.1.1 + +#include "macros.vsh" + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; The cable equation is: +; [L dot N] * C * T +; +; where: +; C = directional light color +; T = baseTexture +; N = particle normal (stored in the normal map) +; L = directional light direction +; +; $SHADER_SPECIFIC_CONST_0 = Directional light direction +;------------------------------------------------------------------------------ + + +;------------------------------------------------------------------------------ +; Transform position from object to projection space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Setup the tangent space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$tmp1 ); +&AllocateRegister( \$tmp2 ); +&AllocateRegister( \$tmp3 ); +&AllocateRegister( \$r ); + +; Get S crossed with T (call it R) +mov $tmp1, $vTangentS +mov $tmp2, $vTangentT + +mul $tmp3, $vTangentS.yzxw, $tmp2.zxyw +mad $r, -$vTangentS.zxyw, $tmp2.yzxw, $tmp3 + +&FreeRegister( \$tmp2 ); +&FreeRegister( \$tmp3 ); + +&AllocateRegister( \$s ); + +; Normalize S (into $s) +dp3 $s.w, $vTangentS, $vTangentS +rsq $s.w, $s.w +mul $s.xyz, $vTangentS, $s.w + +; Normalize R (into $r) +dp3 $r.w, $r, $r +rsq $r.w, $r.w +mul $r.xyz, $r, $r.w + +&AllocateRegister( \$t ); + +; Regenerate T (into $t) +mul $t, $r.yzxw, $tmp1.zxyw +mad $t, -$r.zxyw, $tmp1.yzxw, $t + +&FreeRegister( \$tmp1 ); + +;------------------------------------------------------------------------------ +; Transform the light direction (into oD1) +;------------------------------------------------------------------------------ + +&AllocateRegister( \$lightDirection ); + +dp3 $lightDirection.x, $s, $SHADER_SPECIFIC_CONST_0 +dp3 $lightDirection.y, $t, $SHADER_SPECIFIC_CONST_0 +dp3 $lightDirection.z, $r, $SHADER_SPECIFIC_CONST_0 + +&FreeRegister( \$r ); +&FreeRegister( \$s ); +&FreeRegister( \$t ); + +; Scale into 0-1 range (we're assuming light direction was normalized prior to here) +add oT2, $lightDirection, $cHalf ; + 0.5 +&FreeRegister( \$lightDirection ); + +;------------------------------------------------------------------------------ +; Copy texcoords for the normal map and base texture +;------------------------------------------------------------------------------ + +mov oT0, $vTexCoord0 +mov oT1, $vTexCoord1 + +; Pass the dirlight color through +mov oD0.xyzw, $vColor + + diff --git a/mp/src/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc b/mp/src/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc new file mode 100644 index 00000000..c90ef086 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc @@ -0,0 +1,23 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 projPos : POSITION; + float3 zValue : TEXCOORD0; +}; + +const float3 g_ZFilter : register( c1 ); +const float3 g_ModulationColor : register( c2 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float z = dot( i.zValue, g_ZFilter ); + z = saturate( z ); + float4 color = float4( z, z, z, 1.0f ); + color.rgb *= g_ModulationColor; + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/mp/src/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc b/mp/src/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc new file mode 100644 index 00000000..647acde0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc @@ -0,0 +1,38 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +const float2 cDepthFactor : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 zValue : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.zValue.x = (o.projPos.z - cDepthFactor.y) / cDepthFactor.x; + o.zValue.y = (o.projPos.w - cDepthFactor.y) / cDepthFactor.x; + return o; +} + + + + diff --git a/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp b/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp new file mode 100644 index 00000000..9f3c34bf --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp @@ -0,0 +1,94 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "debugdrawenvmapmask_vs20.inc" +#include "debugdrawenvmapmask_ps20.inc" +#include "debugdrawenvmapmask_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( DebugDrawEnvmapMask, "Help for DebugDrawEnvmapMask", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHOWALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { +// Assert( 0 ); + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + SET_STATIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + SET_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + SET_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + } + } + DYNAMIC_STATE + { + int numBones = s_pShaderAPI->GetCurrentNumBones(); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + + bool bShowAlpha = params[SHOWALPHA]->GetIntValue() ? true : false; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( SHOWALPHA, bShowAlpha ); + SET_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( SHOWALPHA, bShowAlpha ); + SET_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + } + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc b/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc new file mode 100644 index 00000000..f97589af --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc @@ -0,0 +1,26 @@ +// DYNAMIC: "SHOWALPHA" "0..1" + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); +#if SHOWALPHA + float4 result = float4( baseColor.a, baseColor.a, baseColor.a, 1.0f ); +#else + float4 result = float4( baseColor.rgb, 1.0f ); +#endif + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc b/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc new file mode 100644 index 00000000..33aa5dac --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc @@ -0,0 +1,39 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + return o; +} + + + + diff --git a/mp/src/materialsystem/stdshaders/DebugTextureView.cpp b/mp/src/materialsystem/stdshaders/DebugTextureView.cpp new file mode 100644 index 00000000..70d73d34 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugTextureView.cpp @@ -0,0 +1,104 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "shaderlib/cshader.h" + +#include "debugtextureview_vs20.inc" +#include "debugtextureview_ps20.inc" +#include "debugtextureview_ps20b.inc" + +DEFINE_FALLBACK_SHADER( DebugTextureView, DebugTextureView_dx9 ) +BEGIN_VS_SHADER( DebugTextureView_dx9, "Help for DebugTextureView" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHOWALPHA, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "UnlitGeneric"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaTest( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugtextureview_vs20 ); + SET_STATIC_VERTEX_SHADER( debugtextureview_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugtextureview_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SHOWALPHA, params[SHOWALPHA]->GetIntValue() != 0 ); + SET_STATIC_PIXEL_SHADER( debugtextureview_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugtextureview_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SHOWALPHA, params[SHOWALPHA]->GetIntValue() != 0 ); + SET_STATIC_PIXEL_SHADER( debugtextureview_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + //pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + + float cPsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + if ( ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA16161616F ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA16161616 ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGB323232F ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA32323232F ) ) + { + if ( pTexture->IsCubeMap() ) + cPsConst0[0] = 1.0f; + else + cPsConst0[1] = 1.0f; + } + pShaderAPI->SetPixelShaderConstant( 0, cPsConst0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugtextureview_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugtextureview_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ISCUBEMAP, pTexture->IsCubeMap() ); + SET_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ISCUBEMAP, pTexture->IsCubeMap() ); + SET_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/DebugTextureView_ps2x.fxc b/mp/src/materialsystem/stdshaders/DebugTextureView_ps2x.fxc new file mode 100644 index 00000000..4b22d55b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugTextureView_ps2x.fxc @@ -0,0 +1,81 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "SHOWALPHA" "0..1" +// DYNAMIC: "ISCUBEMAP" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler g_tSampler : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +const float3 g_vConst0 : register( c0 ); +#define g_flIsHdrCube g_vConst0.x +#define g_flIsHdr2D g_vConst0.y + +float4 main( PS_INPUT i ) : COLOR +{ + float4 sample = tex2D( g_tSampler, i.texCoord ); + float4 result = { 0.0f, 0.0f, 0.0f, 1.0f }; + + result.rgb = sample.rgb; + #if SHOWALPHA + result.rgb = sample.a; + #endif + + if ( g_flIsHdr2D ) + result.rgb *= MAX_HDR_OVERBRIGHT; + + #if ISCUBEMAP + bool bNoDataForThisPixel = false; + float3 vec = float3( 0, 0, 0 ); + float x = i.texCoord.x; + float y = i.texCoord.y; + float x2 = frac( ( i.texCoord.x ) * 3.0f ) * 2.0f - 1.0f; + float y2 = frac( ( i.texCoord.y ) * 4.0f ) * 2.0f - 1.0f; + if ( ( x >= 0.3333f ) && ( x <= 0.6666f ) ) //Center row + { + if ( y >= 0.75f ) + vec = float3( x2, 1.0, y2 ); + else if ( y >= 0.5f ) + vec = float3( x2, y2, -1.0 ); + else if ( y >= 0.25f ) + vec = float3( x2, -1.0, -y2 ); + else if ( y >= 0.0f ) + vec = float3( x2, -y2, 1.0 ); + } + else if ( ( y >= 0.25f ) && ( y <= 0.5f ) ) + { + if ( x <= 0.3333f ) + vec = float3( -1.0f, -x2, -y2 ); + else if (x >= 0.6666f) + vec = float3( 1.0f, x2, -y2 ); + else + bNoDataForThisPixel = true; + } + else + { + bNoDataForThisPixel = true; + } + + float4 cBase = texCUBE( g_tSampler, vec ); + #if SHOWALPHA + cBase.rgb = cBase.a; + #endif + + if ( g_flIsHdrCube ) + cBase.rgb *= ENV_MAP_SCALE; + + if ( bNoDataForThisPixel == true ) + cBase.rgb = float3( 0.9f, 0.4f, 0.15f ); + + result.rgb = cBase.rgb; + result.a = 1.0f; // - bNoDataForThisPixel; + #endif + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/mp/src/materialsystem/stdshaders/DebugTextureView_vs20.fxc b/mp/src/materialsystem/stdshaders/DebugTextureView_vs20.fxc new file mode 100644 index 00000000..48c3b7e4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/DebugTextureView_vs20.fxc @@ -0,0 +1,23 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vUv0 : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + o.vProjPos.xyzw = mul( i.vPos.xyzw, cModelViewProj ); + o.vUv0.xy = i.vTexCoord0.xy; + return o; +} diff --git a/mp/src/materialsystem/stdshaders/Eyes.psh b/mp/src/materialsystem/stdshaders/Eyes.psh new file mode 100644 index 00000000..6e5e5646 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Eyes.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw the eyes +; t0 - texture +; t1 - iris +; t2 - glint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +lrp r0, t1.a, t1, t0 ; Blend in the iris with the background +mad r0.rgb, r0, v0, t2 + ; Modulate by the illumination, add in the glint +mov r0.a, t0.a diff --git a/mp/src/materialsystem/stdshaders/Eyes_Overbright2.psh b/mp/src/materialsystem/stdshaders/Eyes_Overbright2.psh new file mode 100644 index 00000000..11119233 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Eyes_Overbright2.psh @@ -0,0 +1,18 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw the eyes +; t0 - texture +; t1 - iris +; t2 - glint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +lrp r0, t1.a, t1, t0 ; Blend in the iris with the background +mul_x2 r0, v0, r0 ; Modulate by the illumination with overbright + +add r0.rgb, r0, t2 + ; Add in the glint +mov r0.a, t0.a diff --git a/mp/src/materialsystem/stdshaders/Eyes_vs20.fxc b/mp/src/materialsystem/stdshaders/Eyes_vs20.fxc new file mode 100644 index 00000000..b055eed7 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Eyes_vs20.fxc @@ -0,0 +1,145 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== +// $SHADER_SPECIFIC_CONST_0 = eyeball origin +// $SHADER_SPECIFIC_CONST_1 = eyeball up * 0.5 +// $SHADER_SPECIFIC_CONST_2 = iris projection U +// $SHADER_SPECIFIC_CONST_3 = iris projection V +// $SHADER_SPECIFIC_CONST_4 = glint projection U +// $SHADER_SPECIFIC_CONST_5 = glint projection V +//============================================================================= + +// STATIC: "INTRO" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "vortwarp_vs20_helper.h" + +static const int g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 cEyeOrigin : register( SHADER_SPECIFIC_CONST_0 ); +const float3 cHalfEyeballUp : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cIrisProjectionU : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cIrisProjectionV : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cGlintProjectionU : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cGlintProjectionV : register( SHADER_SPECIFIC_CONST_5 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_6 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_7 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_8 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + float3 vPosFlex : POSITION1; // Delta positions for flexing +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; // Fixed-function fog factor +#endif + float2 baseTC : TEXCOORD0; // Base texture coordinate + float2 irisTC : TEXCOORD1; // Iris texture coordinates + float2 glintTC : TEXCOORD2; // Glint texture coordinates + float3 vColor : TEXCOORD3; // Vertex-lit color + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float4 vPosition = v.vPos; + float3 dummy = v.vPos.xyz; // dummy values that can't be optimized out + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, dummy, vPosition.xyz ); +#endif + + // Transform the position and dummy normal (not doing the dummy normal causes invariance issues with the flashlight!) + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, dummy, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + +#if INTRO + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, dummy, dummy, dummy ); +#endif + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, vProjPos, g_FogType ); +#endif + + // Normal = (Pos - Eye origin) - just step on dummy normal created above + worldNormal = worldPos - cEyeOrigin; + + // Normal -= 0.5f * (Normal dot Eye Up) * Eye Up + float normalDotUp = -dot( worldNormal, cHalfEyeballUp) * 0.5f; + worldNormal = normalize(normalDotUp * cHalfEyeballUp + worldNormal); + + // Vertex lighting +#if ( USE_STATIC_CONTROL_FLOW || defined ( SHADER_MODEL_VS_3_0 ) ) + o.vColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert ); +#else + o.vColor = DoLightingUnrolled( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); +#endif + + // Texture 0 is the base texture + // Texture 1 is a planar projection used for the iris + // Texture 2 is a planar projection used for the glint + o.baseTC = v.vTexCoord0; + o.irisTC.x = dot( cIrisProjectionU, float4(worldPos, 1) ); + o.irisTC.y = dot( cIrisProjectionV, float4(worldPos, 1) ); + o.glintTC.x = dot( cGlintProjectionU, float4(worldPos, 1) ); + o.glintTC.y = dot( cGlintProjectionV, float4(worldPos, 1) ); + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric.psh new file mode 100644 index 00000000..a6794e7e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddBaseAlphaMaskedEnvMap.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddBaseAlphaMaskedEnvMap.psh new file mode 100644 index 00000000..7b042e7a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddBaseAlphaMaskedEnvMap.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t2 ; cube map +tex t3 ; envmap mask + +mul r0.rgb, t2, 1-t3.a +mul r0.rgb, c2, r0 ; apply the envmaptint ++ mul r0.a, c2.a, v0.a diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapMaskNoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapMaskNoTexture.psh new file mode 100644 index 00000000..ccc2c7b1 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapMaskNoTexture.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t2 ; cube map +tex t3 ; envmap mask + +mul r0.rgb, t2, t3 +mul r0.rgb, c2, r0 ++ mul r0.a, c2.a, v0.a diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapNoTexture.psh new file mode 100644 index 00000000..fd4fd7a5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapNoTexture.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t2 ; cube map + +mul r0.rgb, t2, c2 ++ mul r0.a, v0.a, c2.a diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseAlphaMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseAlphaMaskedEnvMapV2.psh new file mode 100644 index 00000000..236db8e3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseAlphaMaskedEnvMapV2.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul r1, t2, 1-t3.a ; envmap * envmapmask (alpha) +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.psh new file mode 100644 index 00000000..75aab35b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.psh @@ -0,0 +1,14 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +mul r0, t0, c0 + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.vsh new file mode 100644 index 00000000..6cef1e5d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.vsh @@ -0,0 +1,38 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTextureBlend.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTextureBlend.vsh new file mode 100644 index 00000000..8eea421f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTextureBlend.vsh @@ -0,0 +1,43 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +mov oT2, $vTexCoord1 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.psh new file mode 100644 index 00000000..ba349187 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.psh @@ -0,0 +1,66 @@ +; STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +ps.1.1 + +;------------------------------------------------------------------------------ +; Environment mapping on a bumped surface +; t0 - Normalmap +; t3 - Cube environment map (*must* be a cube map!) +; +; c0 - color to multiply the results by +; c1 - envmap contrast +; c2 - envmap saturation +; c3 - grey weights +; c4 - fresnel amount +; Input texture coords required here are a little wonky. +; tc0.uv <- U,V into the normal map +; tc1.uvw, tc2.uvw, tc3.uvw <- 3x3 matrix transform +; from tangent space->env map space +; tc1.q, tc2.q, tc3.q <- eye vector in env map space +;------------------------------------------------------------------------------ + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +; FIXME FIXME - Need to do specialized versions of this with and without: +; - constant color +; - fresnel amount of exactly 0 or 1 or in between +; - envmap contrast of 0, 1, or in between +; - envmap saturation of 0, 1, or in between + +; r0 = constant color * result of bump into envmap +mul r0.rgb, t3, c0 + +; dot eye-vector with per-pixel normal from t0 +dp3_sat r1, v0_bx2, t0_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r1.rgb, r0, r0 ; color squared ++mul r0.a, 1-r1.a, 1-r1.a ; squared + +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color ++mul r0.a, r0.a, r0.a ; quartic + +dp3 r1.rgb, r0, c3 ; color greyscaled ++mul r0.a, r0.a, 1-r1.a ; quintic + +; FIXME - these should be able to pair (I think), but don't on nvidia for some reason. +; (I think) cannot pair due to use of >2 constants in single stage +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale +mad r0.a, r0.a, c6.a, c4.a ; Take Fresnel R(0) into consideration + +mul r0.rgb, r0, r0.a ; multiply output color by result of fresnel calc + +#if NORMALMAPALPHAENVMAPMASK ++mul r0.a, c0.a, t0.a ; Fade amount * alpha from the texture +#else ++mov r0.a, c0.a ; Just use the fade amount +#endif + + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.vsh new file mode 100644 index 00000000..73769dce --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.vsh @@ -0,0 +1,96 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $worldEyeVect.x +mov oT2.w, $worldEyeVect.y +mov oT3.w, $worldEyeVect.z + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +&FreeRegister( \$worldEyeVect ); + +&Normalize( $tangentEyeVect ); + +; stick the tangent space eye vector into oD0 +mad oD0.xyz, $tangentEyeVect, $cHalf, $cHalf + +&FreeRegister( \$tangentEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.psh new file mode 100644 index 00000000..2a4efc7d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.psh @@ -0,0 +1,72 @@ +; STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +ps.1.4 +;------------------------------------------------------------------------------ +; Phase 1 +;------------------------------------------------------------------------------ +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! +;mov r0.rgba, r4 + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +#if NORMALMAPALPHAENVMAPMASK +; Alpha gets lost after phase marker, so store it here +mov r5, r0.a +#endif + +;------------------------------------------------------------------------------ +; Phase 2 +;------------------------------------------------------------------------------ +; What's left over from the last phase: +; r0 - normal +; r1 - free +; r2 - vector to sample in envmap +; r3 - free +; r4 - normal +; r5 - normal map alpha (rgba) + +phase + +; Sample environment map +texld r3, r2 + +; dot eye-vector with per-pixel normal from r0 +dp3_sat r1, v0_bx2, r0_bx2 + +; Result goes in output color (multiply by constant color c0) +mul r0.rgb, r3, c0 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r1.rgb, r0, r0 ++mul r0.a, 1-r1.a, 1-r1.a ; squared + +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color ++mul r0.a, r0.a, r0.a ; quartic + +dp3 r1.rgb, r0, c3 ++mul r0.a, r0.a, 1-r1.a ; quintic + +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale +mad r0.a, r0.a, c6.a, c4.a ; Take Fresnel R(0) into consideration + +mul r0.rgb, r0, r0.a ; multiply output color by result of fresnel calc + +#if NORMALMAPALPHAENVMAPMASK ++mul r0.a, c0.a, r5.r ; Fade amount * alpha from the texture +#else ++mov r0.a, c0.a ; Just use the fade amount +#endif diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.vsh new file mode 100644 index 00000000..ea0f143a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.vsh @@ -0,0 +1,92 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; eye vector +mov oT4.xyz, $worldEyeVect + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +&FreeRegister( \$worldEyeVect ); + +&Normalize( $tangentEyeVect ); + +; stick the tangent space eye vector into oD0 +mad oD0.xyz, $tangentEyeVect, $cHalf, $cHalf + +&FreeRegister( \$tangentEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.psh new file mode 100644 index 00000000..9e55248e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.psh @@ -0,0 +1,79 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - Axes of the lightmap coordinate system in tangent space +;------------------------------------------------------------------------------ + +; Get the 3-vector from the normal map +tex t0 + +; Sample the lightmaps +tex t1 +tex t2 +tex t3 + +; output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + +; r0 = ( N dot basis[0] ) +; don't "_sat" here so that everything adds up to one even if the normal is outside of the basis!!!!! +dp3 r0, t0_bx2, c0 + +; r1 = ( N dot basis[1] ) +dp3 r1, t0_bx2, c1 + +;---- +; r0 = ( N dot basis[0] ) +; r1 = ( N dot basis[1] ) +;---- + +; r0.rgb = ( N dot basis[0] )^2 +mul r0.rgb, r0, r0 + +; r1.a = ( N dot basis[1] )^2 ++mul r1.a, r1, r1 + +;---- +; r0.rgb = ( N dot basis[0] )^2 +; r1.a = ( N dot basis[1] )^2 +;---- + +mul t1, r0, t1 + +;---- +; r1.a = ( N dot basis[1] )^2 +; t1 = lightmapColor[0] * ( N dot basis[0] )^2 +;---- + +dp3 r0, t0_bx2, c2 + +;---- +; r1.a = ( N dot basis[1] )^2 +; t1 = lightmapColor[0] * ( N dot basis[0] )^2 +; r0 = ( N dot basis[2] ) +;---- + +mad t1.rgb, r1.a, t2, t1 ++mul r0.a, r0, r0 + +;---- +; t1.rgb = lightmapColor[0] * ( N dot basis[0] )^2 + lightmapColor[1] * ( N dot basis[1] )^2 +; r0.a = ( N dot basis[2] )^2 +;---- + +mad r0.rgba, r0.a, t3, t1 + +;---- +; r0.rgb = lightmapColor[0] * ( N dot basis[0] )^2 + +; lightmapColor[1] * ( N dot basis[1] )^2 + +; lightmapColor[2] * ( N dot basis[2] )^2 +;---- diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.vsh new file mode 100644 index 00000000..229a839a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.vsh @@ -0,0 +1,54 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.xy, $vTexCoord2 +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +; make a 3 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three + +&FreeRegister( \$offset ); diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.psh new file mode 100644 index 00000000..39a25964 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.psh @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; t4 - Base +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - Axes of the lightmap coordinate system in tangent space +;------------------------------------------------------------------------------ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 + +; Sample the lightmaps +texld r1, t1 +texld r2, t2 +texld r3, t3 + +; Sample the base texture +texld r4, t4 + +; output = (lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) ) * base + +dp3 r5.r, r0_bx2, c0 +dp3 r5.g, r0_bx2, c1 +dp3 r5.b, r0_bx2, c2 +mul r5.rgb, r5, r5 +mul r1, r1, r5.r +mad r1, r2, r5.g, r1 +mad r1, r3, r5.g, r1 + +; assume overbright_2 !!! +mul_x2 r0, r1, r4 diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.vsh new file mode 100644 index 00000000..a78d0851 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.vsh @@ -0,0 +1,55 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.xy, $vTexCoord2 +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three +dp4 oT4.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT4.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +&FreeRegister( \$offset ); diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.psh new file mode 100644 index 00000000..f17f14cf --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.psh @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; t4 - Base1 +; t5 - Base2 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - Axes of the lightmap coordinate system in tangent space +;------------------------------------------------------------------------------ +ps.1.4 + +; output = (lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) ) * lerp(base1, base2, lightmapColor[0].a) + +; Get the 3-vector from the normal map +texld r0, t0 + +dp3 r5.r, r0_bx2, c0 +dp3 r5.g, r0_bx2, c1 +dp3 r5.b, r0_bx2, c2 +mul r5.rgb, r5, r5 + +phase + +; Sample the lightmaps +texld r1, t1 +texld r2, t2 +texld r3, t3 + +; Sample the base textures +texld r4, t4 +texld r5, t5 + +mul r1, r1, r5.r +mad r1, r2, r5.g, r1 +mad r1, r3, r5.g, r1 + +; blend base textures +lrp r4, r4, r5, r1.a + +; assume overbright_2 !!! +mul_x2 r0, r1, r4 diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.vsh new file mode 100644 index 00000000..7773d335 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.vsh @@ -0,0 +1,57 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.xy, $vTexCoord2 +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three +dp4 oT4.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT4.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 +dp4 oT5.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT5.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +&FreeRegister( \$offset ); diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.psh new file mode 100644 index 00000000..86e627e5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.psh @@ -0,0 +1,47 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - decal texture +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - ( ( N dot basis[0] )^2 ), ( ( N dot basis[1] )^2 ), ( ( N dot basis[2] )^2 ) +;------------------------------------------------------------------------------ + +; Get the decal color +tex t0 + +; Sample the lightmaps +tex t1 +tex t2 +tex t3 + +; output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + +; r0 = lightmapColor[0] * ( ( N dot basis[0] )^2 ) +mul r0, t1, c0 + +; r0 = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + lightmapColor[1] * ( ( N dot basis[1] )^2 ) +mad r0, t2, c1, r0 + +; r0 = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) +mad r0, t3, c2, r0 + +; Modulate by decal texture +mul r0.rgb, r0, t0 ++ mov r0.a, t0.a + +; Modulate by constant color +mul r0, r0, c3 + +; Modulate by per-vertex factor +mul r0, r0, v0 + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.vsh new file mode 100644 index 00000000..a9db9faa --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.vsh @@ -0,0 +1,56 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.x, $vTexCoord2.x +mov $offset.y, $cZero +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +; make a 3 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three +mov oD0, $vColor + +&FreeRegister( \$offset ); diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_Detail.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_Detail.psh new file mode 100644 index 00000000..89b6c322 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_Detail.psh @@ -0,0 +1,18 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r1.rgb, r0, t2 ; detail texture +lrp r0.rgb, c2, r1, r0 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_DetailNoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_DetailNoTexture.psh new file mode 100644 index 00000000..a9129757 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_DetailNoTexture.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t1 +tex t2 +mul r0.rgb, t1, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a +mul_x2 r0.rgb, r0, t2 ; detail texture +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_DetailSelfIlluminated.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_DetailSelfIlluminated.psh new file mode 100644 index 00000000..a9e05150 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_DetailSelfIlluminated.psh @@ -0,0 +1,23 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r1.rgb, r0, t2 ; detail texture +lrp r0.rgb, c2, r1, r0 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, c1, t0 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lightmap diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapNoTexture.psh new file mode 100644 index 00000000..919da94c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapNoTexture.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t1 +tex t2 + +mov r0.rgb, v0 + ; vertex color +mul r0.a, v0.a, t2.a ; vertex alpha * envmap alpha + +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapV2.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapV2.psh new file mode 100644 index 00000000..f0205e86 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapV2.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly.vsh new file mode 100644 index 00000000..5f740f86 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly.vsh @@ -0,0 +1,45 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +; $SHADER_SPECIFIC_CONST_4 = Modulation color +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +; YUCK! This is to make texcoords continuous for mat_softwaretl +mov oT0, $cZero +; Texture coordinates +mov oT1, $vTexCoord1 + +mov oD0, $cOne + + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly_Overbright2.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly_Overbright2.psh new file mode 100644 index 00000000..30bd9f76 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly_Overbright2.psh @@ -0,0 +1,6 @@ +ps.1.1 + +tex t1 + +mov r0.rgba, t1 + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapNoTexture.psh new file mode 100644 index 00000000..ee59d663 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapNoTexture.psh @@ -0,0 +1,24 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t1 +tex t2 +tex t3 + +mov r0.rgb, v0 ; vertex color +mul r1, t2, t3 ; envmap * envmapmask + +mad r0.rgb, r1, c2, r0 + ; + envmap * envmapmask * envmaptint (color only) +mul r0.a, v0.a, r1.a ; alpha = vertex alpha * envmap alpha * envmapmask alpha + +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapV2.psh new file mode 100644 index 00000000..398ed46a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapV2.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLighting.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLighting.psh new file mode 100644 index 00000000..7944e730 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLighting.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c2, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mul_sat r1.a, t0, v0 ; base times vertex alpha +lrp r0, r1.a, r1, c2 ; interpolate between white + color diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingNoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingNoTexture.psh new file mode 100644 index 00000000..e0fb27b7 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingNoTexture.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c2, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mov_sat r1.a, v0 ; vertex alpha +lrp r0, r1.a, r1, c2 ; interpolate between white + color diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingSelfIllum.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingSelfIllum.psh new file mode 100644 index 00000000..1282ecac --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingSelfIllum.psh @@ -0,0 +1,23 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c2, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 + +; Blend between white and lightmap color based on total alpha +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mov_sat r1.a, v0 ; opacity == vertex opacity (no alpha in texture) + +lrp r0.rgb, t0.a, c1, r1 ; Blend between self-illum + lightmap ++ mov r0.a, c2.a + +lrp r0.rgb, r1.a, r0, c2 ; interpolate between white + color diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_NoTexture.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_NoTexture.psh new file mode 100644 index 00000000..f02de34b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_NoTexture.psh @@ -0,0 +1,14 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t1 +mul r0.rgb, t1, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_SSBumpmappedLightmap.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SSBumpmappedLightmap.psh new file mode 100644 index 00000000..bdcb7783 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SSBumpmappedLightmap.psh @@ -0,0 +1,34 @@ +ps.1.1 +def c0, 1,0,0,0 +def c1, 0,1,0,0 +def c2, 0,0,1,0 + +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +;------------------------------------------------------------------------------ + +; Get the 3-vector from the normal map +tex t0 + +; Sample the lightmaps +tex t1 +tex t2 +tex t3 + +; output = lightmapColor[0] * n.r + lightmapColor[1] * n.g + lightmapColor[2] * n.b + + +mov r0, t0 +dp3 r1, t0, c0 +mul r0.rgb, r1, t1 +dp3 r1, t0, c1 +mad r0.rgb, r1, t2, r0 +dp3 r1, t0, c2 +mad r0.rgb, r1, t3, r0 diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminated.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminated.psh new file mode 100644 index 00000000..cf800a2e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminated.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 + +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, c1, t0 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lightmap diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedEnvMapV2.psh new file mode 100644 index 00000000..9fd0a1c5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedEnvMapV2.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r1, t0.a, t0 ; Self illum +mad r1, c1, r1, t1 ; Self illum * tint + lightmap + +mul r0.rgb, r1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2.psh new file mode 100644 index 00000000..1e62a416 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2.psh @@ -0,0 +1,28 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0.rgb, t0, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r1, c1, t0.a ; Self illum alpha * tint +mad r1, t0, r1, t1 ; Self illum * tint + lightmap +mul r0.rgb, r1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) + diff --git a/mp/src/materialsystem/stdshaders/LightmappedGeneric_VertexColor.vsh b/mp/src/materialsystem/stdshaders/LightmappedGeneric_VertexColor.vsh new file mode 100644 index 00000000..a434a941 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/LightmappedGeneric_VertexColor.vsh @@ -0,0 +1,15 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "LightmappedGeneric_inc.vsh" + +$detail = 0; +$envmap = 0; +$envmapcameraspace = 0; +$envmapsphere = 0; +$vertexcolor = 1; + +&LightmappedGeneric( $detail, $envmap, $envmapcameraspace, $envmapsphere, + $vertexcolor ); + diff --git a/mp/src/materialsystem/stdshaders/Refract_model_vs11.vsh b/mp/src/materialsystem/stdshaders/Refract_model_vs11.vsh new file mode 100644 index 00000000..a6eea2b7 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Refract_model_vs11.vsh @@ -0,0 +1,105 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $worldPos +alloc $worldNormal +alloc $worldTangentS +alloc $worldTangentT + +&SkinPositionNormalAndTangentSpace( $worldPos, $worldNormal, + $worldTangentS, $worldTangentT ); + +alloc $projPos + +; Transform position from world to projection space +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +alloc $tangentEyeVect +; transform the eye vector to tangent space +dp3 oT3.x, $worldEyeVect, $worldTangentS +dp3 oT3.y, $worldEyeVect, $worldTangentT +dp3 oT3.z, $worldEyeVect, $worldNormal + +alloc $bumpTexCoord + +dp4 $bumpTexCoord.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 $bumpTexCoord.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +; dudv map +mov oT0.xy, $bumpTexCoord + +; refract tint + alpha channel +mov oT2.xy, $bumpTexCoord +mov oT3.xy, $bumpTexCoord + +free $bumpTexCoord + +mov oPos, $projPos + +; special case perspective correct texture projection so that the texture fits exactly on the screen + +; flip Y by multiplying by -1 +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_4.w + +; transform from [-w,w] to [0,2*w] +; The reason this is w is because we are in perspective space/homogenous clip space. +add $projPos.xy, $projPos.xy, $projPos.w + +; transform from [0,2*w] to [0,w] +; We'll end up dividing by w in the pixel shader to get to [0,1] +mul $projPos.xy, $projPos.xy, $cHalf + +mov oT1.xy, $projPos.xy + +; emit w to both z and w in case the driver screws up and divides by z +mov oT1.z, $projPos.w +mov oT1.w, $projPos.w + +free $projPos +free $worldPos +free $worldEyeVect +free $tangentEyeVect +free $w +free $worldNormal +free $worldTangentS +free $worldTangentT diff --git a/mp/src/materialsystem/stdshaders/Refract_ps11.psh b/mp/src/materialsystem/stdshaders/Refract_ps11.psh new file mode 100644 index 00000000..f3fe34d2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Refract_ps11.psh @@ -0,0 +1,36 @@ +; STATIC: "REFRACTTINTTEXTURE" "0..1" +; STATIC: "NORMALMAPALPHA" "0..1" + +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: refraction render target +; texcoords: + +tex t0 ; sample dudv map +texbem t1, t0 ; refraction + +#if REFRACTTINTTEXTURE +tex t2 +#endif + +#if NORMALMAPALPHA +tex t3 +#endif + +; refracttint +#if REFRACTTINTTEXTURE +mul_x2 r0, t1, t2 +#else +mov r0, t1 +#endif + +#if NORMALMAPALPHA +mul r0.rgb, r0, c0 + +mov r0.a, t3.a +#else +mul r0.rgb, r0, c0 +#endif diff --git a/mp/src/materialsystem/stdshaders/Refract_vs20.fxc b/mp/src/materialsystem/stdshaders/Refract_vs20.fxc new file mode 100644 index 00000000..698dd192 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Refract_vs20.fxc @@ -0,0 +1,140 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "MODEL" "0..1" +// STATIC: "COLORMODULATE" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const bool g_bModel = MODEL ? true : false; + +const float4 cBumpTexCoordTransform[4] : register( SHADER_SPECIFIC_CONST_1 ); + +const float g_flTime : register( SHADER_SPECIFIC_CONST_5 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; +#if !MODEL + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +#else + float4 vUserData : TANGENT; +#endif +#if COLORMODULATE + float4 vColor : COLOR0; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; +#if !defined( _X360 ) + float vFog : FOG; +#endif + float4 vBumpTexCoord : TEXCOORD0; + float3 vTangentEyeVect : TEXCOORD1; + float3 vWorldNormal : TEXCOORD2; + float3 vWorldTangent : TEXCOORD3; + float3 vWorldBinormal : TEXCOORD4; + float3 vRefractXYW : TEXCOORD5; + float3 vWorldViewVector : TEXCOORD6; +#if COLORMODULATE + float4 vColor : COLOR0; +#endif + float4 fogFactorW : COLOR1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + +#if COLORMODULATE + o.vColor = v.vColor; +#endif + + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + + float3 vObjNormal; +#if MODEL + float4 vObjTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vObjNormal, vObjTangent ); + + SkinPositionNormalAndTangentSpace( + g_bSkinning, + v.vPos, vObjNormal, vObjTangent, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal, worldTangentS, worldTangentT ); +#else + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + worldPos = mul( v.vPos, cModel[0] ); + worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); +#endif + + // World normal + o.vWorldNormal.xyz = normalize( worldNormal.xyz ); + + // Projected position + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos_POSITION = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + //o.projNormal.xyz = mul( worldNormal, cViewProj ); + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Refraction transform + o.vRefractXYW = float3(vRefractPos.x, vRefractPos.y, vProjPos.w); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.fogFactorW = CalcFog( vWorldPos, vProjPos, FOGTYPE_RANGE ); +#if !defined( _X360 ) + o.vFog = o.fogFactorW; +#endif + + // Eye vector + float3 vWorldEyeVect = normalize( cEyePos - vWorldPos ); + o.vWorldViewVector.xyz = -vWorldEyeVect.xyz; + + // Transform to the tangent space + o.vTangentEyeVect.x = dot( vWorldEyeVect, worldTangentS ); + o.vTangentEyeVect.y = dot( vWorldEyeVect, worldTangentT ); + o.vTangentEyeVect.z = dot( vWorldEyeVect, worldNormal ); + + // Tranform bump coordinates + o.vBumpTexCoord.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoord.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + + // Tranform bump coordinates (note wz, not zw) + o.vBumpTexCoord.w = dot( v.vBaseTexCoord, cBumpTexCoordTransform[2] ); + o.vBumpTexCoord.z = dot( v.vBaseTexCoord, cBumpTexCoordTransform[3] ); + + + // Tangent space transform + o.vWorldNormal.xyz = normalize( worldNormal.xyz ); + o.vWorldTangent.xyz = worldTangentS.xyz; + o.vWorldBinormal.xyz = worldTangentT.xyz; + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/Refract_world_vs11.vsh b/mp/src/materialsystem/stdshaders/Refract_world_vs11.vsh new file mode 100644 index 00000000..90f0debe --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Refract_world_vs11.vsh @@ -0,0 +1,168 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $worldPos +alloc $worldNormal +alloc $worldTangentS +alloc $worldTangentT +alloc $projPos + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +dp3 $worldPos.x, $vPos, $cModel0 +dp3 $worldPos.y, $vPos, $cModel1 +dp3 $worldPos.z, $vPos, $cModel2 + +dp3 $worldNormal.x, $vNormal, $cModel0 +dp3 $worldNormal.y, $vNormal, $cModel1 +dp3 $worldNormal.z, $vNormal, $cModel2 + +dp3 $worldTangentS.x, $vTangentS, $cModel0 +dp3 $worldTangentS.y, $vTangentS, $cModel1 +dp3 $worldTangentS.z, $vTangentS, $cModel2 + +dp3 $worldTangentT.x, $vTangentT, $cModel0 +dp3 $worldTangentT.y, $vTangentT, $cModel1 +dp3 $worldTangentT.z, $vTangentT, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +alloc $tangentEyeVect +alloc $bumpTexCoord + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $worldTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $worldTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $worldNormal + +&Normalize( $tangentEyeVect ); + +; stick the tangent space eye vector into oD0 +mad oD0.xyz, $tangentEyeVect, $cHalf, $cHalf + +dp4 $bumpTexCoord.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 $bumpTexCoord.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +; dudv map +mov oT0.xy, $bumpTexCoord + +; refract tint +mov oT3.xy, $bumpTexCoord + +free $bumpTexCoord + +alloc $newProjPos +alloc $w + +mov oPos, $projPos + +; special case perspective correct texture projection so that the texture fits exactly on the screen +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_4.w +add $projPos.xy, $projPos.xy, $projPos.w +mul $projPos.xy, $projPos.xy, $cHalf + +; Do the perspective divide here. .yuck . . we aren't going to be perspective correct +rcp $w.w, $projPos.w +mul $projPos, $projPos, $w.w + +#max $projPos.x, $projPos.x, -$cOne +#min $projPos.x, $projPos.x, $cOne +#max $projPos.z, $projPos.z, $cZero +#min $projPos.z, $projPos.z, $cOne + +;------------------------------------------------------------------------------ +; Transform the tangentS from world to view space +;------------------------------------------------------------------------------ + +alloc $projTangentS + +; we only care about x and y +dp3 $projTangentS.x, $worldTangentS, $cViewProj0 +dp3 $projTangentS.y, $worldTangentS, $cViewProj1 + +; project tangentS +mul $projTangentS.xy, $projTangentS.xy, $w.w + +;max $projTangentS.xy, $projTangentS.xy, $cOne +;min $projTangentS.xy, $projTangentS.xy, -$cOne + +;------------------------------------------------------------------------------ +; Transform the tangentT from world to view space +;------------------------------------------------------------------------------ + +alloc $projTangentT +alloc $texCoord + +; we only care about x and y +dp3 $projTangentT.x, $worldTangentT, $cViewProj0 +dp3 $projTangentT.y, $worldTangentT, $cViewProj1 + +; project tangentT +mul $projTangentT.xy, $projTangentT.xy, $w.w + +;max $projTangentT.xy, $projTangentT.xy, $cOne +;min $projTangentT.xy, $projTangentT.xy, -$cOne + +;max $projPos.xy, $projPos.xy, $cOne +;min $projPos.xy, $projPos.xy, -$cOne + +mul oT1.x, $projTangentS.x, $SHADER_SPECIFIC_CONST_3.x +mul oT1.y, $projTangentT.x, $SHADER_SPECIFIC_CONST_3.x +mov oT1.z, $projPos.x ; huh? + +mul $texCoord.x, $projTangentS.y, -$SHADER_SPECIFIC_CONST_3.x +mul $texCoord.y, $projTangentT.y, -$SHADER_SPECIFIC_CONST_3.x +mov $texCoord.z, $projPos.y +mov oT2.xyz, $texCoord +mov oT3.xyz, $texCoord + +free $texCoord +free $projPos +free $worldPos +free $worldEyeVect +free $tangentEyeVect +free $w +free $projTangentS +free $projTangentT +free $newProjPos +free $worldNormal +free $worldTangentS +free $worldTangentT diff --git a/mp/src/materialsystem/stdshaders/ShadowModel.psh b/mp/src/materialsystem/stdshaders/ShadowModel.psh new file mode 100644 index 00000000..a7514020 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/ShadowModel.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c0,1.0f, 1.0f, 1.0f, 1.0f + +tex t0 ; shadow color +texkill t1 ; Clip +texkill t2 +texkill t3 ; backface cull + +; Darkening equation, compute a color = (shadow color * shadow alpha + 1- shadow alpha) +;sub r1, t0, v0.a ; r1 = shadow alpha +lrp r0.rgb, t0.a, v0, c0 + ; r0.rgb = (shadow color * shadow alpha + 1 - shadow alpha) +mov r0.a, c0.a ; r0.a = 1 + diff --git a/mp/src/materialsystem/stdshaders/ShadowModel.vsh b/mp/src/materialsystem/stdshaders/ShadowModel.vsh new file mode 100644 index 00000000..3e4b9eba --- /dev/null +++ b/mp/src/materialsystem/stdshaders/ShadowModel.vsh @@ -0,0 +1,85 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_2 = Shadow texture matrix +; $SHADER_SPECIFIC_CONST_3 = Tex origin +; $SHADER_SPECIFIC_CONST_4 = Tex Scale +; $SHADER_SPECIFIC_CONST_5 = [Shadow falloff offset, 1/Shadow distance, Shadow scale, 0 ] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending (whacks r1-r7, positions in r7, normals in r8) +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +; Transform the position from world to view space +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Transform position into texture space (from 0 to 1) +;------------------------------------------------------------------------------ +&AllocateRegister( \$texturePos ); +dp4 $texturePos.x, $worldPos, $SHADER_SPECIFIC_CONST_0 +dp4 $texturePos.y, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 $texturePos.z, $worldPos, $SHADER_SPECIFIC_CONST_2 +&FreeRegister( \$worldPos ); + +;------------------------------------------------------------------------------ +; Figure out the shadow fade amount +;------------------------------------------------------------------------------ +&AllocateRegister( \$shadowFade ); +sub $shadowFade, $texturePos.z, $SHADER_SPECIFIC_CONST_5.x +mul $shadowFade, $shadowFade, $SHADER_SPECIFIC_CONST_5.y + +;------------------------------------------------------------------------------ +; Offset it into the texture +;------------------------------------------------------------------------------ +&AllocateRegister( \$actualTextureCoord ); +mul $actualTextureCoord.xyz, $SHADER_SPECIFIC_CONST_4, $texturePos +add oT0.xyz, $actualTextureCoord, $SHADER_SPECIFIC_CONST_3 +;mov oT0.xyz, $texturePos +&FreeRegister( \$actualTextureCoord ); + +;------------------------------------------------------------------------------ +; We're doing clipping by using texkill +;------------------------------------------------------------------------------ +mov oT1.xyz, $texturePos ; also clips when shadow z < 0 ! +sub oT2.xyz, $cOne, $texturePos +sub oT2.z, $cOne, $shadowFade.z ; clips when shadow z > shadow distance +&FreeRegister( \$texturePos ); + +;------------------------------------------------------------------------------ +; We're doing backface culling by using texkill also (wow yucky) +;------------------------------------------------------------------------------ +; Transform z component of normal in texture space +; If it's negative, then don't draw the pixel +dp3 oT3, $worldNormal, -$SHADER_SPECIFIC_CONST_2 +&FreeRegister( \$worldNormal ); + +;------------------------------------------------------------------------------ +; Shadow color, falloff +;------------------------------------------------------------------------------ +mov oD0, $cModulationColor +mul oD0.w, $shadowFade.x, $SHADER_SPECIFIC_CONST_5.z +&FreeRegister( \$shadowFade ); + diff --git a/mp/src/materialsystem/stdshaders/Teeth.vsh b/mp/src/materialsystem/stdshaders/Teeth.vsh new file mode 100644 index 00000000..065f0703 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Teeth.vsh @@ -0,0 +1,97 @@ +vs.1.1 + +# STATIC: "INTRO" "0..1" +# STATIC: "HALF_LAMBERT" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "LIGHT_COMBO" "0..21" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0 = xyz = mouth forward direction vector, w = illum factor +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +$WARPPARAM = $SHADER_SPECIFIC_CONST_2; +$ENTITY_ORIGIN = $SHADER_SPECIFIC_CONST_3; + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +alloc $worldPos +alloc $worldNormal +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +;------------------------------------------------------------------------------ +; Optional intro warping +;------------------------------------------------------------------------------ +if ( $INTRO == 1 ) +{ + alloc $tmp + sub $tmp.xyz, $worldPos, $ENTITY_ORIGIN + mul $tmp.xy, $tmp, $WARPPARAM + add $worldPos.xyz, $tmp, $ENTITY_ORIGIN + free $tmp +} + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $projPos + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); + +free $projPos + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ +alloc $linearColor +&DoDynamicLightingToLinear( $worldPos, $worldNormal, $linearColor ); + +;------------------------------------------------------------------------------ +; Factor in teeth darkening factors +;------------------------------------------------------------------------------ + +alloc $tmp + +mul $linearColor.xyz, $SHADER_SPECIFIC_CONST_0.w, $linearColor ; FIXME Color darkened by illumination factor +dp3 $tmp, $worldNormal, $SHADER_SPECIFIC_CONST_0 ; Figure out mouth forward dot normal +max $tmp, $cZero, $tmp ; clamp from 0 to 1 +mul $linearColor.xyz, $tmp, $linearColor ; Darken by forward dot normal too + +;------------------------------------------------------------------------------ +; Output color (gamma correction) +;------------------------------------------------------------------------------ + +alloc $gammaColor +&LinearToGamma( $linearColor, $gammaColor ); +free $linearColor +mul oD0.xyz, $gammaColor.xyz, $cOverbrightFactor +mov oD0.w, $cOne ; make sure all components are defined + + +free $gammaColor +free $worldPos +free $worldNormal +free $tmp + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +mov oT0, $vTexCoord0 + + + diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric.psh new file mode 100644 index 00000000..53fab24d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric.psh @@ -0,0 +1,13 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color + +mul r0, t0, v0 \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_BaseAlphaMaskedEnvMap.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_BaseAlphaMaskedEnvMap.psh new file mode 100644 index 00000000..1ed9314e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_BaseAlphaMaskedEnvMap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0.rgb, t1, 1-t2.a ; can't use mad cause can't use 3 texture registers +mul r0.rgb, c2, r0 ; apply the envmaptint +mad r0.rgb, t0, v0, r0 ++ mul r0.a, t0, v0 diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_Detail.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_Detail.psh new file mode 100644 index 00000000..5fcb3f31 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_Detail.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t3 ; detail texture + +mul r0, t0, v0 +mul_x2 r0.rgb, r0, t3 \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailBaseAlphaMaskedEnvMap.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailBaseAlphaMaskedEnvMap.psh new file mode 100644 index 00000000..69693331 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailBaseAlphaMaskedEnvMap.psh @@ -0,0 +1,29 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +;mul r0.rgb, t1, 1-t2.a ; can't use mad cause can't use 3 texture registers +;mul r0.rgb, c2, r0 ; apply the envmaptint +;mad r0.rgb, t0, v0, r0 +;+ mul r0.a, t0, v0 +;mul_x2 r0.rgb, r0, t3 ; mod2x detail texture + +; version 2: applies the mod2x *before* environment map +mul r0, t0, v0 ; Base times modulation color +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture +mul r1, t1, 1-t2.a ; Have to invert the alpha for basealpha (feh!) +mul r1, c2, r1 ; apply the envmaptint +add r0.rgb, r0, r1 ; add in the envmap diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMap.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMap.psh new file mode 100644 index 00000000..dab6efbb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMap.psh @@ -0,0 +1,25 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +;mul r1, c2, t1 +;mad r0.rgb, t0, v0, r1 +;+ mul r0.a, t0, v0 +;mul_x2 r0.rgb, r0, t3 ; mod2x detail texture + +; version 2: applies the mod2x *before* environment map +mul r0, t0, v0 ; Base times modulation color +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture +mad r0.rgb, c2, t1, r0 ; add in tinted envmap diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMask.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMask.psh new file mode 100644 index 00000000..29411c9b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMask.psh @@ -0,0 +1,29 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +;mul r0.rgb, t1, t2 ; can't use mad cause can't use 3 texture registers +;mul r0.rgb, c2, r0 ; apply the envmaptint +;mad r0.rgb, t0, v0, r0 +;+ mul r0.a, t0, v0 +;mul_x2 r0.rgb, r0, t3 ; mod2x detail texture + +; version 2: applies the mod2x *before* environment map +mul r0, t0, v0 ; Base times modulation color +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture +mul r1, t1, t2 ; Envmap * envmapmask +mul r1, c2, r1 ; apply the envmaptint +add r0.rgb, r0, r1 ; add in the envmap diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMaskNoTexture.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMaskNoTexture.psh new file mode 100644 index 00000000..e8c6f3cb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMaskNoTexture.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +; version 2 doesn't make sense here! +mul r0, t1, t2 +mul r0.rgb, c2, r0 +mul r0, r0, v0 +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapNoTexture.psh new file mode 100644 index 00000000..829849b9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapNoTexture.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +; version 2 doesn't make sense here! +mul r0, v0, t1 +mul r0.rgb, r0, c2 +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailNoTexture.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailNoTexture.psh new file mode 100644 index 00000000..c79dc2ce --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_DetailNoTexture.psh @@ -0,0 +1,10 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Just use the vertex color +;------------------------------------------------------------------------------ + +tex t3 + +mul_x2 r0.rgb, v0, t3 ++ mov r0.a, v0.a \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMap.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMap.psh new file mode 100644 index 00000000..9116997f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMap.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map + +mul r1, c2, t1 +mad r0.rgb, t0, v0, r1 ++ mul r0.a, t0, v0 diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMask.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMask.psh new file mode 100644 index 00000000..f8de572c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMask.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0.rgb, t1, t2 ; can't use mad cause can't use 3 texture registers +mul r0.rgb, c2, r0 ; apply the envmaptint +mad r0.rgb, t0, v0, r0 ++ mul r0.a, t0, v0 diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMaskNoTexture.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMaskNoTexture.psh new file mode 100644 index 00000000..a9bd7e46 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMaskNoTexture.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t1, t2 +mul r0.rgb, c2, r0 +mul r0, r0, v0 diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapNoTexture.psh new file mode 100644 index 00000000..966255fd --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapNoTexture.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map + +mul r0, v0, t1 +mul r0.rgb, r0, c2 diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_LightingOnly.vsh b/mp/src/materialsystem/stdshaders/UnlitGeneric_LightingOnly.vsh new file mode 100644 index 00000000..6361c811 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_LightingOnly.vsh @@ -0,0 +1,21 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +&AllocateRegister( \$worldPos ); +&SkinPosition( $worldPos ); + +; Transform the position from world to view space +dp4 oPos.x, $worldPos, $cViewProj0 +dp4 oPos.y, $worldPos, $cViewProj1 +dp4 oPos.z, $worldPos, $cViewProj2 +dp4 oPos.w, $worldPos, $cViewProj3 + +&FreeRegister( \$worldPos ); + +mov oD0, $cOne + + diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_MaskBaseByDetailAlpha_ps11.fxc b/mp/src/materialsystem/stdshaders/UnlitGeneric_MaskBaseByDetailAlpha_ps11.fxc new file mode 100644 index 00000000..f46a7617 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_MaskBaseByDetailAlpha_ps11.fxc @@ -0,0 +1,20 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD3; +}; + +sampler BaseTextureSampler : register( s0 ); +sampler DetailTextureSampler : register( s3 ); + +float4 main( PS_INPUT i ) : COLOR +{ + // Sample frames from texture 0 + float4 base= tex2D( BaseTextureSampler, i.texCoord0 ); + float4 detail=tex2D( DetailTextureSampler, i.texCoord1 ); + + return float4(base.rgb, base.a * detail.a); +} diff --git a/mp/src/materialsystem/stdshaders/UnlitGeneric_NoTexture.psh b/mp/src/materialsystem/stdshaders/UnlitGeneric_NoTexture.psh new file mode 100644 index 00000000..feb29ba6 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/UnlitGeneric_NoTexture.psh @@ -0,0 +1,7 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Just use the vertex color +;------------------------------------------------------------------------------ + +mov r0, v0 diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric.psh new file mode 100644 index 00000000..9824a915 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric.psh @@ -0,0 +1,13 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 + +mul r0, t0, c3 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_BaseAlphaMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_BaseAlphaMaskedEnvMapV2.psh new file mode 100644 index 00000000..1844c402 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_BaseAlphaMaskedEnvMapV2.psh @@ -0,0 +1,17 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_BlendTint.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_BlendTint.psh new file mode 100644 index 00000000..f719821b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_BlendTint.psh @@ -0,0 +1,17 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 + +mul r0, c3, t0 +lrp r0.rgb, c1, c3, r0 +lrp r0.rgb, t0.a, r0, t0 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#else ++mov r0.a, c3 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail.psh new file mode 100644 index 00000000..f42d54ac --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail.psh @@ -0,0 +1,16 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +mul r0, t0, c3 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r1.rgb, r0, t3 ; detail texture +lrp r0.rgb, c1, r1, r0 + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailBaseAlphaMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailBaseAlphaMaskedEnvMapV2.psh new file mode 100644 index 00000000..09bf59ca --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailBaseAlphaMaskedEnvMapV2.psh @@ -0,0 +1,18 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailEnvMapV2.psh new file mode 100644 index 00000000..12b2295c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailEnvMapV2.psh @@ -0,0 +1,16 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t3 ; detail texture + +mul r0, t0, c3 ; base times modulation +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailMaskedEnvMapV2.psh new file mode 100644 index 00000000..ec35a8ba --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailMaskedEnvMapV2.psh @@ -0,0 +1,18 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, t2 ; Envmap * mask +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailNoTexture.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailNoTexture.psh new file mode 100644 index 00000000..d75a2790 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailNoTexture.psh @@ -0,0 +1,12 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t3 + +mul r0, v0, c3 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminated.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminated.psh new file mode 100644 index 00000000..4b80e91b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminated.psh @@ -0,0 +1,22 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +; interpolate between illuminated + non-selfilluminated +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +#if WRITEONETODESTALPHA +mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedEnvMapV2.psh new file mode 100644 index 00000000..e625791a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedEnvMapV2.psh @@ -0,0 +1,24 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t1 +tex t3 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedMaskedEnvMapV2.psh new file mode 100644 index 00000000..119633a9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedMaskedEnvMapV2.psh @@ -0,0 +1,26 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask +tex t3 ; detail + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_LerpBase.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_LerpBase.psh new file mode 100644 index 00000000..7a9ce740 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_LerpBase.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +lrp r0, c1, t3, t0 ; Lerp between textures +mul r0, r0, c3 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive.psh new file mode 100644 index 00000000..64501f74 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +mul r1, c1, t3 +mad r0, t0, c3, r1 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive_selfillum.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive_selfillum.psh new file mode 100644 index 00000000..07f9d387 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive_selfillum.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +mul r0, c3, t0 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, c1, t3, r0 + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapNoTexture.psh new file mode 100644 index 00000000..4ce3caca --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapNoTexture.psh @@ -0,0 +1,14 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t1 ; cube map + +mul r0.rgb, t1, c2 + ; envmap * envmaptint (color only) + +mov r0.a, c3.a ; Use alpha from modulation... (?) + +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapV2.psh new file mode 100644 index 00000000..80ef4330 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapV2.psh @@ -0,0 +1,14 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map + +mul r0, t0, c3 ; base times modulation +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2.psh new file mode 100644 index 00000000..e6b0c6e4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2.psh @@ -0,0 +1,36 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Environment mapping on a bumped surface +; t0 - Normalmap +; t3 - Cube environment map (*must* be a cube map!) +; +; c0 - color to multiply the results by +; Input texture coords required here are a little wonky. +; tc0.uv <- U,V into the normal map +; tc1.uvw, tc2.uvw, tc3.uvw <- 3x3 matrix transform +; from tangent space->env map space +; tc1.q, tc2.q, tc3.q <- eye vector in env map space +;------------------------------------------------------------------------------ +; This version doesn't multiply by lighting. + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +; result goes in output color +mul r0.rgb, t3, c0 ; constant color ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha.psh new file mode 100644 index 00000000..9fa7db3e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha.psh @@ -0,0 +1,42 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Environment mapping on a bumped surface +; t0 - Normalmap +; t3 - Cube environment map (*must* be a cube map!) +; +; c0 - color to multiply the results by +; Input texture coords required here are a little wonky. +; tc0.uv <- U,V into the normal map +; tc1.uvw, tc2.uvw, tc3.uvw <- 3x3 matrix transform +; from tangent space->env map space +; tc1.q, tc2.q, tc3.q <- eye vector in env map space +;------------------------------------------------------------------------------ +; This version doesn't multiply by lighting. + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +; result goes in output color +mul r0.rgb, t3, c0 ; constant color ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + +; Multiply the output color by the alpha channel of the normal map. +mul r0.rgb, t0.a, r0 + + + + + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14.psh new file mode 100644 index 00000000..eac900c9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14.psh @@ -0,0 +1,42 @@ +ps.1.4 +;------------------------------------------------------------------------------ +; Phase 1 +;------------------------------------------------------------------------------ +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! +;mov r0.rgba, r4 + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) +; Alpha gets lost after phase marker, so store it here +mov r5, r0.a +;------------------------------------------------------------------------------ +; Phase 2 +;------------------------------------------------------------------------------ +phase +; Sample environment map +texld r3, r2 +; Result goes in output color (multiply by constant color c0) +mul r0.rgb, r3, c0 ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + +; mult by alpha +mul r0.rgb, r0, r5 diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_ps14.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_ps14.psh new file mode 100644 index 00000000..7c88013f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_ps14.psh @@ -0,0 +1,39 @@ +ps.1.4 +;------------------------------------------------------------------------------ +; Phase 1 +;------------------------------------------------------------------------------ +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) +; Alpha gets lost after phase marker, so store it here +mov r5, r0.a +;------------------------------------------------------------------------------ +; Phase 2 +;------------------------------------------------------------------------------ +phase +; Sample environment map +texld r3, r2 +; Result goes in output color (multiply by constant color c0) +mul r0.rgb, r3, c0 ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting.vsh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting.vsh new file mode 100644 index 00000000..576e31cf --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting.vsh @@ -0,0 +1,93 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$worldTangentS ); +&AllocateRegister( \$worldTangentT ); + +&SkinPositionNormalAndTangentSpace( $worldPos, $worldNormal, + $worldTangentS, $worldTangentT ); + +;------------------------------------------------------------------------------ +; Transform the position from world to proj space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +; svect +mov oT1.x, $worldTangentS.x +mov oT2.x, $worldTangentS.y +mov oT3.x, $worldTangentS.z +&FreeRegister( \$worldTangentS ); + +; tvect +mov oT1.y, $worldTangentT.x +mov oT2.y, $worldTangentT.y +mov oT3.y, $worldTangentT.z +&FreeRegister( \$worldTangentT ); + +; normal +mov oT1.z, $worldNormal.x +mov oT2.z, $worldNormal.y +mov oT3.z, $worldNormal.z + +&FreeRegister( \$worldNormal ); + +; Compute the vector from vertex to camera +&AllocateRegister( \$eyeVector ); +sub $eyeVector.xyz, $cEyePos, $worldPos + +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $eyeVector.x +mov oT2.w, $eyeVector.y +mov oT3.w, $eyeVector.z + +&FreeRegister( \$eyeVector ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.vsh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.vsh new file mode 100644 index 00000000..2ac66164 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.vsh @@ -0,0 +1,90 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$worldTangentS ); +&AllocateRegister( \$worldTangentT ); + +&SkinPositionNormalAndTangentSpace( $worldPos, $worldNormal, + $worldTangentS, $worldTangentT ); + +;------------------------------------------------------------------------------ +; Transform the position from world to proj space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +; svect +mov oT1.x, $worldTangentS.x +mov oT2.x, $worldTangentS.y +mov oT3.x, $worldTangentS.z +&FreeRegister( \$worldTangentS ); + +; tvect +mov oT1.y, $worldTangentT.x +mov oT2.y, $worldTangentT.y +mov oT3.y, $worldTangentT.z +&FreeRegister( \$worldTangentT ); + +; normal +mov oT1.z, $worldNormal.x +mov oT2.z, $worldNormal.y +mov oT3.z, $worldNormal.z + +&FreeRegister( \$worldNormal ); + +; Compute the vector from vertex to camera +&AllocateRegister( \$eyeVector ); +sub $eyeVector.xyz, $cEyePos, $worldPos + +&FreeRegister( \$worldPos ); + +; eye vector +mov oT4.xyz, $eyeVector + +&FreeRegister( \$eyeVector ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapNoTexture.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapNoTexture.psh new file mode 100644 index 00000000..4c65d906 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapNoTexture.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t1 ; cube map +tex t2 ; envmap mask + +mul r1, t1, t2 ; Envmap * mask +mul r0.rgb, r1, c2 ; envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 + ; * 2 * (overbrightFactor/2) +mul r0.a, c3.a, t2.a ; alpha = modulation * mask alpha + +#if WRITEONETODESTALPHA +mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapV2.psh new file mode 100644 index 00000000..ffa3f1e0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapV2.psh @@ -0,0 +1,16 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, t2 ; Envmap * mask +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_NoTexture.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_NoTexture.psh new file mode 100644 index 00000000..b98b9396 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_NoTexture.psh @@ -0,0 +1,9 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +mul r0, v0, c3 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.psh new file mode 100644 index 00000000..86710123 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.psh @@ -0,0 +1,5 @@ +ps.1.1 + +tex t0 + +mul r0.rgba, c0, t0 diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.vsh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.vsh new file mode 100644 index 00000000..40eb8d28 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.vsh @@ -0,0 +1,41 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&SkinPosition( $worldPos ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$projPos ); +&FreeRegister( \$worldPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminated.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminated.psh new file mode 100644 index 00000000..c837e9af --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminated.psh @@ -0,0 +1,19 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 + +; interpolate between illuminated + non-selfilluminated +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedEnvMapV2.psh new file mode 100644 index 00000000..2d280f5c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedEnvMapV2.psh @@ -0,0 +1,21 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t1 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedMaskedEnvMapV2.psh b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedMaskedEnvMapV2.psh new file mode 100644 index 00000000..da6b77c3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedMaskedEnvMapV2.psh @@ -0,0 +1,23 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/mp/src/materialsystem/stdshaders/VertexLitTexture.psh b/mp/src/materialsystem/stdshaders/VertexLitTexture.psh new file mode 100644 index 00000000..7a692c92 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitTexture.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 + +mul r0, t0, v0 + diff --git a/mp/src/materialsystem/stdshaders/VertexLitTexture_Overbright2.psh b/mp/src/materialsystem/stdshaders/VertexLitTexture_Overbright2.psh new file mode 100644 index 00000000..a69250bf --- /dev/null +++ b/mp/src/materialsystem/stdshaders/VertexLitTexture_Overbright2.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 + +mul_x2 r0.rgb, t0, v0 ++ mul r0.a, t0, v0 + diff --git a/mp/src/materialsystem/stdshaders/WaterCheapFresnelOpaque_ps14.psh b/mp/src/materialsystem/stdshaders/WaterCheapFresnelOpaque_ps14.psh new file mode 100644 index 00000000..08438dcb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapFresnelOpaque_ps14.psh @@ -0,0 +1,40 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 +texld r4, t5 ; Normalize the tangent-space eye vector + +; dot eye-vector with per-pixel normal from r0 +dp3_sat r1, r4_bx2, r0_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r0.a, 1-r1.a, 1-r1.a ; squared +mul r0.a, r0.a, r0.a ; quartic +mul_sat r1.a, r0.a, 1-r1.a ; quintic + +; multiply color by reflecttint +mul r0, r3, c1 + +; blend between reflected color and fog color based on fresnel +lrp r0.rgb, r1.a, r0, c0 \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/WaterCheapFresnel_ps14.psh b/mp/src/materialsystem/stdshaders/WaterCheapFresnel_ps14.psh new file mode 100644 index 00000000..5ebb39f4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapFresnel_ps14.psh @@ -0,0 +1,39 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 +texld r4, t5 ; Normalize the tangent-space eye vector + +; dot eye-vector with per-pixel normal from r0 +dp3_sat r1, r4_bx2, r0_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r0.a, 1-r1.a, 1-r1.a ; squared +mul r0.a, r0.a, r0.a ; quartic +mul_sat r1.a, r0.a, 1-r1.a ; quintic + +; multiply color by reflecttint +mul r0.rgb, r3, c1 ++mov_sat r0.a, v0.a +add_sat r0.a, r1.a, r0.a diff --git a/mp/src/materialsystem/stdshaders/WaterCheapNoFresnelOpaque_ps11.psh b/mp/src/materialsystem/stdshaders/WaterCheapNoFresnelOpaque_ps11.psh new file mode 100644 index 00000000..60502016 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapNoFresnelOpaque_ps11.psh @@ -0,0 +1,19 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0, t3, c1 ; multiply color by reflecttint +lrp r0.rgb, c1.a, r0, c0 ; blend between reflected color and fog color based on constant factor + + + + + diff --git a/mp/src/materialsystem/stdshaders/WaterCheapNoFresnel_ps11.psh b/mp/src/materialsystem/stdshaders/WaterCheapNoFresnel_ps11.psh new file mode 100644 index 00000000..fe76d772 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapNoFresnel_ps11.psh @@ -0,0 +1,18 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0.rgb, t3, c1 ; multiply color by reflecttint ++mov_sat r0.a, v0.a ; NOTE: This is necessary since v0.a can be outside 0 - 1! +add_sat r0.a, c1.a, r0.a ; cheap water blend factor + constant blend factor + + + diff --git a/mp/src/materialsystem/stdshaders/WaterCheapOpaque_ps11.psh b/mp/src/materialsystem/stdshaders/WaterCheapOpaque_ps11.psh new file mode 100644 index 00000000..50d7f803 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapOpaque_ps11.psh @@ -0,0 +1,26 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0, t3, c1 ; envmap color * envmaptint + +dp3_sat t2, v0_bx2, t0_bx2 ; dot eye-vector with per-pixel normal from t0 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +; NOTE: This is not perspective-correct and results in strange artifacts +mul r1.a, 1-t2.a, 1-t2.a ; squared +mul r1.a, r1.a, r1.a ; quartic +mul_sat r1.a, r1.a, 1-t2.a ; quintic + +; t1.a is now the fresnel factor +lrp r0.rgb, r1.a, r0, c0 ; blend between reflected color and fog color based on fresnel + + diff --git a/mp/src/materialsystem/stdshaders/WaterCheapOpaque_ps14.psh b/mp/src/materialsystem/stdshaders/WaterCheapOpaque_ps14.psh new file mode 100644 index 00000000..bd491d58 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapOpaque_ps14.psh @@ -0,0 +1,31 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 + +; multiply color by reflecttint +mul r0, r3, c1 + +; blend between reflected color and fog color based on constant factor +lrp r0.rgb, c1.a, r0, c0 diff --git a/mp/src/materialsystem/stdshaders/WaterCheapPerVertexFresnel_vs11.vsh b/mp/src/materialsystem/stdshaders/WaterCheapPerVertexFresnel_vs11.vsh new file mode 100644 index 00000000..6ca504cf --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheapPerVertexFresnel_vs11.vsh @@ -0,0 +1,100 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $worldEyeVect.x +mov oT2.w, $worldEyeVect.y +mov oT3.w, $worldEyeVect.z + +&AllocateRegister( \$tangentEyeVect ); + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +&Normalize( $tangentEyeVect ); +mov oD0.xyz, $tangentEyeVect + +&FreeRegister( \$tangentEyeVect ); + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_2.x +mul oD0.w, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_2.y + +&FreeRegister( \$worldEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/mp/src/materialsystem/stdshaders/WaterCheap_ps11.psh b/mp/src/materialsystem/stdshaders/WaterCheap_ps11.psh new file mode 100644 index 00000000..34178d28 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheap_ps11.psh @@ -0,0 +1,26 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0.rgb, t3, c1 ; envmap color * envmaptint ++mov_sat r0.a, v0.a ; Put the cheap water blend factor here + +dp3_sat t2, v0_bx2, t0_bx2 ; dot eye-vector with per-pixel normal from t0 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +; NOTE: This is not perspective-correct and results in strange artifacts +mul r1.a, 1-t2.a, 1-t2.a ; squared +mul r1.a, r1.a, r1.a ; quartic +mul_sat r1.a, r1.a, 1-t2.a ; quintic + +; t1.a is now the fresnel factor +add_sat r0.a, r1.a, r0.a ; Now we have the final blend factor between cheap water + refraction + diff --git a/mp/src/materialsystem/stdshaders/WaterCheap_ps14.psh b/mp/src/materialsystem/stdshaders/WaterCheap_ps14.psh new file mode 100644 index 00000000..2c452539 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheap_ps14.psh @@ -0,0 +1,30 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 + +; multiply color by reflecttint +mul r0.rgb, r3, c1 ++mov_sat r0.a, v0.a ; Necessary since v0.a may be negative +add_sat r0.a, c1.a, r0.a diff --git a/mp/src/materialsystem/stdshaders/WaterCheap_ps2x.fxc b/mp/src/materialsystem/stdshaders/WaterCheap_ps2x.fxc new file mode 100644 index 00000000..4ca66570 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheap_ps2x.fxc @@ -0,0 +1,152 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "FRESNEL" "0..1" +// STATIC: "BLEND" "0..1" +// STATIC: "REFRACTALPHA" "0..1" +// STATIC: "HDRTYPE" "0..2" +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] + +// DYNAMIC: "HDRENABLED" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +#include "common_ps_fxc.h" + +const HALF3 g_WaterFogColor : register( c0 ); +const HALF4 g_CheapWaterParams : register( c1 ); +const HALF4 g_ReflectTint : register( c2 ); +const float4 g_PixelFogParams : register( c3 ); + +#define g_CheapWaterStart g_CheapWaterParams.x +#define g_CheapWaterEnd g_CheapWaterParams.y +#define g_CheapWaterDeltaRecip g_CheapWaterParams.z +#define g_CheapWaterStartDivDelta g_CheapWaterParams.w + +sampler EnvmapSampler : register( s0 ); +sampler NormalMapSampler : register( s1 ); +#if REFRACTALPHA +sampler RefractSampler : register( s2 ); +#endif +sampler NormalizeSampler : register( s6 ); + +struct PS_INPUT +{ + float2 normalMapTexCoord : TEXCOORD0; + HALF3 worldSpaceEyeVect : TEXCOORD1; + HALF3x3 tangentSpaceTranspose : TEXCOORD2; + float4 vRefract_W_ProjZ : TEXCOORD5; + +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; +#endif + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBlend = BLEND ? true : false; + +#if MULTITEXTURE + float3 vNormal = tex2D( NormalMapSampler, i.normalMapTexCoord ); + float3 vNormal1 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.xy ); + float3 vNormal2 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.zw ); + vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 ); + +#if ( NORMAL_DECODE_MODE == NORM_DECODE_ATI2N ) + vNormal.xy = vNormal.xy * 2.0f - 1.0f; + vNormal.z = sqrt( 1.0f - dot(vNormal.xy, vNormal.xy) ); +#else + vNormal = 2.0 * vNormal - 1.0; +#endif + +#else + float3 vNormal = DecompressNormal( NormalMapSampler, i.normalMapTexCoord, NORMAL_DECODE_MODE ); +#endif + + HALF3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); + HALF3 worldSpaceEye; + + HALF flWorldSpaceDist = 1.0f; + +#ifdef NV3X + // for some reason, fxc doesn't convert length( half3 v ) into all _pp opcodes. + if (bBlend) + { + worldSpaceEye = i.worldSpaceEyeVect; + HALF worldSpaceDistSqr = dot( worldSpaceEye, worldSpaceEye ); + HALF rcpWorldSpaceDist = rsqrt( worldSpaceDistSqr ); + worldSpaceEye *= rcpWorldSpaceDist; + flWorldSpaceDist = worldSpaceDistSqr * rcpWorldSpaceDist; + } + else + { + worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect ); + } +#else // !NV3X + if (bBlend) + { + worldSpaceEye = i.worldSpaceEyeVect; + flWorldSpaceDist = length( worldSpaceEye ); + worldSpaceEye /= flWorldSpaceDist; + } + else + { + worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect ); + } +#endif + + HALF3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldSpaceEye ); + HALF3 specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= g_ReflectTint; + +#if FRESNEL + // FIXME: It's unclear that we want to do this for cheap water + // but the code did this previously and I didn't want to change it + HALF flDotResult = dot( worldSpaceEye, worldSpaceNormal ); + flDotResult = 1.0f - max( 0.0f, flDotResult ); + + HALF flFresnelFactor = flDotResult * flDotResult; + flFresnelFactor *= flFresnelFactor; + flFresnelFactor *= flDotResult; +#else + HALF flFresnelFactor = g_ReflectTint.a; +#endif + + HALF flAlpha; + if (bBlend) + { + HALF flReflectAmount = saturate( flWorldSpaceDist * g_CheapWaterDeltaRecip - g_CheapWaterStartDivDelta ); + flAlpha = saturate( flFresnelFactor + flReflectAmount ); + +#if REFRACTALPHA + // Perform division by W only once + float ooW = 1.0f / i.vRefract_W_ProjZ.z; + float2 unwarpedRefractTexCoord = i.vRefract_W_ProjZ * ooW; + float fogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a; + // Fade on the border between the water and land. + flAlpha *= saturate( ( fogDepthValue - .05f ) * 20.0f ); +#endif + } + else + { + flAlpha = 1.0f; +#if HDRTYPE == 0 || HDRENABLED == 0 + specularLighting = lerp( g_WaterFogColor, specularLighting, flFresnelFactor ); +#else + specularLighting = lerp( GammaToLinear( g_WaterFogColor ), specularLighting, flFresnelFactor ); +#endif + } + + // multiply the color by alpha.since we are using alpha blending to blend against dest alpha for borders. + + + +#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE) + float fogFactor = CalcRangeFog( i.vRefract_W_ProjZ.w, g_PixelFogParams.x, g_PixelFogParams.z, g_PixelFogParams.w ); +#else + float fogFactor = 0; +#endif + + return FinalOutput( float4( specularLighting, flAlpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/mp/src/materialsystem/stdshaders/WaterCheap_vs11.vsh b/mp/src/materialsystem/stdshaders/WaterCheap_vs11.vsh new file mode 100644 index 00000000..b1cdd61f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheap_vs11.vsh @@ -0,0 +1,88 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $worldEyeVect.x +mov oT2.w, $worldEyeVect.y +mov oT3.w, $worldEyeVect.z + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_2.x +mul oD0, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_2.y + +&FreeRegister( \$worldEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/mp/src/materialsystem/stdshaders/WaterCheap_vs14.vsh b/mp/src/materialsystem/stdshaders/WaterCheap_vs14.vsh new file mode 100644 index 00000000..0e5a1074 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheap_vs14.vsh @@ -0,0 +1,96 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; eye vector +mov oT4.xyz, $worldEyeVect + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_2.x +mul oD0, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_2.y + +; stick the tangent space eye vector into oT5.xyz +mov oT5.xyz, $tangentEyeVect + +&FreeRegister( \$worldEyeVect ); +&FreeRegister( \$tangentEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/mp/src/materialsystem/stdshaders/WaterCheap_vs20.fxc b/mp/src/materialsystem/stdshaders/WaterCheap_vs20.fxc new file mode 100644 index 00000000..bae02380 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterCheap_vs20.fxc @@ -0,0 +1,84 @@ +// STATIC: "BLEND" "0..1" +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vNormalMapCoord : TEXCOORD0; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 normalMapTexCoord : TEXCOORD0; + float3 worldVertToEyeVector : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + float4 vRefract_W_ProjZ : TEXCOORD5; + float4 vExtraBumpTexCoord : TEXCOORD6; + float4 fogFactorW : COLOR1; +}; + +const float4 cNormalMapTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 TexOffsets : register( SHADER_SPECIFIC_CONST_3 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + + projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + +#if BLEND + // Map projected position to the reflection texture + o.vRefract_W_ProjZ.x = projPos.x; + o.vRefract_W_ProjZ.y = -projPos.y; // invert Y + o.vRefract_W_ProjZ.xy = (o.vRefract_W_ProjZ + projPos.w) * 0.5f; + o.vRefract_W_ProjZ.z = projPos.w; +#endif + + o.vRefract_W_ProjZ.w = projPos.z; + + worldPos = mul( v.vPos, cModel[0] ); + + float3 worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + float3 worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + o.tangentSpaceTranspose[0] = worldTangentS; + o.tangentSpaceTranspose[1] = worldTangentT; + o.tangentSpaceTranspose[2] = worldNormal; + + float3 worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + o.worldVertToEyeVector = worldVertToEyeVector; + + // FIXME: need to add a normalMapTransform to all of the water shaders. + //o.normalMapTexCoord.x = dot( v.vNormalMapCoord, cNormalMapTransform[0] ) + cNormalMapTransform[0].w; + //o.normalMapTexCoord.y = dot( v.vNormalMapCoord, cNormalMapTransform[1] ) + cNormalMapTransform[1].w; + o.normalMapTexCoord = v.vNormalMapCoord; + + float f45x=v.vNormalMapCoord.x+v.vNormalMapCoord.y; + float f45y=v.vNormalMapCoord.y-v.vNormalMapCoord.x; + o.vExtraBumpTexCoord.x=f45x*0.1+TexOffsets.x; + o.vExtraBumpTexCoord.y=f45y*0.1+TexOffsets.y; + o.vExtraBumpTexCoord.z=v.vNormalMapCoord.y*0.45+TexOffsets.z; + o.vExtraBumpTexCoord.w=v.vNormalMapCoord.x*0.45+TexOffsets.w; + + o.fogFactorW = CalcFog( worldPos, projPos, FOGTYPE_RANGE ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/WaterReflect_ps11.psh b/mp/src/materialsystem/stdshaders/WaterReflect_ps11.psh new file mode 100644 index 00000000..d31ab49c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterReflect_ps11.psh @@ -0,0 +1,27 @@ +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: reflection render target +; texcoords: +; t2: +; texture: normal map (usef for fresnel calculation) +; texcoords: +; t4: texture: normalization cube map +; texcoords: eye vect + +tex t0 ; sample dudv map +texbem t1, t0 ; reflection +tex t2 ; normal map +tex t3 ; eye vector (through normalization cubemap) + +; dot eye-vector with per-pixel normal from t2 +dp3_sat r1.rgba, t3_bx2, t2_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 +mul r0.a, 1-r1.a, 1-r1.a // squared +mul r0.a, r0.a, r0.a // quartic +mul r0.rgb, t1, c0 // shove color from reflection render target into r0 ++mul_sat r0.a, r0.a, 1-r1.a // quintic \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/WaterRefractFresnel_ps11.psh b/mp/src/materialsystem/stdshaders/WaterRefractFresnel_ps11.psh new file mode 100644 index 00000000..88d1f8dc --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterRefractFresnel_ps11.psh @@ -0,0 +1,24 @@ +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: refraction render target +; texcoords: + +tex t0 ; sample dudv map +texbem t1, t0 ; refraction +tex t2 ; The normal map +tex t3 ; Normalize the tangent-space vector to the eye + +; dot eye-vector with per-pixel normal from t2 +dp3_sat r1.rgba, t2_bx2, t3_bx2 + +mul r0.a, 1-r1.a, 1-r1.a ; squared +mul r0.a, r0.a, r0.a ; quartic + +mul r0.rgb, t1, c0 ++mul_sat r0.a, r0.a, 1-r1.a ; quintic + +add_sat r0.a, r0.a, v0.a ; cheap water distance diff --git a/mp/src/materialsystem/stdshaders/WaterRefract_ps11.psh b/mp/src/materialsystem/stdshaders/WaterRefract_ps11.psh new file mode 100644 index 00000000..7e3ee733 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WaterRefract_ps11.psh @@ -0,0 +1,13 @@ +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: refraction render target +; texcoords: + +tex t0 ; sample dudv map +texbem t1, t0 ; refraction + +mul r0, t1, c0 diff --git a/mp/src/materialsystem/stdshaders/Water_ps14.psh b/mp/src/materialsystem/stdshaders/Water_ps14.psh new file mode 100644 index 00000000..e9daecd1 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Water_ps14.psh @@ -0,0 +1,96 @@ +; STATIC: "REFLECT" "0..1" +; STATIC: "REFRACT" "0..1" +ps.1.4 +; T2 - refraction +; T3 - normal map +; T4 - reflection +; TC0 - normal map coords +; TC1 - proj tex coords (reflection) +; TC2 - proj tex coords (refraction) +; TC3 - tangent space view vec +; TC4 - displacement scale + +; sample normal map +texld r3, t0 + +#if REFLECT +; reflection coords +texcrd r4.xy, t1_dw.xyw +#endif +#if REFRACT +; refraction coords +texcrd r2.xy, t2_dw.xyw +#endif +; tangent space eye vector +texld r1, t5 ; <---- Normalizing CUBE MAP here!!! +; reflection/refraction scale (x,y) +texcrd r0.xyz, t4.xyz + +; perturb coords by constant displacement +; and by normal map alpha (which has 1/(2**miplevel in it) +mul r0.rg, r0, r3.a +#if REFLECT +mad r4.rg, r3_bx2, r0.x, r4 +#endif + +#if REFRACT +mad r2.rg, r3_bx2, r0.y, r2 +#endif + +; stuff something into z so that texld will deal +#if REFLECT +mov r4.b, c5 +#endif +#if REFRACT +mov r2.b, c5 +#endif + +phase + +#if REFLECT +; reflection +texld r4, r4 +#endif +#if REFRACT +; refraction +texld r2, r2 +#endif + +#if REFLECT +; N.V +dp3_sat r1.a, r3_bx2, r1_bx2 +#endif + +#if REFRACT +; tint refraction +mul r2.rgb, r2, c1 +#endif + +#if REFLECT +; tint reflction +mul r4.rgb, r4, c4 + +; (1-N.V) ^ 5 ++mul r0.a, 1-r1.a, 1-r1.a +mul r0.a, r0.a, r0.a +mul_sat r0.a, r0.a, 1-r1.a +#endif + +#if !REFLECT && !REFRACT +; This is wrong!!!! +mov r0.rgba, c0 +#endif + +#if !REFLECT && REFRACT +mov r0.rgba, r2 +#endif + +#if REFLECT && !REFRACT +mov r0.rgba, r4 +#endif + +#if REFLECT && REFRACT +; reflection * fresnel + refraction * ( 1 - fresnel ) +lrp r0.rgba, r0.a, r4, r2 +#endif + diff --git a/mp/src/materialsystem/stdshaders/Water_ps14.vsh b/mp/src/materialsystem/stdshaders/Water_ps14.vsh new file mode 100644 index 00000000..0ec30aa7 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Water_ps14.vsh @@ -0,0 +1,95 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; $SHADER_SPECIFIC_CONST_0..$SHADER_SPECIFIC_CONST_3 - special proj matrix +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + + +alloc $projPos + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos + +; Transform position from object to world space +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal +mov $tangentEyeVect.w, $cZero + +mov oT5, $tangentEyeVect + +; base coordinates +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +; reflection +alloc $projPosReflect + +mov $projPosReflect, $projPos +add $projPosReflect.xy, $projPosReflect, $projPosReflect.w +mul $projPosReflect.xy, $projPosReflect, $cHalf +mov oT1, $projPosReflect + +; refraction +mov $projPos.y, -$projPos.y +add $projPos.xy, $projPos, $projPos.w +mul $projPos.xy, $projPos, $cHalf +mov oT2, $projPos + +; reflectionscale, refractionscale +mov oT4, $SHADER_SPECIFIC_CONST_4 + +free $worldEyeVect +free $tangentEyeVect +free $projPosReflect +free $worldPos +free $projPos \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/Water_vs11.vsh b/mp/src/materialsystem/stdshaders/Water_vs11.vsh new file mode 100644 index 00000000..3b0131b8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Water_vs11.vsh @@ -0,0 +1,102 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $projPos + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +alloc $worldPos + +; Transform position from object to world space +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +; transform the eye vector to tangent space +dp3 oT3.x, $worldEyeVect, $vTangentS +dp3 oT3.y, $worldEyeVect, $vTangentT +dp3 oT3.z, $worldEyeVect, $vNormal + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_3.x +mul oD0, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_3.y + +; dudv map +alloc $bumpTexCoord + +dp4 $bumpTexCoord.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 $bumpTexCoord.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +mov oT0.xy, $bumpTexCoord + +; normal map +mov oT2.xy, $bumpTexCoord + +free $bumpTexCoord + +alloc $newProjPos + +mov oPos, $projPos + +; special case perspective correct texture projection so that the texture fits exactly on the screen +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_4.w +add $projPos.xy, $projPos.xy, $projPos.w +mul $projPos.xy, $projPos.xy, $cHalf + +mov oT1.xy, $projPos.xy +mov oT1.z, $cZero +mov oT1.w, $projPos.w + +free $projPos +free $worldPos +free $worldEyeVect +free $projTangentS +free $projTangentT +free $newProjPos diff --git a/mp/src/materialsystem/stdshaders/Water_vs20.fxc b/mp/src/materialsystem/stdshaders/Water_vs20.fxc new file mode 100644 index 00000000..8f3a7a81 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/Water_vs20.fxc @@ -0,0 +1,117 @@ +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "MULTITEXTURE" "0..1" + +// SKIP: $MULTITEXTURE && $BASETEXTURE + +#include "common_vs_fxc.h" + +const float4 cBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); +const float4 TexOffsets : register( SHADER_SPECIFIC_CONST_3 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; +#if !defined( _X360 ) + float vFog : FOG; +#endif + float2 vBumpTexCoord : TEXCOORD0; + float3 vTangentEyeVect : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float W : TEXCOORD3; + float4 vProjPos : TEXCOORD4; + float screenCoord : TEXCOORD5; +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; +#endif +#if BASETEXTURE + HALF4 lightmapTexCoord1And2 : TEXCOORD6; + HALF4 lightmapTexCoord3 : TEXCOORD7; +#endif + float4 fogFactorW : COLOR1; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + // Projected position + float4 vProjPos = mul( v.vPos, cModelViewProj ); + o.vProjPos = o.vProjPos_POSITION = vProjPos; + + // Project tangent basis + float2 vProjTangentS = mul( v.vTangentS, cViewProj ); + float2 vProjTangentT = mul( v.vTangentT, cViewProj ); + + // Map projected position to the reflection texture + float2 vReflectPos; + vReflectPos = (vProjPos.xy + vProjPos.w) * 0.5f; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Reflection transform + o.vReflectXY_vRefractYX = float4( vReflectPos.x, vReflectPos.y, vRefractPos.y, vRefractPos.x ); + o.W = vProjPos.w; + + o.screenCoord = vProjPos.x; + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.fogFactorW = CalcFog( vWorldPos, vProjPos, FOGTYPE_RANGE ); +#if !defined( _X360 ) + o.vFog = o.fogFactorW; +#endif + + // Eye vector + float3 vWorldEyeVect = cEyePos - vWorldPos; + // Transform to the tangent space + o.vTangentEyeVect.x = dot( vWorldEyeVect, v.vTangentS ); + o.vTangentEyeVect.y = dot( vWorldEyeVect, v.vTangentT ); + o.vTangentEyeVect.z = dot( vWorldEyeVect, vObjNormal ); + + // Tranform bump coordinates + o.vBumpTexCoord.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoord.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + float f45x=v.vBaseTexCoord.x+v.vBaseTexCoord.y; + float f45y=v.vBaseTexCoord.y-v.vBaseTexCoord.x; +#if MULTITEXTURE + o.vExtraBumpTexCoord.x=f45x*0.1+TexOffsets.x; + o.vExtraBumpTexCoord.y=f45y*0.1+TexOffsets.y; + o.vExtraBumpTexCoord.z=v.vBaseTexCoord.y*0.45+TexOffsets.z; + o.vExtraBumpTexCoord.w=v.vBaseTexCoord.x*0.45+TexOffsets.w; +#endif + +#if BASETEXTURE + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; +#endif + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/WorldTexture.psh b/mp/src/materialsystem/stdshaders/WorldTexture.psh new file mode 100644 index 00000000..6144fdf2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldTexture.psh @@ -0,0 +1,14 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +mov r0, t0 + diff --git a/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend.psh b/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend.psh new file mode 100644 index 00000000..b9494b02 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mov r0.rgb, t0 + +mul r0.a, t0.a, v0.a ; Grab alpha from vertex color + +lrp r0.rgb, t2.a, t2, r0 ; Base = base * (1 - detail alpha) + detail * detail alpha +mul r0.rgb, r0, v0 ; modulate by vertex color +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend_DetailAlpha.psh b/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend_DetailAlpha.psh new file mode 100644 index 00000000..033730bb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend_DetailAlpha.psh @@ -0,0 +1,25 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c1, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 +tex t2 + +mov_x2_sat r0.rgb, t0 + ; r0 = sat( t0 * 2 ) +mul r0.a, t0.a, v0.a ; Grab alpha from vertex color + +lrp_sat r0.rgb, t2.a, r0, c1 ; r0 = B*Da + (1-Da) + +mul r0.rgb, r0, t2 ; modulate by detail color +mul r0.rgb, r0, v0 ; modulate by vertex color +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend_SelfIlluminated.psh b/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend_SelfIlluminated.psh new file mode 100644 index 00000000..2f5a8ca5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldTwoTextureBlend_SelfIlluminated.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mov r0.rgb, t0 + +mov r0.a, v0.a ; Grab alpha from vertex color + +lrp r0.rgb, t2.a, t2, r0 ; Base = base * (1 - detail alpha) + detail * detail alpha +mul r0.rgb, r0, v0 ; modulate by vertex color +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1.rgb, c1, t0 ; Self illum * tint ++ mul r1.a, t0.a, 1-t2.a ; Reduce self-illum amount based on 1 - detailalpha + +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lightmap + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexAlpha.psh b/mp/src/materialsystem/stdshaders/WorldVertexAlpha.psh new file mode 100644 index 00000000..e610452e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexAlpha.psh @@ -0,0 +1,10 @@ +ps.1.1 + +tex t0 ; basetexture +tex t1 ; lightmap + +mov r0.a, 1-t1.a +;mov r0.rgb, t0 ; * 2 * (overbrightFactor/2) +;mov_x2 r0.rgb, t0 ; * 2 * (overbrightFactor/2) +mul r0.rgb, t0, t1; +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/WorldVertexAlpha.vsh b/mp/src/materialsystem/stdshaders/WorldVertexAlpha.vsh new file mode 100644 index 00000000..ae2566a6 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexAlpha.vsh @@ -0,0 +1,37 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +mov oT0, $vTexCoord0 + +; lightmap texcoords +mov oT1, $vTexCoord1 + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc b/mp/src/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc new file mode 100644 index 00000000..7ccc584a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc @@ -0,0 +1,43 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "PASS" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +// CENTROID: TEXCOORD1 + +sampler BaseSampler : register( s0 ); +sampler LightmapSampler: register( s1 ); +sampler LightmapAlphaSampler: register( s2 ); + +struct PS_INPUT +{ + float2 baseCoord : TEXCOORD0; + float2 lightmapCoord : TEXCOORD1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bAlphaPass = PASS ? true : false; + + float4 base = tex2D( BaseSampler, i.baseCoord ); + float4 lightmap = tex2D( LightmapSampler, i.lightmapCoord ); + float4 alpha = tex2D( LightmapAlphaSampler, i.lightmapCoord ); + + float4 color; + + base.a = dot( base, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); + color = 2.0f * base * lightmap; // The 2x is for an assumed overbright 2 (it's always 2 on dx9) + + if( bAlphaPass ) + { + // Don't care about color, just return pre-multiplied alpha + return FinalOutput( float4( 0.0f, 0.0f, 1.0f, (1.0f - alpha.a) * color.a ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } + else + { + return FinalOutput( float4( color.rgb, (1.0f - alpha.a) ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } +} + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition.psh b/mp/src/materialsystem/stdshaders/WorldVertexTransition.psh new file mode 100644 index 00000000..4fd2882b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition.psh @@ -0,0 +1,18 @@ +; STATIC: "DETAIL" "0..1" +ps.1.1 + +tex t0 ; basetexture +tex t1 ; basetexture2 +tex t2 ; lightmap +#if DETAIL +tex t3 ; detail +#endif + +mov_sat r1.a, v0.a +lrp r0, r1.a, t1, t0 + +mul r0, r0, t2 +#if DETAIL +mul_x2 r0.rgb, r0, t3 +#endif +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition.vsh b/mp/src/materialsystem/stdshaders/WorldVertexTransition.vsh new file mode 100644 index 00000000..81e56dbe --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition.vsh @@ -0,0 +1,48 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +; lightmap texcoords +mov oT2, $vTexCoord1 + +; detail +dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh b/mp/src/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh new file mode 100644 index 00000000..d4a5c623 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +mul r0.rgb, t1, t0 ; fold in lightmap (color) ++mov r0.a, v0.a ; fold in lightmap (alpha) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_Editor.psh b/mp/src/materialsystem/stdshaders/WorldVertexTransition_Editor.psh new file mode 100644 index 00000000..936edc9e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_Editor.psh @@ -0,0 +1,10 @@ +ps.1.1 + +tex t0 ; basetexture +tex t1 ; basetexture2 +tex t2 ; lightmap + +; The editor uses vertex alpha as the blend factor +lrp r0, 1-v0.a, t1, t0 +mul r0, r0, t2 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.psh b/mp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.psh new file mode 100644 index 00000000..8d4edad0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.psh @@ -0,0 +1,23 @@ +ps.1.1 + +def c0, 1.0f, 0.0f, 0.0f, 0.0f +def c1, 0.0f, 1.0f, 0.0f, 0.0f +def c2, 0.0f, 0.0f, 1.0f, 0.0f + +tex t0 ; basetexture zy +tex t1 ; basetexture xz +tex t2 ; basetexture xy +tex t3 ; lightmap + +dp3_sat r1, v0, c0 +mul r0, t0, r1 + +dp3_sat r1, v0, c1 +mad r0, t1, r1, r0 + +dp3_sat r1, v0, c2 +mad r0, t2, r1, r0 + +; multiply by lightmap +mul_x2 r0.rgb, r0, t3 ++mov r0.a, v0 ; $vColor diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.vsh b/mp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.vsh new file mode 100644 index 00000000..dd0cc99c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.vsh @@ -0,0 +1,54 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +alloc $projPos + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos +alloc $worldNormal + +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +dp3 $worldNormal.x, $vNormal, $cModel0 +dp3 $worldNormal.y, $vNormal, $cModel1 +dp3 $worldNormal.z, $vNormal, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +free $projPos + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +alloc $texcoord +mul $texcoord.xyz, $worldPos, $SHADER_SPECIFIC_CONST_0 + +mov oT0.xy, $texcoord.zy; +mov oT1.xy, $texcoord.xz; +mov oT2.xy, $texcoord.xy; + +free $texcoord + +; lightmap texcoords +mov oT3, $vTexCoord1 + +mul oD0.rgb, $worldNormal, $worldNormal + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0.a, $vColor + +free $worldPos +free $worldNormal diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_dx8.cpp b/mp/src/materialsystem/stdshaders/WorldVertexTransition_dx8.cpp new file mode 100644 index 00000000..331f8f17 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_dx8.cpp @@ -0,0 +1,537 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "worldvertextransition.inc" +#include "worldvertextransition_vs14.inc" +#include "worldvertextransition_seamless.inc" +#include "lightmappedgeneric_vs11.inc" +#include "writevertexalphatodestalpha_vs11.inc" +#include "worldvertextransition_dx8_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX8 ) + +ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +BEGIN_VS_SHADER( WorldVertexTransition_DX8, + "Help for WorldVertexTransition_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture2", "base texture2 help" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $baseTexture" ) + SHADER_PARAM( BASETEXTURETRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$baseTexture texcoord transform" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map for BASETEXTURE" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( BUMPBASETEXTURE2WITHBUMPMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "0.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "WorldVertexTransition_DX6"; + return 0; + } + + void SetupVars( WorldVertexTransitionEditor_DX8_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTextureTransformVar = BASETEXTURETRANSFORM; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nBaseTexture2FrameVar = FRAME2; + info.m_nBaseTexture2TransformVar = BASETEXTURETRANSFORM2; + } + + SHADER_INIT_PARAMS() + { + // Initializes FLASHLIGHTTEXTURE + MATERIAL_VAR2_LIGHTING_LIGHTMAP + WorldVertexTransitionEditor_DX8_Vars_t info; + SetupVars( info ); + InitParamsWorldVertexTransitionEditor_DX8( params, info ); + + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( IsUsingGraphics() && params[ENVMAP]->IsDefined() && !CanUseEditorMaterials() ) + { + if( stricmp( params[ENVMAP]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + { + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + { + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + if( !params[BUMPBASETEXTURE2WITHBUMPMAP]->IsDefined() ) + { + params[BUMPBASETEXTURE2WITHBUMPMAP]->SetIntValue( 0 ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[DETAILFRAME]->IsDefined() ) + { + params[DETAILFRAME]->SetIntValue( 0 ); + } + + if( params[SEAMLESS_SCALE]->IsDefined() && params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + // seamless scale is going to be used, so kill some other features. . might implement with these features later. + params[DETAIL]->SetUndefined(); + params[BUMPMAP]->SetUndefined(); + params[ENVMAP]->SetUndefined(); + } + + if ( !params[SEAMLESS_SCALE]->IsDefined() ) + { + // zero means don't do seamless mapping. + params[SEAMLESS_SCALE]->SetFloatValue( 0.0f ); + } + + if( params[SSBUMP]->IsDefined() && params[SSBUMP]->GetIntValue() != 0 ) + { + // turn of normal mapping since we have ssbump defined, which + // means that we didn't make a dx8 fallback for this material. + params[BUMPMAP]->SetUndefined(); + } + } + SHADER_INIT + { + // Loads BASETEXTURE, BASETEXTURE2 + WorldVertexTransitionEditor_DX8_Vars_t info; + SetupVars( info ); + InitWorldVertexTransitionEditor_DX8( this, params, info ); + + // FLASHLIGHTFIXME + if ( params[FLASHLIGHTTEXTURE]->IsDefined() ) + { + LoadTexture( FLASHLIGHTTEXTURE ); + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + if ( g_pHardwareConfig->SupportsPixelShaders_1_4() && params[BLENDMODULATETEXTURE]->IsDefined() ) + { + LoadTexture( BLENDMODULATETEXTURE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( params[ENVMAP]->IsDefined() && !params[BUMPMAP]->IsDefined() ) + { + Warning( "must have $bumpmap if you have $envmap for worldvertextransition\n" ); + params[ENVMAP]->SetUndefined(); + params[BUMPMAP]->SetUndefined(); + } + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + LoadBumpMap( BUMPMAP ); + } + if( params[ENVMAP]->IsDefined() ) + { + if( !IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ) ) + { + LoadCubeMap( ENVMAP ); + } + else + { + Warning( "$envmapsphere not supported by worldvertextransition\n" ); + params[ENVMAP]->SetUndefined(); + } + } + } + + void WriteVertexAlphaToDestAlpha( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + if( pShaderShadow ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( false ); + + writevertexalphatodestalpha_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "writevertexalphatodestalpha_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "writevertexalphatodestalpha_ps11" ); + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR, 2, 0, 0 ); + } + else + { + writevertexalphatodestalpha_vs11_Dynamic_Index vshIndex; + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + void DrawFlashlightPass( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, int passID ) + { + bool bBump = ( passID == 0 ) && ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture(); + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, true, passID, BASETEXTURE2, FRAME2 ); + } + + bool ShouldUseBumpmapping( IMaterialVar **params ) + { + return g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + WriteVertexAlphaToDestAlpha( params, pShaderAPI, pShaderShadow ); + DrawFlashlightPass( params, pShaderAPI, pShaderShadow, 0 ); + DrawFlashlightPass( params, pShaderAPI, pShaderShadow, 1 ); + } + + SHADER_DRAW + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + bool bSupports14 = g_pHardwareConfig->SupportsPixelShaders_1_4(); + + // FLASHLIGHTFIXME: need to make these the same. + bool hasFlashlight = UsingFlashlight( params ); + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow ); + } + else if ( params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + // This is the seamless_scale version, which doesn't use $detail or $bumpmap + SHADOW_STATE + { + // three copies of the base texture for seamless blending + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_seamless_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_Seamless", vshIndex.GetIndex() ); + + int pshIndex = 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_Seamless", pshIndex ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + // Texture 0..2 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + float fSeamlessScale = params[SEAMLESS_SCALE]->GetFloatValue(); + float map_scale[4]= { fSeamlessScale, fSeamlessScale, fSeamlessScale, fSeamlessScale }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + + worldvertextransition_seamless_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + SHADOW_STATE + { + // inherit state from previous pass + + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + DYNAMIC_STATE + { + if( !bLightingOnly ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE2, FRAME2 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE2, FRAME2 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE2, FRAME2 ); + } + } + Draw(); + } + else if( !params[BUMPMAP]->IsTexture() || !g_pConfig->UseBumpmapping() ) + { + bool bDetail = params[DETAIL]->IsTexture(); + bool bBlendModulate = params[BLENDMODULATETEXTURE]->IsTexture(); + SHADOW_STATE + { + // This is the dx8, non-worldcraft version, non-bumped version + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if( bDetail ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + if ( bSupports14 && bBlendModulate ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + int fmt = VERTEX_POSITION | VERTEX_COLOR; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + if ( !bSupports14 ) + { + worldvertextransition_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition", vshIndex.GetIndex() ); + + int pshIndex = bDetail ? 1 : 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition", pshIndex ); + } + else + { + worldvertextransition_vs14_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_vs14", vshIndex.GetIndex() ); + + int pshIndex = bDetail ? 1 : 0; + pshIndex += bBlendModulate ? 2 : 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_ps14", pshIndex ); + } + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Texture 1 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE2, FRAME2 ); + } + if( bDetail ) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + } + if ( bSupports14 && bBlendModulate ) + { + BindTexture( SHADER_SAMPLER4, BLENDMODULATETEXTURE ); + } + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + // go ahead and set this even if we don't have a detail texture so the vertex shader doesn't + // barf chunks with unitialized data. + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + + if ( bSupports14 ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, BLENDMASKTRANSFORM ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM2 ); + if ( !bSupports14 ) + { + worldvertextransition_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + worldvertextransition_vs14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); + } + else + { + if( params[BUMPBASETEXTURE2WITHBUMPMAP]->GetIntValue() ) + { + DrawWorldBumpedUsingVertexShader( BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, + ENVMAPFRAME, ENVMAPTINT, COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, + FRESNELREFLECTION, true, BASETEXTURE2, BASETEXTURETRANSFORM2, FRAME2, false ); + } + else + { + // draw the base texture with everything else you normally would for + // bumped world materials + DrawWorldBumpedUsingVertexShader( + BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, ENVMAPFRAME, ENVMAPTINT, + COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, + FRESNELREFLECTION, + false, -1, -1, -1, false ); + + // blend basetexture 2 on top of everything using lightmap alpha. + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR, 2, 0, 0 ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( true ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WorldVertexTransition_BlendBase2" ); + FogToFogColor(); + } + DYNAMIC_STATE + { + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE2, FRAME2 ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + float half[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 4, half ); + EnablePixelShaderOverbright( 0, true, true ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM2 ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + } + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_ps14.psh b/mp/src/materialsystem/stdshaders/WorldVertexTransition_ps14.psh new file mode 100644 index 00000000..763a5d11 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_ps14.psh @@ -0,0 +1,32 @@ +; STATIC: "DETAIL" "0..1" +; STATIC: "BLENDMODULATETEXTURE" "0..1" +ps.1.4 + +def c1, 3.0, -2.0, 0.5, 0.5 + +texld r0, t0 +texld r1, t1 +texld r2, t2 +#if DETAIL +texld r3, t3 ; detail +#endif +#if BLENDMODULATETEXTURE +texld r4, t4 ; detail +#endif + +#if BLEND_MODULATETEXTURE +sub r5.a, v0.a, r4.g +add_sat r5.a, r5.a, c1.a +mad r6.a, c1.g, r5.a, c1.r +mul r6.a, r6.a, r5.a +mul r5.a, r6.a, r5.a +#else +mov_sat r5.a, v0.a +#endif +lrp r0, r5.a, r1, r0 + +mul r0, r0, r2 +#if DETAIL +mul_x2 r0.rgb, r0, r3 +#endif +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc b/mp/src/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc new file mode 100644 index 00000000..f27e870d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc @@ -0,0 +1,47 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "MACROS" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + + +sampler BaseSampler : register( s0 ); +// NOTE: LightmapSampler is at the same place as the lightmap sampler in lightmappedgeneric so that we have +// generally the same texture state here. +// CENTROID: TEXCOORD1 +sampler LightmapSampler: register( s1 ); +sampler BaseSampler2: register( s2 ); +sampler LightmapAlphaSampler: register( s3 ); +sampler MacrosSampler: register( s4 ); + +struct PS_INPUT +{ + float2 baseCoord : TEXCOORD0; + float2 baseCoord2 : TEXCOORD1; + float2 lightmapCoord : TEXCOORD2; + float2 macrosCoord : TEXCOORD3; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bMacros = MACROS ? true : false; + + float4 base = tex2D( BaseSampler, i.baseCoord ); + float4 base2 = tex2D( BaseSampler2, i.baseCoord2 ); + + float4 lightmap = tex2D( LightmapSampler, i.lightmapCoord ); + float blendFactor = lightmap.a; + + float4 color = 2.0f * lightmap * lerp( base2, base, blendFactor ); + if( bMacros ) + { + float4 macros = tex2D( MacrosSampler, i.macrosCoord ); + + // Not sure what to do with macro alpha + color.rgb *= 2.0f * lerp( macros.a, macros.b, blendFactor ); + } + + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_vs14.vsh b/mp/src/materialsystem/stdshaders/WorldVertexTransition_vs14.vsh new file mode 100644 index 00000000..eecc1c89 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_vs14.vsh @@ -0,0 +1,52 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +; lightmap texcoords +mov oT2, $vTexCoord1 + +; detail +dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +; mask +dp4 oT4.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_6 +dp4 oT4.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_7 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/mp/src/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc b/mp/src/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc new file mode 100644 index 00000000..5f18ca81 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc @@ -0,0 +1,64 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cBaseTexCoordTransform2[2] : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cMacrosTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseCoord : TEXCOORD0; + float2 baseCoord2 : TEXCOORD1; + float2 lightmapCoord : TEXCOORD2; + float2 macrosCoord : TEXCOORD3; + float4 color : COLOR0; + float4 fogFactorW : COLOR1; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldNormal, worldPos; + float2 texCoord; + worldPos = mul( v.vPos, cModel[0] ); + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + o.color = v.vColor; + + o.baseCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + o.baseCoord2.x = dot( v.vTexCoord0, cBaseTexCoordTransform2[0] ); + o.baseCoord2.y = dot( v.vTexCoord0, cBaseTexCoordTransform2[1] ); + + o.lightmapCoord = v.vTexCoord1; + + o.macrosCoord.x = dot( v.vTexCoord0, cMacrosTexCoordTransform[0] ); + o.macrosCoord.y = dot( v.vTexCoord0, cMacrosTexCoordTransform[1] ); + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/cable_dx6.cpp b/mp/src/materialsystem/stdshaders/cable_dx6.cpp new file mode 100644 index 00000000..9b11551f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cable_dx6.cpp @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX6 ) + +BEGIN_SHADER( Cable_DX6, + "Help for Cable_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.25", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.25", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + int GetDrawFlagsPass1(IMaterialVar** params ) + { + int flags = SHADER_DRAW_POSITION; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + flags |= SHADER_DRAW_TEXCOORD0; + return flags; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + SetNormalBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params) ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + Vector min, max; + params[MINLIGHT]->GetVecValue( &min.x, 3 ); + params[MAXLIGHT]->GetVecValue( &max.x, 3 ); + Vector avg = ( min + max ) * 0.5f; + pShaderAPI->Color3fv( &avg.x ); + } + Draw( ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/cable_dx8.cpp b/mp/src/materialsystem/stdshaders/cable_dx8.cpp new file mode 100644 index 00000000..9e3c98dd --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cable_dx8.cpp @@ -0,0 +1,132 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A wet version of base * lightmap +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "cable.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX8 ) + +BEGIN_VS_SHADER( Cable_DX8, + "Help for Cable shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "cable/cablenormalmap", "bumpmap texture" ) + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.1", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.3", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && !g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + return "UnlitGeneric_DX6"; + } + return 0; + } + + SHADER_INIT + { + LoadBumpMap( BUMPMAP ); + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Enable blending? + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + int tCoordDimensions[] = {2,2}; + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR | VERTEX_TANGENT_S | VERTEX_TANGENT_T, + 2, tCoordDimensions, 0 ); + + cable_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Cable", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "Cable" ); + + // we are writing linear values from this shader. + // This is kinda wrong. We are writing linear or gamma depending on "IsHDREnabled" below. + // The COLOR really decides if we are gamma or linear. + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBWrite( true ); + } + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BUMPMAP ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + + + // The dot product with the light is remapped from the range + // [-1,1] to [MinLight, MaxLight]. + + // Given: + // -A + B = MinLight + // A + B = MaxLight + // then A = (MaxLight - MinLight) / 2 + // and B = (MaxLight + MinLight) / 2 + + // So here, we multiply the light direction by A to scale the dot product. + // Then in the pixel shader we add by B. + float flMinLight = params[MINLIGHT]->GetFloatValue(); + float flMaxLight = params[MAXLIGHT]->GetFloatValue(); + + float A = (flMaxLight - flMinLight) * 0.5f; + float B = (flMaxLight + flMinLight) * 0.5f; + + float b4[4] = {B,B,B,B}; + if( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + SetPixelShaderConstantGammaToLinear( 0, b4 ); + } + else + { + pShaderAPI->SetPixelShaderConstant( 0, b4 ); + } + + // This is the light direction [0,1,0,0] * A * 0.5 + float lightDir[4] = {0, A*0.5, 0, 0}; + if( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + SetVertexShaderConstantGammaToLinear( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lightDir ); + } + else + { + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lightDir ); + } + + cable_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/cable_dx9.cpp b/mp/src/materialsystem/stdshaders/cable_dx9.cpp new file mode 100644 index 00000000..5b25ed61 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cable_dx9.cpp @@ -0,0 +1,141 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A wet version of base * lightmap +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "cable_vs20.inc" +#include "cable_ps20.inc" +#include "cable_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern ConVar mat_fullbright; + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX9 ) + +BEGIN_VS_SHADER( Cable_DX9, + "Help for Cable shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "cable/cablenormalmap", "bumpmap texture" ) + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.1", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.3", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( !(g_pHardwareConfig->SupportsPixelShaders_2_0() && g_pHardwareConfig->SupportsVertexShaders_2_0()) || + (g_pHardwareConfig->GetDXSupportLevel() < 90) ) + { + return "Cable_DX8"; + } + return 0; + } + + SHADER_INIT + { + LoadBumpMap( BUMPMAP ); + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + } + + SHADER_DRAW + { + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + // Enable blending? + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + int tCoordDimensions[] = {2,2}; + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR | VERTEX_TANGENT_S | VERTEX_TANGENT_T, + 2, tCoordDimensions, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( cable_vs20 ); + SET_STATIC_VERTEX_SHADER( cable_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( cable_ps20b ); + SET_STATIC_PIXEL_SHADER( cable_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( cable_ps20 ); + SET_STATIC_PIXEL_SHADER( cable_ps20 ); + } + + // we are writing linear values from this shader. + // This is kinda wrong. We are writing linear or gamma depending on "IsHDREnabled" below. + // The COLOR really decides if we are gamma or linear. + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + BindTexture( SHADER_SAMPLER0, BUMPMAP ); + if ( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + + } + else + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( cable_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER( cable_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( cable_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( cable_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( cable_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( cable_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/cable_ps2x.fxc b/mp/src/materialsystem/stdshaders/cable_ps2x.fxc new file mode 100644 index 00000000..a3c7ff13 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cable_ps2x.fxc @@ -0,0 +1,54 @@ +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler NormalSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + + float4 directionalLightColor : COLOR0; + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 vNormalMapDir = tex2D( NormalSampler, i.vTexCoord0 ); // Get the 3-vector from the normal map + float4 textureColor = tex2D( BaseTextureSampler, i.vTexCoord1 ); // Interpret tcoord t1 as color data. + + //Expand compacted vectors + //TODO: find if there's a better way to expand a color normal to a full vector ( _bx2 was used in the assembly code ) + vNormalMapDir = (vNormalMapDir - 0.5) * 2.0; + float3 vLightDir = float3( 0.0f, 0.0f, 1.0f ); + + float lightDirDotNormalMap = dot( vNormalMapDir, vLightDir ); //normalMap dot dirLightDir + + // do half-lambert on the dot + lightDirDotNormalMap = lightDirDotNormalMap * 0.5 + 0.5; + lightDirDotNormalMap = lightDirDotNormalMap * lightDirDotNormalMap; + + float4 resultColor; + resultColor.xyz = lightDirDotNormalMap * ( textureColor.rgb * i.directionalLightColor.rgb ); + resultColor.a = textureColor.a * i.directionalLightColor.a; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/mp/src/materialsystem/stdshaders/cable_vs20.fxc b/mp/src/materialsystem/stdshaders/cable_vs20.fxc new file mode 100644 index 00000000..adb3559e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cable_vs20.fxc @@ -0,0 +1,80 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 directionalLightColor : COLOR0; + + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + + float4 directionalLightColor : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + //------------------------------------------------------------------------------ + // Setup the tangent space + //------------------------------------------------------------------------------ + + // Get S crossed with T (call it R) + float3 r = cross( v.vTangentS, v.vTangentT ); + + // Normalize S (into s) + float3 s = normalize( v.vTangentS ); + + // Normalize R (into r) + r = normalize( r ); + + // Regenerate T (into t) + float3 t = cross( r, v.vTangentS ); + + //------------------------------------------------------------------------------ + // Copy texcoords for the normal map and base texture + //------------------------------------------------------------------------------ + o.vTexCoord0 = v.vTexCoord0; + o.vTexCoord1 = v.vTexCoord1; + + // Pass the dirlight color through + o.directionalLightColor = v.directionalLightColor; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/cloud.cpp b/mp/src/materialsystem/stdshaders/cloud.cpp new file mode 100644 index 00000000..810e6c4d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud.cpp @@ -0,0 +1,76 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( Cloud, + "Help for Cloud" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + LoadTexture( CLOUDALPHATEXTURE ); + if( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + if( g_pHardwareConfig->GetSamplerCount() >= 2 ) + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | + SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_TEXCOORD1 ); + DefaultFog(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // handle scrolling of base texture + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE0, + BASETEXTURETRANSFORM, CLOUDSCALE ); + SetFixedFunctionTextureScale( MATERIAL_TEXTURE1, MASKSCALE ); + } + Draw(); + } + else + { + ShaderWarning("Cloud not supported for single-texturing boards!\n"); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/cloud_dx8.cpp b/mp/src/materialsystem/stdshaders/cloud_dx8.cpp new file mode 100644 index 00000000..d3bc2530 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud_dx8.cpp @@ -0,0 +1,77 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "cloud_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Cloud_dx8, "Help for Cloud" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( CLOUDALPHATEXTURE, TEXTUREFLAGS_SRGB ); + if ( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if ( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, 0, 0 ); + + cloud_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "cloud_vs11", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "cloud_ps11" ); + + DefaultFog(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // handle scrolling of base texture + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM, CLOUDSCALE ); + SetVertexShaderTextureScale( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, MASKSCALE ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/cloud_dx9.cpp b/mp/src/materialsystem/stdshaders/cloud_dx9.cpp new file mode 100644 index 00000000..4b04b8b4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud_dx9.cpp @@ -0,0 +1,94 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// DirectX 9 Cloud shader +// +//=============================================================================== + +#include "BaseVSShader.h" +#include "cloud_vs20.inc" +#include "cloud_ps20.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Cloud, Cloud_dx9 ) + +BEGIN_VS_SHADER( Cloud_dx9, "Help for Cloud" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "Cloud_dx8"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( CLOUDALPHATEXTURE, TEXTUREFLAGS_SRGB ); + if ( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if ( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( cloud_vs20 ); + SET_STATIC_VERTEX_SHADER( cloud_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( cloud_ps20 ); + SET_STATIC_PIXEL_SHADER( cloud_ps20 ); + + DefaultFog(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // Handle scrolling of base texture + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM, CLOUDSCALE ); + SetVertexShaderTextureScale( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, MASKSCALE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( cloud_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( cloud_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( cloud_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( cloud_ps20 ); + } + + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/cloud_ps11.psh b/mp/src/materialsystem/stdshaders/cloud_ps11.psh new file mode 100644 index 00000000..8e5627cb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud_ps11.psh @@ -0,0 +1,6 @@ +ps.1.1 + +tex t0 +tex t1 + +mul r0, t0, t1 diff --git a/mp/src/materialsystem/stdshaders/cloud_ps20.fxc b/mp/src/materialsystem/stdshaders/cloud_ps20.fxc new file mode 100644 index 00000000..31f8bbd2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud_ps20.fxc @@ -0,0 +1,26 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler CloudAlphaSampler : register( s1 ); + +struct PS_INPUT +{ + float2 baseCoords : TEXCOORD0; + float2 cloudAlphaCoords : TEXCOORD1; + float fogFactor : TEXCOORD2; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 vBase = tex2D( BaseTextureSampler, i.baseCoords ); + float4 vCloudAlpha = tex2D( CloudAlphaSampler, i.cloudAlphaCoords ); + + float fogFactor = 2.0f * smoothstep( 0.3f, 0.6f, i.fogFactor ); + + float4 result = vBase * vCloudAlpha; + result.a *= fogFactor; + + // No actual fog. Use the "fog factor" to modulate alpha (after some smoothstep mojo) + return FinalOutput( result, 1.0f, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} diff --git a/mp/src/materialsystem/stdshaders/cloud_vs11.vsh b/mp/src/materialsystem/stdshaders/cloud_vs11.vsh new file mode 100644 index 00000000..6348937e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud_vs11.vsh @@ -0,0 +1,26 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..0" + +#include "macros.vsh" + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); +; $worldPos unused, for above water, range fog calcs +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); +&FreeRegister( \$worldPos ); + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 oT1.x, $vTexCoord1, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord1, $SHADER_SPECIFIC_CONST_3 + diff --git a/mp/src/materialsystem/stdshaders/cloud_vs20.fxc b/mp/src/materialsystem/stdshaders/cloud_vs20.fxc new file mode 100644 index 00000000..3655e9fa --- /dev/null +++ b/mp/src/materialsystem/stdshaders/cloud_vs20.fxc @@ -0,0 +1,37 @@ +#include "common_vs_fxc.h" + +const float4 g_matBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_matCloudTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseCoords : TEXCOORD0; + float2 cloudAlphaCoords : TEXCOORD1; + float fogFactor : TEXCOORD2; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + o.projPos = mul( v.vPos, cModelViewProj ); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.fogFactor = CalcFog( vWorldPos, o.projPos, FOGTYPE_RANGE ); + + // Texture coordinate transforms + o.baseCoords.x = dot( v.vTexCoord0.xyzw, g_matBaseTexCoordTransform[0] ); + o.baseCoords.y = dot( v.vTexCoord0.xyzw, g_matBaseTexCoordTransform[1] ); + o.cloudAlphaCoords.x = dot( v.vTexCoord1.xyzw, g_matCloudTexCoordTransform[0] ); + o.cloudAlphaCoords.y = dot( v.vTexCoord1.xyzw, g_matCloudTexCoordTransform[1] ); + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/debugdepth.cpp b/mp/src/materialsystem/stdshaders/debugdepth.cpp new file mode 100644 index 00000000..65e55e0c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugdepth.cpp @@ -0,0 +1,113 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/cshader.h" +#include "convar.h" +#include "debugdrawdepth_vs20.inc" +#include "debugdrawdepth_ps20.inc" +#include "debugdrawdepth_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_debugdepthmode( "mat_debugdepthmode", "0" ); +static ConVar mat_debugdepthval( "mat_debugdepthval", "128.0f" ); +static ConVar mat_debugdepthvalmax( "mat_debugdepthvalmax", "256.0f" ); + +BEGIN_SHADER_FLAGS( DebugDepth, "Help for DebugDepth", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { +// Assert( 0 ); + return "WireFrame"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + SET_STATIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawdepth_ps20b ); + SET_STATIC_PIXEL_SHADER( debugdrawdepth_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawdepth_ps20 ); + SET_STATIC_PIXEL_SHADER( debugdrawdepth_ps20 ); + } + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, s_pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + + Vector4D vecZFilter( 0, 0, 0, 1 ); + int nDepthMode = mat_debugdepthmode.GetInt(); + if ( nDepthMode > 1 ) + { + nDepthMode = 0; + } + + vecZFilter[nDepthMode] = 1; + s_pShaderAPI->SetPixelShaderConstant( 1, vecZFilter.Base() ); + + Vector4D vecModulationColor( 0, 0, 0, 1 ); + if ( IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) + { + vecModulationColor[0] = 0; + vecModulationColor[1] = 1; + vecModulationColor[2] = 1; + } + else + { + vecModulationColor[0] = 1; + vecModulationColor[1] = 1; + vecModulationColor[2] = 1; + } + s_pShaderAPI->SetPixelShaderConstant( 2, vecModulationColor.Base() ); + + float flDepthFactor = mat_debugdepthval.GetFloat(); + float flDepthFactorMax = mat_debugdepthvalmax.GetFloat(); + if ( flDepthFactor == 0 ) + { + flDepthFactor = 1.0f; + } + Vector4D vecZFactor( (flDepthFactorMax - flDepthFactor), flDepthFactor, 1, 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vecZFactor.Base() ); + } + Draw(); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/debugluxel.cpp b/mp/src/materialsystem/stdshaders/debugluxel.cpp new file mode 100644 index 00000000..b3135fcb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugluxel.cpp @@ -0,0 +1,140 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/cshader.h" + +#define USE_NEW_SHADER //Updating assembly shaders to fxc, this is for A/B testing. + +#ifdef USE_NEW_SHADER + +#include "unlitgeneric_vs20.inc" +#include "unlitgeneric_ps20.inc" +#include "unlitgeneric_ps20b.inc" + +#endif + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( DebugLuxels, "Help for DebugLuxels", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( NOSCALE, SHADER_PARAM_TYPE_BOOL, "0", "fixme" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } +#endif +} + +SHADER_INIT +{ + LoadTexture( BASETEXTURE ); +} + +SHADER_DRAW +{ + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + if (IS_FLAG_SET(MATERIAL_VAR_TRANSLUCENT)) + { + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + else + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + bool bVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bVertexColor ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } +#endif + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + int texCoordScaleX = 1, texCoordScaleY = 1; + if (!params[NOSCALE]->GetIntValue()) + { + pShaderAPI->GetLightmapDimensions( &texCoordScaleX, &texCoordScaleY ); + } + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + float vVertexColor[4] = { IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, vVertexColor, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + + //texture scale transform + Vector4D transformation[2]; + transformation[0].Init( (float)texCoordScaleX, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, (float)texCoordScaleY, 0.0f, 0.0f ); + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, transformation[0].Base(), 2 ); + } + else +#endif + { + if (!params[NOSCALE]->GetIntValue()) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE0 ); + pShaderAPI->LoadIdentity( ); + pShaderAPI->ScaleXY( texCoordScaleX, texCoordScaleY ); + } + } + } + Draw(); +} +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/debugmodifyvertex.cpp b/mp/src/materialsystem/stdshaders/debugmodifyvertex.cpp new file mode 100644 index 00000000..c497ca95 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmodifyvertex.cpp @@ -0,0 +1,93 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This is an example of a material that modifies vertex data +// in the shader. NOTE: Every pass is given a clean set of vertex data. +// Modifications made in the first pass are *not* carried over to the next pass +// Modifications must take place during the DYNAMIC_STATE block. +// Use the function MeshBuilder() to build the mesh +// +// Also note: Using thie feature is *really expensive*! It makes a copy of +// the vertex data *per pass!* If you wish to modify vertex data to be used +// with all passes, your best bet is to construct a dynamic mesh instead. +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( DebugModifyVertex, "Help for DebugModifyVertex", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( WAVE, SHADER_PARAM_TYPE_FLOAT, "1.0", "wave amplitude" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + if( g_pHardwareConfig->GetSamplerCount() >= 2 ) + { + // lightmap + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableVertexDataPreprocess( true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float amp = params[WAVE]->GetFloatValue(); + float currTime = pShaderAPI->CurrentTime(); + for (int i = 0; i < MeshBuilder()->NumVertices(); ++i) + { + float const* pPos = MeshBuilder()->Position(); + MeshBuilder()->Position3f( pPos[0] + amp * sin( currTime + pPos[2] / 4 ), + pPos[1] + amp * sin( currTime + pPos[2] / 4 + 2 * 3.14 / 3 ), + pPos[2] + amp * sin( currTime + pPos[2] / 4 + 4 * 3.14 / 3 ) ); + MeshBuilder()->AdvanceVertex(); + } + } + Draw(); + + // base * vertex color + SHADOW_STATE + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | + SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Notice here that since we didn't modify the position, and this is a second + // pass, the position has been reset to it's initial, unmodified position + float currTime = pShaderAPI->CurrentTime(); + for (int i = 0; i < MeshBuilder()->NumVertices(); ++i) + { + float const* pPos = MeshBuilder()->Position(); + MeshBuilder()->Color3f( ( sin( currTime + pPos[0] ) + 1.0F) * 0.5, + ( sin( currTime + pPos[1] ) + 1.0F) * 0.5, + ( sin( currTime + pPos[2] ) + 1.0F) * 0.5 ); + MeshBuilder()->AdvanceVertex(); + } + } + Draw(); + } + else + { + ShaderWarning( "DebugModifyVertex: not " + "implemented for single-texturing hardware\n" ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp b/mp/src/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp new file mode 100644 index 00000000..2f5c6a8e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp @@ -0,0 +1,64 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "debugmorphaccumulator_ps30.inc" +#include "debugmorphaccumulator_vs30.inc" + +BEGIN_VS_SHADER_FLAGS( DebugMorphAccumulator, "Help for Debug Morph Accumulator", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableCulling( false ); + pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + SET_STATIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + SET_STATIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + } + Draw( ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc b/mp/src/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc new file mode 100644 index 00000000..b479085c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc @@ -0,0 +1,16 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 vTexCoord : TEXCOORD0; +}; + +sampler MorphAccumulator : register( s0 ); + +HALF4 main( PS_INPUT i ) : COLOR +{ + float4 vDeltas = tex2D( MorphAccumulator, i.vTexCoord ); + return float4( abs( vDeltas.x ), abs( vDeltas.z ), abs( vDeltas.y ) + abs( vDeltas.w ), 1.0f ); +} + diff --git a/mp/src/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc b/mp/src/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc new file mode 100644 index 00000000..4ff8a742 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc @@ -0,0 +1,23 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos = mul( v.vPos, cModelViewProj ); + o.vTexCoord = v.vTexCoord; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/debugmrttexture.cpp b/mp/src/materialsystem/stdshaders/debugmrttexture.cpp new file mode 100644 index 00000000..04a1128e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmrttexture.cpp @@ -0,0 +1,86 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "debugmrttexture_ps20.inc" +#include "debugmrttexture_ps20b.inc" +#include "debugmrttexture_vs20.inc" + +BEGIN_VS_SHADER_FLAGS( DebugMRTTexture, "Help for DebugMRTTexture", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( MRTINDEX, SHADER_PARAM_TYPE_INTEGER, "", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { +// if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) +// { +// return "UnlitGeneric_DX8"; +// } + return 0; + } + + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + DECLARE_STATIC_VERTEX_SHADER( debugmrttexture_vs20 ); + SET_STATIC_VERTEX_SHADER( debugmrttexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugmrttexture_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( MRTINDEX, params[MRTINDEX]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( debugmrttexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugmrttexture_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( MRTINDEX, params[MRTINDEX]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( debugmrttexture_ps20 ); + } + + int numTexCoords = 2; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, numTexCoords, 0, 0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugmrttexture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( debugmrttexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20 ); + } + } + Draw(); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/debugmrttexture_ps2x.fxc b/mp/src/materialsystem/stdshaders/debugmrttexture_ps2x.fxc new file mode 100644 index 00000000..7764e529 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmrttexture_ps2x.fxc @@ -0,0 +1,26 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "MRTINDEX" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +sampler BaseTextureSampler1 : register( s0 ); +sampler BaseTextureSampler2 : register( s1 ); + +float4 main( PS_INPUT i ) : COLOR +{ +#if MRTINDEX == 0 + float4 result = tex2D( BaseTextureSampler1, i.baseTexCoord ); +#else + float4 result = tex2D( BaseTextureSampler2, i.baseTexCoord ); +#endif + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/mp/src/materialsystem/stdshaders/debugmrttexture_vs20.fxc b/mp/src/materialsystem/stdshaders/debugmrttexture_vs20.fxc new file mode 100644 index 00000000..db5c4863 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugmrttexture_vs20.fxc @@ -0,0 +1,29 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 projPos; + float3 worldPos; + + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + + o.baseTexCoord = v.vBaseTexCoord; + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/debugnormalmap.cpp b/mp/src/materialsystem/stdshaders/debugnormalmap.cpp new file mode 100644 index 00000000..0be5246a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugnormalmap.cpp @@ -0,0 +1,148 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#define USE_NEW_SHADER //Updating assembly shaders to fxc, this is for A/B testing. + + + +#ifdef USE_NEW_SHADER + +#include "unlitgeneric_vs20.inc" +#include "unlitgeneric_ps20.inc" +#include "unlitgeneric_ps20b.inc" + +#endif + +#include "unlitgeneric_vs11.inc" + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( DebugNormalMap, "Help for DebugNormalMap", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldDiffuseBumpMap_bump", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + { +// Assert( 0 ); + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } + else +#endif + { + unlitgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( false ); + vshIndex.SetSEPARATEDETAILUVS( false ); + pShaderShadow->SetVertexShader( "unlitgeneric_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "unlitgeneric" ); + } + } + DYNAMIC_STATE + { + if ( params[BUMPMAP]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + float vVertexColor[4] = { 0, 0, 0, 0 }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, vVertexColor, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } + else +#endif + { + unlitgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/debugsoftwarevertexshader.cpp b/mp/src/materialsystem/stdshaders/debugsoftwarevertexshader.cpp new file mode 100644 index 00000000..be7cedf3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugsoftwarevertexshader.cpp @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ) +{ + float t = pShaderAPI->CurrentTime(); + for( int i = 0; i < meshBuilder.NumVertices(); i++ ) + { + const float *pPos = meshBuilder.Position(); + meshBuilder.Position3f( pPos[0], pPos[1], pPos[2] + 10.0f * sin( t + pPos[0] ) ); + meshBuilder.AdvanceVertex(); + } +} + +FORWARD_DECLARE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + +BEGIN_SHADER_FLAGS( DebugSoftwareVertexShader, "blah", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/basetexture", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( FRAME, SHADER_PARAM_TYPE_INTEGER, "0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() ) + { + USE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + } + else + { + USE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + } + } + SHADER_DRAW + { + SHADOW_STATE + { + } + DYNAMIC_STATE + { + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/debugtangentspace.cpp b/mp/src/materialsystem/stdshaders/debugtangentspace.cpp new file mode 100644 index 00000000..30279012 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugtangentspace.cpp @@ -0,0 +1,133 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +#define USE_NEW_SHADER //Updating assembly shaders to fxc, this is for A/B testing. + +#ifdef USE_NEW_SHADER +#include "debugtangentspace_vs11.inc" +#include "debugtangentspace_vs20.inc" +#include "unlitgeneric_notexture_ps11.inc" +#include "unlitgeneric_notexture_ps20.inc" +#include "unlitgeneric_notexture_ps20b.inc" + +#else +#include "debugtangentspace.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( DebugTangentSpace, "Help for DebugTangentSpace" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/basetexture", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( FRAME, SHADER_PARAM_TYPE_INTEGER, "0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + if (g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 0; + int userDataSize = 4; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + DECLARE_STATIC_VERTEX_SHADER( debugtangentspace_vs20 ); + SET_STATIC_VERTEX_SHADER( debugtangentspace_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + } + } + else + { + DECLARE_STATIC_VERTEX_SHADER( debugtangentspace_vs11 ); + SET_STATIC_VERTEX_SHADER( debugtangentspace_vs11 ); + + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + } +#else + debugtangentspace_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "DebugTangentSpace", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "UnlitGeneric_NoTexture" ); +#endif + } + DYNAMIC_STATE + { + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + } + } + else // legacy hardware + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs11 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs11 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + } +#else + debugtangentspace_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); +#endif + } + Draw(); + } + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/debugtangentspace.vsh b/mp/src/materialsystem/stdshaders/debugtangentspace.vsh new file mode 100644 index 00000000..cb38a23b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugtangentspace.vsh @@ -0,0 +1,34 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +&FreeRegister( \$worldPos ); + +; stick the normal in the color channel +mov oD0.xyz, $worldNormal.xyz +mov oD0.w, $cOne ; make sure all components are defined + +&FreeRegister( \$projPos ); +&FreeRegister( \$worldNormal ); diff --git a/mp/src/materialsystem/stdshaders/debugtangentspace_vs11.fxc b/mp/src/materialsystem/stdshaders/debugtangentspace_vs11.fxc new file mode 100644 index 00000000..1584ef26 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugtangentspace_vs11.fxc @@ -0,0 +1,51 @@ +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float3 vNormal : NORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, v.vPos, v.vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // stick the normal in the color channel + o.vDiffuse.rgb = worldNormal; + o.vDiffuse.a = 1.0f; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/debugtangentspace_vs20.fxc b/mp/src/materialsystem/stdshaders/debugtangentspace_vs20.fxc new file mode 100644 index 00000000..f829bde9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/debugtangentspace_vs20.fxc @@ -0,0 +1,55 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, v.vPos, vObjNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // stick the normal in the color channel + o.vDiffuse.rgb = worldNormal; + o.vDiffuse.a = 1.0f; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc b/mp/src/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc new file mode 100644 index 00000000..61daa238 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc @@ -0,0 +1,11 @@ +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float projPosZ : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( float4( 0, 0, 0, 1.0f ), 0.0f, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE, true, i.projPosZ ); +} diff --git a/mp/src/materialsystem/stdshaders/depthtodestalpha_vs20.fxc b/mp/src/materialsystem/stdshaders/depthtodestalpha_vs20.fxc new file mode 100644 index 00000000..9891502e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/depthtodestalpha_vs20.fxc @@ -0,0 +1,23 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float projPosZ : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos = mul( v.vPos, cModelViewProj ); + o.projPosZ = o.vProjPos.z; + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/depthwrite.cpp b/mp/src/materialsystem/stdshaders/depthwrite.cpp new file mode 100644 index 00000000..06d7690f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/depthwrite.cpp @@ -0,0 +1,207 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "depthwrite_ps20.inc" +#include "depthwrite_ps20b.inc" +#include "depthwrite_vs20.inc" + +#if !defined( _X360 ) +#include "depthwrite_ps30.inc" +#include "depthwrite_vs30.inc" +#endif + +BEGIN_VS_SHADER_FLAGS( DepthWrite, "Help for Depth Write", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "", "Alpha reference value" ) + SHADER_PARAM( COLOR_DEPTH, SHADER_PARAM_TYPE_BOOL, "0", "Write depth as color") + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Wireframe"; + } + return 0; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + bool bAlphaClip = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ); + int nColorDepth = GetIntParam( COLOR_DEPTH, params, 0 ); + + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( nColorDepth == 0 ) + { + // Bias primitives when rendering into shadow map so we get slope-scaled depth bias + // rather than having to apply a constant bias in the filtering shader later + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_SHADOW_BIAS ); + } + + // Turn off writes to color buffer since we always sample shadows from the DEPTH texture later + // This gives us double-speed fill when rendering INTO the shadow map + pShaderShadow->EnableColorWrites( ( nColorDepth == 1 ) ); + pShaderShadow->EnableAlphaWrites( false ); + + // Don't backface cull unless alpha clipping, since this can cause artifacts when the + // geometry is clipped by the flashlight near plane + // If a material was already marked nocull, don't cull it + pShaderShadow->EnableCulling( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) && !IS_FLAG_SET(MATERIAL_VAR_NOCULL) ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( depthwrite_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ONLY_PROJECT_POSITION, !bAlphaClip && IsX360() && !nColorDepth ); //360 needs to know if it *shouldn't* output texture coordinates to avoid shader patches + SET_STATIC_VERTEX_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_VERTEX_SHADER( depthwrite_vs20 ); + + if ( bAlphaClip || g_pHardwareConfig->PlatformRequiresNonNullPixelShaders() || nColorDepth ) + { + if( bAlphaClip ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps20 ); + } + } + } +#ifndef _X360 + else + { + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( depthwrite_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( ONLY_PROJECT_POSITION, 0 ); //360 only combo, and this is a PC path + SET_STATIC_VERTEX_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_VERTEX_SHADER( depthwrite_vs30 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps30 ); + } +#endif + } + DYNAMIC_STATE + { + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + depthwrite_vs20_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetCOMPRESSED_VERTS( (int)vertexCompression ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if ( bAlphaClip ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float vAlphaThreshold[4] = {0.7f, 0.7f, 0.7f, 0.7f}; + if ( ALPHATESTREFERENCE != -1 && ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) ) + { + vAlphaThreshold[0] = vAlphaThreshold[1] = vAlphaThreshold[2] = vAlphaThreshold[3] = params[ALPHATESTREFERENCE]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vAlphaThreshold, 1 ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps20 ); + } + } +#ifndef _X360 + else // 3.0 shader case (PC only) + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + depthwrite_vs30_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetMORPHING( pShaderAPI->IsHWMorphingEnabled() ); + vshIndex.SetCOMPRESSED_VERTS( (int)vertexCompression ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if ( bAlphaClip ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float vAlphaThreshold[4] = {0.7f, 0.7f, 0.7f, 0.7f}; + if ( ALPHATESTREFERENCE != -1 && ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) ) + { + vAlphaThreshold[0] = vAlphaThreshold[1] = vAlphaThreshold[2] = vAlphaThreshold[3] = params[ALPHATESTREFERENCE]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vAlphaThreshold, 1 ); + } + + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps30 ); + } +#endif + + Vector4D vParms; + + // set up arbitrary far planes, as the real ones are too far ( 30,000 ) +// pShaderAPI->SetPSNearAndFarZ( 1 ); + vParms.x = 7.0f; // arbitrary near + vParms.y = 4000.0f; // arbitrary far + vParms.z = 0.0f; + vParms.w = 0.0f; + pShaderAPI->SetPixelShaderConstant( 1, vParms.Base(), 2 ); + + } // DYNAMIC_STATE + + Draw( ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/depthwrite_ps2x.fxc b/mp/src/materialsystem/stdshaders/depthwrite_ps2x.fxc new file mode 100644 index 00000000..1baabcf3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/depthwrite_ps2x.fxc @@ -0,0 +1,44 @@ +// STATIC: "COLOR_DEPTH" "0..1" + +// DYNAMIC: "ALPHACLIP" "0..1" + +const float g_AlphaThreshold : register( c0 ); + +const float2 g_vNearFarPlanes : register( c1 ); + #define g_flNearPlane g_vNearFarPlanes.x + #define g_flFarPlane g_vNearFarPlanes.y + +struct PS_INPUT +{ +#if ALPHACLIP + float2 texCoord0 : TEXCOORD0; +#endif + +#if COLOR_DEPTH + float4 vWorldPos_projPosZ : TEXCOORD1; +#endif +}; + +sampler BaseTextureSampler : register( s0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float4 color = float4( 1, 0, 0, 1 ); // opaque alpha....the color doesn't matter for this shader + +#if ALPHACLIP + color = tex2D( BaseTextureSampler, i.texCoord0 ); + + clip( color.a - g_AlphaThreshold ); + +#endif + +#if ( COLOR_DEPTH == 1 ) + + return float4( i.vWorldPos_projPosZ.w / g_flFarPlane, 0.0, 0.0, 1.0 ); + +#else + + return color; + +#endif +} diff --git a/mp/src/materialsystem/stdshaders/depthwrite_vs20.fxc b/mp/src/materialsystem/stdshaders/depthwrite_vs20.fxc new file mode 100644 index 00000000..f98e40e2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/depthwrite_vs20.fxc @@ -0,0 +1,83 @@ +// STATIC: "ONLY_PROJECT_POSITION" "0..1" [XBOX] +// STATIC: "ONLY_PROJECT_POSITION" "0..0" [PC] +// STATIC: "COLOR_DEPTH" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord : TEXCOORD0; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + + // Position delta stream + float3 vPosFlex : POSITION1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + +#if (ONLY_PROJECT_POSITION == 0) //360 sometimes runs without the pixel shader component, but has to patch this output if it does. + float2 texCoord : TEXCOORD0; +#endif + +#if COLOR_DEPTH + float4 vWorldPos_projPosZ : TEXCOORD1; +#endif + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + float3 vWorldPos; + float4 vPosition = v.vPos; + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, float3(0, 0, 0), vPosition.xyz ); +#endif + + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, vWorldPos ); + + float4 vProjPos = mul( float4( vWorldPos, 1.0f ), cViewProj ); + + o.vProjPos = vProjPos; + +#if (ONLY_PROJECT_POSITION == 0) + o.texCoord = v.vTexCoord; +#endif + +#if ( COLOR_DEPTH && !ONLY_PROJECT_POSITION ) + o.vWorldPos_projPosZ.z = vProjPos.z; + o.vWorldPos_projPosZ.w = vProjPos.w; +#endif + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/detail.cpp b/mp/src/materialsystem/stdshaders/detail.cpp new file mode 100644 index 00000000..956bf518 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/detail.cpp @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Detail, "Help for Detail" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_FALLBACK + { + return "UnlitGeneric"; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + } + +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/detail_ps11.psh b/mp/src/materialsystem/stdshaders/detail_ps11.psh new file mode 100644 index 00000000..fb5916ab --- /dev/null +++ b/mp/src/materialsystem/stdshaders/detail_ps11.psh @@ -0,0 +1,12 @@ +ps.1.1 + +tex t0 +tex t1 + +mul r0.rgb, t0, v0 + + +; handle distance fade +sub r0.a, t0.a, 1-v0.a + +sub r0.a, r0.a, t1_bias.a +cnd r0.a, r0.a, c0.a, c1.a diff --git a/mp/src/materialsystem/stdshaders/detail_vs11.vsh b/mp/src/materialsystem/stdshaders/detail_vs11.vsh new file mode 100644 index 00000000..28dee2fd --- /dev/null +++ b/mp/src/materialsystem/stdshaders/detail_vs11.vsh @@ -0,0 +1,56 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 +mov $worldPos.w, $cOne + + +;------------------------------------------------------------------------------ +; Transform the position from world to proj space +;------------------------------------------------------------------------------ +&AllocateRegister( \$projPos ); +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$worldPos ); + + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +mov oT0.xy, $vTexCoord0.xy + +; special case perspective correct texture projection so that the texture fits exactly on the screen +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_0.w +add $projPos.xy, $projPos.xy, $projPos.w +mul $projPos.xy, $projPos.xy, $cHalf +mul $projPos.xy, $projPos.xy, $SHADER_SPECIFIC_CONST_0.xy +mad $projPos.xy, $projPos.w, $SHADER_SPECIFIC_CONST_1.xy, $projPos.xy + +mov oT1.xy, $projPos.xy +mov oT1.z, $projPos.w +mov oT1.w, $projPos.w + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Modulation color +;------------------------------------------------------------------------------ +mov oD0, $vColor diff --git a/mp/src/materialsystem/stdshaders/eye_refract.cpp b/mp/src/materialsystem/stdshaders/eye_refract.cpp new file mode 100644 index 00000000..87528028 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eye_refract.cpp @@ -0,0 +1,253 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "eye_refract_helper.h" +#include "cloak_blended_pass_helper.h" +#include "emissive_scroll_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( EyeRefract, EyeRefract_dx9 ) +BEGIN_VS_SHADER( EyeRefract_dx9, "Help for Eyes" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( CORNEATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "cornea texture" ) + SHADER_PARAM( AMBIENTOCCLTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "reflection texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Pupil dilation (0 is none, 1 is maximal)" ) + SHADER_PARAM( GLOSSINESS, SHADER_PARAM_TYPE_FLOAT, "1", "Glossiness of eye (1 is default, 0 is not glossy at all)" ) + SHADER_PARAM( SPHERETEXKILLCOMBO, SHADER_PARAM_TYPE_BOOL, "1", "texkill pixels not on sphere" ) + SHADER_PARAM( RAYTRACESPHERE, SHADER_PARAM_TYPE_BOOL, "1", "Raytrace sphere" ) + SHADER_PARAM( PARALLAXSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Parallax strength" ) + SHADER_PARAM( CORNEABUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Cornea strength" ) + + SHADER_PARAM( AMBIENTOCCLCOLOR, SHADER_PARAM_TYPE_VEC3, "[1 1 1]", "Ambient occlusion color" ) + SHADER_PARAM( EYEBALLRADIUS, SHADER_PARAM_TYPE_FLOAT, "0", "Eyeball radius for ray casting" ) + + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + END_SHADER_PARAMS + + void SetupVarsEyeRefract( Eye_Refract_Vars_t &info ) + { + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nDilation = DILATION; + info.m_nGlossiness = GLOSSINESS; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + info.m_nCorneaTexture = CORNEATEXTURE; + info.m_nAmbientOcclTexture = AMBIENTOCCLTEXTURE; + info.m_nEnvmap = ENVMAP; + info.m_nSphereTexKillCombo = SPHERETEXKILLCOMBO; + info.m_nRaytraceSphere = RAYTRACESPHERE; + info.m_nParallaxStrength = PARALLAXSTRENGTH; + info.m_nCorneaBumpStrength = CORNEABUMPSTRENGTH; + info.m_nAmbientOcclColor = AMBIENTOCCLCOLOR; + info.m_nEyeballRadius = EYEBALLRADIUS; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = IRIS; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + } + + SHADER_INIT_PARAMS() + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + InitParams_Eyes_Refract( this, params, pMaterialName, info ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Eyes_dx8"; + } + + return 0; + } + + SHADER_INIT + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Init_Eyes_Refract( this, params, info ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardEye = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardEye = false; + } + } + + // Standard rendering pass + if ( bDrawStandardEye ) + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Draw_Eyes_Refract( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/eye_refract_helper.cpp b/mp/src/materialsystem/stdshaders/eye_refract_helper.cpp new file mode 100644 index 00000000..af4d2c08 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eye_refract_helper.cpp @@ -0,0 +1,461 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "eye_refract_helper.h" + +#include "cpp_shader_constant_register_map.h" + +#include "eyes_flashlight_vs11.inc" +#include "eyes_flashlight_ps11.inc" + +#include "eye_refract_vs20.inc" +#include "eye_refract_ps20.inc" +#include "eye_refract_ps20b.inc" + +#ifndef _X360 +#include "eye_refract_vs30.inc" +#include "eye_refract_ps30.inc" +#endif + +#include "convar.h" + +static ConVar r_lightwarpidentity( "r_lightwarpidentity","0", FCVAR_CHEAT ); + +void InitParams_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eye_Refract_Vars_t &info ) +{ + // FLASHLIGHTFIXME + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // Set material parameter default values + if ( ( info.m_nIntro >= 0 ) && ( !params[info.m_nIntro]->IsDefined() ) ) + { + params[info.m_nIntro]->SetIntValue( kDefaultIntro ); + } + + if ( ( info.m_nDilation >= 0 ) && ( !params[info.m_nDilation]->IsDefined() ) ) + { + params[info.m_nDilation]->SetFloatValue( kDefaultDilation ); + } + + if ( ( info.m_nGlossiness >= 0 ) && ( !params[info.m_nGlossiness]->IsDefined() ) ) + { + params[info.m_nGlossiness]->SetFloatValue( kDefaultGlossiness ); + } + + if ( ( info.m_nSphereTexKillCombo >= 0 ) && ( !params[info.m_nSphereTexKillCombo]->IsDefined() ) ) + { + params[info.m_nSphereTexKillCombo]->SetIntValue( kDefaultSphereTexKillCombo ); + } + + if ( ( info.m_nRaytraceSphere >= 0 ) && ( !params[info.m_nRaytraceSphere]->IsDefined() ) ) + { + params[info.m_nRaytraceSphere]->SetIntValue( kDefaultRaytraceSphere ); + } + + if ( ( info.m_nAmbientOcclColor >= 0 ) && ( !params[info.m_nAmbientOcclColor]->IsDefined() ) ) + { + params[info.m_nAmbientOcclColor]->SetVecValue( kDefaultAmbientOcclColor, 4 ); + } + + if ( ( info.m_nEyeballRadius >= 0 ) && ( !params[info.m_nEyeballRadius]->IsDefined() ) ) + { + params[info.m_nEyeballRadius]->SetFloatValue( kDefaultEyeballRadius ); + } + + if ( ( info.m_nParallaxStrength >= 0 ) && ( !params[info.m_nParallaxStrength]->IsDefined() ) ) + { + params[info.m_nParallaxStrength]->SetFloatValue( kDefaultParallaxStrength ); + } + + if ( ( info.m_nCorneaBumpStrength >= 0 ) && ( !params[info.m_nCorneaBumpStrength]->IsDefined() ) ) + { + params[info.m_nCorneaBumpStrength]->SetFloatValue( kDefaultCorneaBumpStrength ); + } +} + +void Init_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, Eye_Refract_Vars_t &info ) +{ + pShader->LoadTexture( info.m_nCorneaTexture ); // SHADER_SAMPLER0 (this is a normal, hence not sRGB) + pShader->LoadTexture( info.m_nIris, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER1 + pShader->LoadCubeMap( info.m_nEnvmap, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER2 + pShader->LoadTexture( info.m_nAmbientOcclTexture, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER3 + + if ( IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture ) ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); // SHADER_SAMPLER4 + } + + pShader->LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER5 +} + +void Draw_Eyes_Refract_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bDrawFlashlightAdditivePass, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bDiffuseWarp = IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture ); + bool bIntro = IS_PARAM_DEFINED( info.m_nIntro ) ? ( params[info.m_nIntro]->GetIntValue() ? true : false ) : false; + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Cornea normal + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Cube reflection + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Ambient occlusion + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( bDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Light warp + } + + int nShadowFilterMode = 0; + if ( bDrawFlashlightAdditivePass == true ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + pShaderShadow->EnableDepthWrites( false ); + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Write over the eyes that were already there + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Flashlight cookie + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eye_refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false ); + bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false ); + + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps20b ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER6 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Noise map + } + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eye_refract_vs30 ); + + bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false ); + bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false ); + + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps30 ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Shadow depth map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Noise map + } + } +#endif + + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); // Cube map reflection + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Ambient occlusion + pShaderShadow->EnableSRGBWrite( true ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); // Flashlight cookie + } + + // Fog + if ( bDrawFlashlightAdditivePass == true ) + { + pShader->FogToBlack(); + } + else + { + pShader->FogToFogColor(); + } + } + DYNAMIC_STATE + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture = NULL; + FlashlightState_t flashlightState; + bool bFlashlightShadows = false; + if ( bDrawFlashlightAdditivePass == true ) + { + flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + } + + pShader->BindTexture( SHADER_SAMPLER0, info.m_nCorneaTexture ); // Cornea normal + pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nEnvmap ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nAmbientOcclTexture ); + + if ( bDiffuseWarp ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nDiffuseWarpTexture ); + } + } + + if ( bDrawFlashlightAdditivePass == true ) + pShader->BindTexture( SHADER_SAMPLER5, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + pShader->SetAmbientCubeDynamicStateVertexShader(); + + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV ); + + if ( bDrawFlashlightAdditivePass == true ) + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flashlightState.m_vecLightOrigin.Base(), 1 ); + + LightState_t lightState = { 0, false, false }; + if ( bDrawFlashlightAdditivePass == false ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 ); + } +#endif + + // Get luminance of ambient cube and saturate it + float fAverageAmbient = max(0.0f, min( pShaderAPI->GetAmbientLightCubeLuminance(), 1.0f ) ); + + // Special constant for DX9 eyes: { Dilation, Glossiness, x, x }; + float vPSConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPSConst[0] = IS_PARAM_DEFINED( info.m_nDilation ) ? params[info.m_nDilation]->GetFloatValue() : kDefaultDilation; + vPSConst[1] = IS_PARAM_DEFINED( info.m_nGlossiness ) ? params[info.m_nGlossiness]->GetFloatValue() : kDefaultGlossiness; + vPSConst[2] = fAverageAmbient; + vPSConst[3] = IS_PARAM_DEFINED( info.m_nCorneaBumpStrength ) ? params[info.m_nCorneaBumpStrength]->GetFloatValue() : kDefaultCorneaBumpStrength; + pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + pShaderAPI->SetPixelShaderConstant( 1, IS_PARAM_DEFINED( info.m_nEyeOrigin ) ? params[info.m_nEyeOrigin]->GetVecValue() : kDefaultEyeOrigin, 1 ); + pShaderAPI->SetPixelShaderConstant( 2, IS_PARAM_DEFINED( info.m_nIrisU ) ? params[info.m_nIrisU]->GetVecValue() : kDefaultIrisU, 1 ); + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_nIrisV ) ? params[info.m_nIrisV]->GetVecValue() : kDefaultIrisV, 1 ); + + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 4, vEyePos, 1 ); + pShaderAPI->SetPixelShaderConstant( 5, IS_PARAM_DEFINED( info.m_nAmbientOcclColor ) ? params[info.m_nAmbientOcclColor]->GetVecValue() : kDefaultAmbientOcclColor, 1 ); + + float vPackedConst6[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + //vPackedConst6[0] Unused + vPackedConst6[1] = IS_PARAM_DEFINED( info.m_nEyeballRadius ) ? params[info.m_nEyeballRadius]->GetFloatValue() : kDefaultEyeballRadius; + //vPackedConst6[2] = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? params[info.m_nRaytraceSphere]->GetFloatValue() : kDefaultRaytraceSphere; + vPackedConst6[3] = IS_PARAM_DEFINED( info.m_nParallaxStrength ) ? params[info.m_nParallaxStrength]->GetFloatValue() : kDefaultParallaxStrength; + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 ); + + float fPixelFogType = pShaderAPI->GetPixelFogCombo() == 1 ? 1 : 0; + + // Controls for lerp-style paths through shader code + float vShaderControls[4] = { fPixelFogType, 0, 0, 0 }; + pShaderAPI->SetPixelShaderConstant( 10, vShaderControls, 1 ); + + if ( bDrawFlashlightAdditivePass == true ) + { + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + if ( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER6, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_SHADOW_NOISE_2D ); + } + } + + // Flashlight tax +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b ); + } + else // ps.2.0 + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 ); + } +#endif + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + if ( bDrawFlashlightAdditivePass == true ) + { + float atten[4], pos[4], tweaks[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( 7, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( 8, pos, 1 ); + + //pShaderAPI->SetPixelShaderConstant( 9, worldToTexture.Base(), 4 ); + //10 + //11 + //12 + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture[0], 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, worldToTexture[1], 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, worldToTexture[2], 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, worldToTexture[3], 1 ); + + // Tweaks associated with a given flashlight + tweaks[0] = flashlightState.m_flShadowFilterSize / flashlightState.m_flShadowMapResolution; + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( 9, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + else // Lighting constants when not drawing flashlight + { + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + } + + // Intro tax + if ( bIntro ) + { + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + if ( IS_PARAM_DEFINED( info.m_nEntityOrigin ) ) + { + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, timeVec, 1 ); + } + } + pShader->Draw(); +} + + +extern ConVar r_flashlight_version2; +void Draw_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + Draw_Eyes_Refract_Internal( pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + Draw_Eyes_Refract_Internal( pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression ); +} diff --git a/mp/src/materialsystem/stdshaders/eye_refract_helper.h b/mp/src/materialsystem/stdshaders/eye_refract_helper.h new file mode 100644 index 00000000..ce62a33b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eye_refract_helper.h @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef EYE_REFRACT_HELPER_H +#define EYE_REFRACT_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Eye_Refract_Vars_t +{ + Eye_Refract_Vars_t() { memset( this, 0xFF, sizeof(Eye_Refract_Vars_t) ); } + + int m_nFrame; + int m_nIris; + int m_nIrisFrame; + int m_nEyeOrigin; + int m_nIrisU; + int m_nIrisV; + int m_nDilation; + int m_nGlossiness; + int m_nIntro; + int m_nEntityOrigin; // Needed for intro + int m_nWarpParam; + int m_nCorneaTexture; + int m_nAmbientOcclTexture; + int m_nEnvmap; + int m_nSphereTexKillCombo; + int m_nRaytraceSphere; + int m_nParallaxStrength; + int m_nCorneaBumpStrength; + int m_nAmbientOcclColor; + int m_nEyeballRadius; + int m_nDiffuseWarpTexture; +}; + +// Default values (Arrays should only be vec[4]) +static const int kDefaultIntro = 0; +static const float kDefaultEyeOrigin[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultIrisU[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultIrisV[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultDilation = 0.5f; +static const float kDefaultGlossiness = 1.0f; +static const float kDefaultWarpParam = 0.0f; +static const int kDefaultSphereTexKillCombo = 0; +static const int kDefaultRaytraceSphere = 0; +static const float kDefaultParallaxStrength = 0.25f; +static const float kDefaultCorneaBumpStrength = 1.0f; +static const float kDefaultAmbientOcclColor[4] = { 0.33f, 0.33f, 0.33f, 0.0f }; +static const float kDefaultEyeballRadius = 0.5f; + +void InitParams_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eye_Refract_Vars_t &info ); +void Init_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, Eye_Refract_Vars_t &info ); +void Draw_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EYES_DX8_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc b/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc new file mode 100644 index 00000000..da053d22 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc @@ -0,0 +1,494 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =========================== + +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" + +// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps20b] +// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps30] + +// STATIC: "RAYTRACESPHERE" "0..1" [ps20b] +// STATIC: "RAYTRACESPHERE" "0..1" [ps30] + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] + +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +// We don't use other lights when doing the flashlight +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps30] +// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps20b] + +// Debug 2.0 shader locally +//#ifdef SHADER_MODEL_PS_2_B +//#undef SHADER_MODEL_PS_2_B +//#define SHADER_MODEL_PS_2_0 +//#endif + + +// Includes ======================================================================================= +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +// Texture Samplers =============================================================================== +sampler g_tCorneaSampler : register( s0 ); +sampler g_tIrisSampler : register( s1 ); +sampler g_tEyeReflectionCubemapSampler : register( s2 ); +sampler g_tEyeAmbientOcclSampler : register( s3 ); +sampler g_tLightwarpSampler : register( s4 ); // 1D texture for TF NPR lighting + +sampler g_tFlashlightCookieSampler : register( s5 ); +sampler g_tFlashlightDepthSampler : register( s6 ); +sampler g_tRandomRotationSampler : register( s7 ); + +// Shaders Constants and Globals ================================================================== +const float4 g_vPackedConst0 : register( c0 ); +#define g_flDilationFactor g_vPackedConst0.x +#define g_flGlossiness g_vPackedConst0.y +#define g_flAverageAmbient g_vPackedConst0.z +#define g_flCorneaBumpStrength g_vPackedConst0.w + +const float3 g_vEyeOrigin : register( c1 ); +const float4 g_vIrisProjectionU : register( c2 ); +const float4 g_vIrisProjectionV : register( c3 ); +const float4 g_vCameraPosition : register( c4 ); +const float3 g_cAmbientOcclColor : register( c5 ); + +const float4 g_vPackedConst6 : register( c6 ); +#define g_flEyeballRadius g_vPackedConst6.y //0.51f +//#define g_bRaytraceSphere g_vPackedConst6.z //1.0f +#define g_flParallaxStrength g_vPackedConst6.w //0.25f + +// Flashlight constants +const float4 g_vFlashlightAttenuationFactors : register( c7 ); // FarZ in w +const float3 g_vFlashlightPos : register( c8 ); +const float4 g_vShadowTweaks : register( c9 ); +const float4 g_ShaderControls : register( c10 ); +#define g_fPixelFogType g_ShaderControls.x + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); + +PixelShaderLightInfo g_sLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0; + float4 cVertexLight : TEXCOORD1; // w is used for the flashlight pass + float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass) + float4 vWorldPosition_ProjPosZ : TEXCOORD3; + float3 vWorldNormal : TEXCOORD4; // World-space normal + float3 vWorldTangent : TEXCOORD5; // World-space tangent + float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights + float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights + + float3 vWorldBinormal : COLOR0; // World-space normal +}; + +// Ray sphere intersect returns distance along ray to intersection ================================ +float IntersectRaySphere ( float3 cameraPos, float3 ray, float3 sphereCenter, float sphereRadius) +{ + float3 dst = cameraPos.xyz - sphereCenter.xyz; + float B = dot(dst, ray); + float C = dot(dst, dst) - (sphereRadius * sphereRadius); + float D = B*B - C; + return (D > 0) ? (-B - sqrt(D)) : 0; +} + +// Calculate both types of Fog and lerp to get result +float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float fRangeFog = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + float fHeightFog = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + return lerp( fRangeFog, fHeightFog, fPixelFogType ); +} + +// Blend both types of Fog and lerp to get result +float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType ) +{ + pixelFogFactor = saturate( pixelFogFactor ); + float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + return lerp( fRangeResult, fHeightResult, fPixelFogType ); +} + +float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE ) +{ + float4 result = vShaderColor; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb *= LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb *= GAMMA_LIGHT_SCALE; + } + + result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType ); + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion + + return result; +} + + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Set bools to compile out code + bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + int nNumLights = FLASHLIGHT ? 1 : NUM_LIGHTS; // Flashlight is considered one light, otherwise, use numlights combo + +#if !defined( SHADER_MODEL_PS_2_0 ) + bool bRayCast = RAYTRACESPHERE ? true : false; + bool bRayCastTexKill = SPHERETEXKILLCOMBO ? true : false; +#endif + + float flFlashlightNDotL = i.vTangentViewVector.w; + float4 vFlashlightTexCoord = { 0.0f, 0.0f, 0.0f, 0.0f }; + if ( bFlashlight ) + { + vFlashlightTexCoord.xyzw = i.cVertexLight.xyzw; // This was hidden in this interpolator + i.cVertexLight.rgba = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + } + + // Interpolated vectors + float3 vWorldNormal = i.vWorldNormal.xyz; + float3 vWorldTangent = i.vWorldTangent.xyz; + float3 vWorldBinormal = ( i.vWorldBinormal.xyz * 2.0f ) - 1.0f; // normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) ); + + float3 vTangentViewVector = i.vTangentViewVector.xyz; + + // World position + float3 vWorldPosition = i.vWorldPosition_ProjPosZ.xyz; + + // World view vector to pixel + float3 vWorldViewVector = normalize( vWorldPosition.xyz - g_vCameraPosition.xyz ); + + //=================// + // TF NPR lighting // + //=================// + if ( bDoDiffuseWarp ) + { + // Replace the interpolated vertex light + if ( bFlashlight == true ) + { + // Deal with this below in the flashlight section + } + else + { + if ( nNumLights > 0 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.z ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 1 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.w ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 2 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.z ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 3 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.w ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ) * cWarpedLight.rgb; + } + } + } + + //==========================================================================================================// + // Ray cast against sphere representing eyeball to reduce artifacts from non-spherical morphed eye geometry // + //==========================================================================================================// +#if !defined( SHADER_MODEL_PS_2_0 ) + if ( bRayCast ) + { + float fSphereRayCastDistance = IntersectRaySphere( g_vCameraPosition.xyz, vWorldViewVector.xyz, g_vEyeOrigin.xyz, g_flEyeballRadius ); + vWorldPosition.xyz = g_vCameraPosition.xyz + ( vWorldViewVector.xyz * fSphereRayCastDistance ); + if (fSphereRayCastDistance == 0) + { + if ( bRayCastTexKill ) + clip(-1); // texkill to get a better silhouette + vWorldPosition.xyz = g_vEyeOrigin.xyz + ( vWorldNormal.xyz * g_flEyeballRadius ); + } + } +#endif + + //=================================// + // Generate sphere and cornea uv's // + //=================================// +#if !defined( SHADER_MODEL_PS_2_0 ) + float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture + vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) ); + vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) ); + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; +#else // ps_20 + float2 vCorneaUv = i.vAmbientOcclUv_fallbackCorneaUv.wz; // Note: Cornea texture is a cropped version of the iris texture + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; +#endif + + //=================================// + // Hacked parallax mapping on iris // + //=================================// + float fIrisOffset = tex2D( g_tCorneaSampler, vCorneaUv.xy ).b; + +#if !defined( SHADER_MODEL_PS_2_0 ) + float2 vParallaxVector = ( ( vTangentViewVector.xy * fIrisOffset * g_flParallaxStrength ) / ( 1.0f - vTangentViewVector.z ) ); // Note: 0.25 is a magic number + vParallaxVector.x = -vParallaxVector.x; //Need to flip x...not sure why. + //vParallaxVector.x *= -1.0; //Need to flip x...not sure why. + //vParallaxVector = 0.0f; //Disable parallax for debugging +#else // Disable parallax effect in 2.0 version + float2 vParallaxVector = { 0.0f, 0.0f }; +#endif + + float2 vIrisUv = vSphereUv.xy - vParallaxVector.xy; + + // Note: We fetch from this texture twice right now with different uv's for the color and alpha + float2 vCorneaNoiseUv = vSphereUv.xy + ( vParallaxVector.xy * 0.5 ); + float fCorneaNoise = tex2D( g_tIrisSampler, vCorneaNoiseUv.xy ).a; + + //===============// + // Cornea normal // + //===============// + // Sample 2D normal from texture + float3 vCorneaTangentNormal = { 0.0, 0.0, 1.0 }; + float4 vCorneaSample = tex2D( g_tCorneaSampler, vCorneaUv.xy ); + vCorneaTangentNormal.xy = vCorneaSample.rg - 0.5f; // Note: This scales the bump to 50% strength + + // Scale strength of normal + vCorneaTangentNormal.xy *= g_flCorneaBumpStrength; + + // Add in surface noise and imperfections (NOTE: This should be baked into the normal map!) + vCorneaTangentNormal.xy += fCorneaNoise * 0.1f; + + // Normalize tangent vector +#if !defined( SHADER_MODEL_PS_2_0 ) + // Since this isn't used later in 2.0, skip the normalize to save shader instructions + vCorneaTangentNormal.xyz = normalize( vCorneaTangentNormal.xyz ); +#endif + + // Transform into world space + float3 vCorneaWorldNormal = Vec3TangentToWorldNormalized( vCorneaTangentNormal.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + //============// + // Flashlight // + //============// + float3 vFlashlightVector = { 0.0f, 0.0f, 0.0f }; + float3 cFlashlightColorFalloff = { 0.0f, 0.0f, 0.0f }; + if ( bFlashlight == true ) + { + // Flashlight vector + vFlashlightVector.xyz = normalize( g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz ); + + // Distance attenuation for flashlight and to fade out shadow over distance + float3 vDelta = g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz; + float flDistSquared = dot( vDelta, vDelta ); + float flDist = sqrt( flDistSquared ); + float flFlashlightAttenuation = dot( g_vFlashlightAttenuationFactors.xyz, float3( 1.0f, 1.0f/flDist, 1.0f/flDistSquared ) ); + + // Flashlight cookie +#if !defined( SHADER_MODEL_PS_2_0 ) + float3 vProjCoords = vFlashlightTexCoord.xyz / vFlashlightTexCoord.w; + float3 cFlashlightCookieColor = tex2D( g_tFlashlightCookieSampler, vProjCoords ); +#else + float3 cFlashlightCookieColor = tex2Dproj( g_tFlashlightCookieSampler, vFlashlightTexCoord.xyzw ); +#endif + + // Shadow depth map +#if FLASHLIGHTSHADOWS && !defined( SHADER_MODEL_PS_2_0 ) + int nShadowLevel = FLASHLIGHTDEPTHFILTERMODE; + float flShadow = DoFlashlightShadow( g_tFlashlightDepthSampler, g_tRandomRotationSampler, vProjCoords, float2(0,0), nShadowLevel, g_vShadowTweaks, false ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = lerp( flAttenuated, flShadow, flFlashlightAttenuation ); // Blend between shadow and above, according to light attenuation + cFlashlightCookieColor *= flShadow; // Apply shadow term to cookie color +#endif + + // Flashlight color intensity (needs to be multiplied by global flashlight color later) + cFlashlightColorFalloff.rgb = flFlashlightAttenuation * cFlashlightCookieColor.rgb; + + // Add this into the interpolated lighting + if ( bDoDiffuseWarp ) + { + //float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, flFlashlightNDotL ).rgb; + //i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * cWarpedLight.rgb; + i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; // No light warp for now + } + else + { + i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; + } + } + + //==============// + // Dilate pupil // + //==============// +#if !defined( SHADER_MODEL_PS_2_0 ) + vIrisUv.xy -= 0.5f; // Center around (0,0) + float fPupilCenterToBorder = saturate( length( vIrisUv.xy ) / 0.2f ); //Note: 0.2 is the uv radius of the iris + float fPupilDilateFactor = g_flDilationFactor; // This value should be between 0-1 + vIrisUv.xy *= lerp (1.0f, fPupilCenterToBorder, saturate( fPupilDilateFactor ) * 2.5f - 1.25f ); + vIrisUv.xy += 0.5f; +#endif + + //============// + // Iris color // + //============// + float4 cIrisColor = tex2D( g_tIrisSampler, vIrisUv.xy ); + + //==========================// + // Iris lighting highlights // + //==========================// + float3 cIrisLighting = float3( 0.0f, 0.0f, 0.0f ); + +#if !defined( SHADER_MODEL_PS_2_0 ) + // Mask off everything but the iris pixels + float fIrisHighlightMask = tex2D( g_tCorneaSampler, vCorneaUv.xy ).a; + + // Generate the normal + float3 vIrisTangentNormal = vCorneaTangentNormal.xyz; + vIrisTangentNormal.xy *= -2.5f; // I'm not normalizing on purpose + + for ( int j=0; j < nNumLights; j++ ) + { + // World light vector + float3 vWorldLightVector; + if ( ( j == 0 ) && ( bFlashlight == true ) ) + vWorldLightVector = vFlashlightVector.xyz; + else + vWorldLightVector = PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, j ); + + // Tangent light vector + float3 vTangentLightVector = Vec3WorldToTangent( vWorldLightVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Adjust the tangent light vector to generate the iris lighting + float3 tmpv = -vTangentLightVector.xyz; + tmpv.xy *= -0.5f; //Flatten tangent view + tmpv.z = max( tmpv.z, 0.5f ); //Clamp z of tangent view to help maintain highlight + tmpv.xyz = normalize( tmpv.xyz ); + + // Core iris lighting math + float fIrisFacing = pow( abs( dot( vIrisTangentNormal.xyz, tmpv.xyz ) ), 6.0f ) * 0.5f; // Yes, 6.0 and 0.5 are magic numbers + + // Cone of darkness to darken iris highlights when light falls behind eyeball past a certain point + float flConeOfDarkness = pow( 1.0f - saturate( ( -vTangentLightVector.z - 0.25f ) / 0.75f ), 4.0f ); + //float flConeOfDarkness = pow( 1.0f - saturate( ( -dot( vIrisTangentNormal.xyz, vTangentLightVector.xyz ) - 0.15f ) / 0.85f ), 8.0f ); + + // Tint by iris color and cone of darkness + float3 cIrisLightingTmp = fIrisFacing * fIrisHighlightMask * flConeOfDarkness; + + // Attenuate by light color and light falloff + if ( ( j == 0 ) && ( bFlashlight == true ) ) + cIrisLightingTmp.rgb *= cFlashlightColorFalloff.rgb * cFlashlightColor.rgb; + else if ( j == 0 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ); + else if ( j == 1 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ); + else if ( j == 2 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ); + else + cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ); + + // Sum into final variable + cIrisLighting.rgb += cIrisLightingTmp.rgb; + } + + // Add slight view dependent iris lighting based on ambient light intensity to enhance situations with no local lights (0.5f is to help keep it subtle) + cIrisLighting.rgb += saturate( dot( vIrisTangentNormal.xyz, -vTangentViewVector.xyz ) ) * g_flAverageAmbient * fIrisHighlightMask * 0.5f; +#else + // Else, intensify light over cornea to simulate the brightening that happens above + cIrisLighting.rgb += i.cVertexLight.rgb * vCorneaSample.a; +#endif + + //===================// + // Ambient occlusion // + //===================// + float3 cAmbientOcclFromTexture = tex2D( g_tEyeAmbientOcclSampler, i.vAmbientOcclUv_fallbackCorneaUv.xy ).rgb; + float3 cAmbientOcclColor = lerp( g_cAmbientOcclColor, 1.0f, cAmbientOcclFromTexture.rgb ); // Color the ambient occlusion + i.cVertexLight.rgb *= cAmbientOcclColor.rgb; + + //==========================// + // Reflection from cube map // + //==========================// + float3 vCorneaReflectionVector = reflect ( vWorldViewVector.xyz, vCorneaWorldNormal.xyz ); + + //float3 cReflection = ENV_MAP_SCALE * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb; + float3 cReflection = g_flGlossiness * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb; + + // Hack: Only add in half of the env map for the flashlight pass. This looks reasonable. + if ( bFlashlight ) + { + cReflection.rgb *= 0.5f; + } + + //===========================// + // Glint specular highlights // + //===========================// + float3 cSpecularHighlights = 0.0f; + if ( bFlashlight ) + { + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, vFlashlightVector.xyz ) ), 128.0f ) * cFlashlightColorFalloff.rgb * cFlashlightColor.rgb; + } + else // no flashlight + { + if ( nNumLights > 0 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 0 ) ) ), 128.0f ) * i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ); + + if ( nNumLights > 1 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 1 ) ) ), 128.0f ) * i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ); + + if ( nNumLights > 2 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 2 ) ) ), 128.0f ) * i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ); + + if ( nNumLights > 3 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 3 ) ) ), 128.0f ) * i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ); + } + + //===============// + // Combine terms // + //===============// + float4 result; + + // Unlit iris, pupil, and sclera color + result.rgb = cIrisColor.rgb; + + // Add in slight cornea noise to help define raised cornea layer for close-ups + result.rgb += fCorneaNoise * 0.1f; + + // Diffuse light (Vertex lighting + extra iris caustic lighting) + result.rgb *= i.cVertexLight.rgb + cIrisLighting.rgb; + + // Environment map + result.rgb += cReflection.rgb * i.cVertexLight.rgb; + + // Local light glints + result.rgb += cSpecularHighlights.rgb; + + // Set alpha to 1.0 by default + result.a = 1.0; + +#if !defined( SHADER_MODEL_PS_2_0 ) + float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w ); + return FinalOutputConst( result, fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR ); +#else + float fogFactor = CalcPixelFogFactor( PIXEL_FOG_TYPE_NONE, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w ); + return FinalOutput( result, fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +#endif + +} diff --git a/mp/src/materialsystem/stdshaders/eye_refract_vs20.fxc b/mp/src/materialsystem/stdshaders/eye_refract_vs20.fxc new file mode 100644 index 00000000..af975f99 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eye_refract_vs20.fxc @@ -0,0 +1,217 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// STATIC: "INTRO" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "vortwarp_vs20_helper.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_iFogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 g_cEyeOrigin : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_vIrisProjectionU : register( SHADER_SPECIFIC_CONST_2 ); +const float4 g_vIrisProjectionV : register( SHADER_SPECIFIC_CONST_3 ); +const float4 g_vFlashlightPosition : register( SHADER_SPECIFIC_CONST_4 ); + +#if INTRO +const float4 g_vConst4 : register( SHADER_SPECIFIC_CONST_5 ); +#define g_vModelOrigin g_vConst4.xyz +#define g_flTime g_vConst4.w +#endif + +const float4 g_vFlashlightMatrixRow1 : register( SHADER_SPECIFIC_CONST_6 ); +const float4 g_vFlashlightMatrixRow2 : register( SHADER_SPECIFIC_CONST_7 ); +const float4 g_vFlashlightMatrixRow3 : register( SHADER_SPECIFIC_CONST_8 ); +const float4 g_vFlashlightMatrixRow4 : register( SHADER_SPECIFIC_CONST_9 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + // Position deltas + float3 vPosFlex : POSITION1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; // Fixed-function fog factor +#endif + float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0; // Base texture coordinate + float4 cVertexLight : TEXCOORD1; // Vertex-lit color (Note: w is used for flashlight pass) + float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass) + float4 vWorldPosition_ProjPosZ : TEXCOORD3; + float3 vWorldNormal : TEXCOORD4; // World-space normal + float3 vWorldTangent : TEXCOORD5; // World-space tangent + float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights + float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights + + float3 vWorldBinormal : COLOR0; // World-space normal +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vPosition = v.vPos; + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz ); +#endif + + // Transform the position + float3 vWorldPosition; + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, vWorldPosition ); + + // Note: I'm relying on the iris projection vector math not changing or this will break + float3 vEyeSocketUpVector = normalize( -g_vIrisProjectionV.xyz ); + float3 vEyeSocketLeftVector = normalize( -g_vIrisProjectionU.xyz ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_flTime, g_vModelOrigin, vWorldPosition, dummy, dummy, dummy ); +#endif + + o.vWorldPosition_ProjPosZ.xyz = vWorldPosition.xyz; + + // Transform into projection space + //vWorldPosition -= ( vWorldPosition - g_cEyeOrigin ) * 0.9; //Debug to visualize eye origin + float4 vProjPos = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( vWorldPosition, 1.0f ), cViewProjZ ); + + + o.vWorldPosition_ProjPosZ.w = vProjPos.z; + +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( vWorldPosition, vProjPos, g_iFogType ); +#endif + + // Normal = (Pos - Eye origin) + float3 vWorldNormal = normalize( vWorldPosition.xyz - g_cEyeOrigin.xyz ); + o.vWorldNormal.xyz = vWorldNormal.xyz; + + // Tangent & binormal + /* + float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vEyeSocketLeftVector.xyz ) ); + o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f; + + float3 vWorldTangent = normalize( cross( vWorldBinormal.xyz, vWorldNormal.xyz ) ); + o.vWorldTangent.xyz = vWorldTangent.xyz; + //*/ + + //* + float3 vWorldTangent = normalize( cross( vEyeSocketUpVector.xyz, vWorldNormal.xyz ) ); + o.vWorldTangent.xyz = vWorldTangent.xyz; + + float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) ); + o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f; + //*/ + + float3 vWorldViewVector = normalize (vWorldPosition.xyz - cEyePos.xyz); + o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized (vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz); + + // AV - I think this will effectively make the eyeball less rounded left to right to help vertext lighting quality + // AV - Note: This probably won't look good if put on an exposed eyeball + //float vNormalDotSideVec = -dot( vWorldNormal, g_vEyeballUp ) * 0.5f; + float vNormalDotSideVec = -dot( vWorldNormal, vEyeSocketLeftVector) * 0.5f; + float3 vBentWorldNormal = normalize(vNormalDotSideVec * vEyeSocketLeftVector + vWorldNormal); + + // Compute vertex lighting + o.cVertexLight.a = 0.0f; //Only used for flashlight pass + o.cVertexLight.rgb = DoLightingUnrolled( vWorldPosition, vBentWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, nNumLights ); + + // Only interpolate ambient light for TF NPR lighting + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + if ( bDoDiffuseWarp ) + { + if( bDynamicLight ) + { + o.cVertexLight.rgb = AmbientLight( vBentWorldNormal.xyz ); + } + else + { + o.cVertexLight.rgb = float3( 0.0f, 0.0f, 0.0f ); + } + } + +// NOTE: it appears that o.vLightFalloffCosine01 and o.vLightFalloffCosine23 are filled in even if +// we don't have enough lights, meaning we pass garbage to the pixel shader which then throws it away + + // Light falloff for first two local lights + o.vLightFalloffCosine01.x = VertexAttenInternal( vWorldPosition.xyz, 0 ); + o.vLightFalloffCosine01.y = VertexAttenInternal( vWorldPosition.xyz, 1 ); + o.vLightFalloffCosine01.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 0, g_bHalfLambert ); + o.vLightFalloffCosine01.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 1, g_bHalfLambert ); + + // Light falloff for next two local lights + o.vLightFalloffCosine23.x = VertexAttenInternal( vWorldPosition.xyz, 2 ); + o.vLightFalloffCosine23.y = VertexAttenInternal( vWorldPosition.xyz, 3 ); + o.vLightFalloffCosine23.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 2, g_bHalfLambert ); + o.vLightFalloffCosine23.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 3, g_bHalfLambert ); + + // Texture coordinates set by artists for ambient occlusion + o.vAmbientOcclUv_fallbackCorneaUv.xy = v.vTexCoord0.xy; + + // Cornea uv for ps.2.0 fallback + float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture + vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) ); + vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) ); + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; + o.vAmbientOcclUv_fallbackCorneaUv.wz = vCorneaUv.xy; // Note: wz unpacks faster than zw in ps.2.0! + + // Step on the vertex light interpolator for the flashlight tex coords + bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false; + o.vTangentViewVector.w = 0.0f; + if ( bFlashlight ) + { + o.cVertexLight.x = dot( g_vFlashlightMatrixRow1.xyzw, float4( vWorldPosition, 1.0f ) ); + o.cVertexLight.y = dot( g_vFlashlightMatrixRow2.xyzw, float4( vWorldPosition, 1.0f ) ); + o.cVertexLight.z = dot( g_vFlashlightMatrixRow3.xyzw, float4( vWorldPosition, 1.0f ) ); + o.cVertexLight.w = dot( g_vFlashlightMatrixRow4.xyzw, float4( vWorldPosition, 1.0f ) ); + + o.vTangentViewVector.w = saturate( dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ) ); // Flashlight N.L with modified normal + + // Half lambert version + //o.cVertexLight.z = dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ); // Flashlight N.L with modified normal + //o.cVertexLight.z = ( o.cVertexLight.z * 0.5f ) + 0.5f; + //o.cVertexLight.z *= o.cVertexLight.z; + } + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/eyeball.cpp b/mp/src/materialsystem/stdshaders/eyeball.cpp new file mode 100644 index 00000000..7113585d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyeball.cpp @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Eyeball shader +// +//=============================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Eyeball, "Help for EyeBall" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/pupil_l", "iris texture", 0 ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + // This should be a dead shader... + return "Wireframe"; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + } + +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/eyeglint_dx9.cpp b/mp/src/materialsystem/stdshaders/eyeglint_dx9.cpp new file mode 100644 index 00000000..d2662e6d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyeglint_dx9.cpp @@ -0,0 +1,66 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Run procedural glint generation inner loop in pixel shader +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "shaderlib/cshader.h" + +#include "eyeglint_vs20.inc" +#include "eyeglint_ps20.inc" +#include "eyeglint_ps20b.inc" + +DEFINE_FALLBACK_SHADER( EyeGlint, EyeGlint_dx9 ) +BEGIN_VS_SHADER( EyeGlint_dx9, "Help for EyeGlint" ) + +BEGIN_SHADER_PARAMS +END_SHADER_PARAMS + +SHADER_INIT +{ +} + +SHADER_FALLBACK +{ + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Wireframe"; + } + return 0; +} + +SHADER_DRAW +{ + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Additive blending + + int pTexCoords[3] = { 2, 2, 3 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, pTexCoords, 0 ); + + pShaderShadow->EnableCulling( false ); + + pShaderShadow->EnableSRGBWrite( false ); // linear texture + + DECLARE_STATIC_VERTEX_SHADER( eyeglint_vs20 ); + SET_STATIC_VERTEX_SHADER( eyeglint_vs20 ); + + SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( eyeglint ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyeglint_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( eyeglint_vs20 ); + + SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( eyeglint ); + } + Draw(); +} +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/eyeglint_ps2x.fxc b/mp/src/materialsystem/stdshaders/eyeglint_ps2x.fxc new file mode 100644 index 00000000..bc39f079 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyeglint_ps2x.fxc @@ -0,0 +1,32 @@ +// ======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== +// +// Run procedural glint generation inner loop in pixel shader (ps_2_0) +// +// ============================================================================= + +struct PS_INPUT +{ + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +float GlintGaussSpotCoefficient( float2 d ) +{ + return saturate( exp( -25.0f * dot(d, d) ) ); +} + +float4 main( PS_INPUT i ) : COLOR +{ + float2 uv = i.tc - i.glintCenter; // This texel relative to glint center + + float intensity = GlintGaussSpotCoefficient( uv + float2(-0.25f, -0.25f) ) + + GlintGaussSpotCoefficient( uv + float2( 0.25f, -0.25f) ) + + 5 * GlintGaussSpotCoefficient( uv ) + + GlintGaussSpotCoefficient( uv + float2(-0.25f, 0.25f) ) + + GlintGaussSpotCoefficient( uv + float2( 0.25f, 0.25f) ); + + intensity *= 4.0f/9.0f; + + return float4( intensity * i.glintColor, 1.0f ); +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/eyeglint_vs20.fxc b/mp/src/materialsystem/stdshaders/eyeglint_vs20.fxc new file mode 100644 index 00000000..cf1ccb9b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyeglint_vs20.fxc @@ -0,0 +1,38 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Vertex shader to pass through texcoords needed to run the +// procedural glint generation inner loop in the pixel shader +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel in 3x3 quad + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint in local 3x3 quad + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel in 3x3 quad + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint in local 3x3 quad + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + o.projPos = float4( v.vPos, 1.0f ); + o.tc = v.tc; + o.glintCenter = v.glintCenter; + o.glintColor = v.glintColor; + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/eyes.cpp b/mp/src/materialsystem/stdshaders/eyes.cpp new file mode 100644 index 00000000..7aa4738f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes.cpp @@ -0,0 +1,186 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: eye renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "eyes_dx8_dx9_helper.h" +#include "cloak_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( eyes, Eyes_dx8 ) + +BEGIN_VS_SHADER( Eyes_dx8, + "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/eyeball_l", "iris texture", 0 ) + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/pupil_l", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "models/humans/male/glint", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Iris dilation" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + END_SHADER_PARAMS + + void SetupVars( Eyes_DX8_DX9_Vars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nGlint = GLINT; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nEyeUp = EYEUP; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nGlintU = GLINTU; + info.m_nGlintV = GLINTV; + info.m_nDilation = DILATION; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_INIT_PARAMS() + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitParamsEyes_DX8_DX9( this, params, pMaterialName, info ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "Eyes_dx6"; + + return 0; + } + + SHADER_INIT + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitEyes_DX8_DX9( this, params, info ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + // There is some strangeness in DX8 when trying to skip the main pass, so leave this alone for now + //bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + DrawEyes_DX8_DX9( false, this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/eyes.vsh b/mp/src/materialsystem/stdshaders/eyes.vsh new file mode 100644 index 00000000..58ae021d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes.vsh @@ -0,0 +1,80 @@ +vs.1.1 +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0 = eyeball origin +; $SHADER_SPECIFIC_CONST_1 = eyeball up * 0.5 +; $SHADER_SPECIFIC_CONST_2 = iris projection U +; $SHADER_SPECIFIC_CONST_3 = iris projection V +; $SHADER_SPECIFIC_CONST_4 = glint projection U +; $SHADER_SPECIFIC_CONST_5 = glint projection V +;------------------------------------------------------------------------------ + +# STATIC: "HALF_LAMBERT" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "LIGHT_COMBO" "0..21" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending (whacks r1-r7, positions in r7) +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&SkinPosition( $worldPos ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Normal is based on vertex position +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$normalDotUp ); + +sub $worldNormal, $worldPos, $SHADER_SPECIFIC_CONST_0 ; Normal = (Pos - Eye origin) +dp3 $normalDotUp, $worldNormal, $SHADER_SPECIFIC_CONST_1 ; Normal -= 0.5f * (Normal dot Eye Up) * Eye Up +mul $normalDotUp, $normalDotUp, $cHalf +mad $worldNormal, -$normalDotUp, $SHADER_SPECIFIC_CONST_1, $worldNormal + +&FreeRegister( \$normalDotUp ); + +; normalize the normal +&Normalize( $worldNormal ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ +&DoLighting( $worldPos, $worldNormal ); + +&FreeRegister( \$worldNormal ); + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +; Texture 0 is the base texture +; Texture 1 is a planar projection used for the iris +; Texture 2 is a planar projection used for the glint +;------------------------------------------------------------------------------ + +mov oT0, $vTexCoord0 +dp4 oT1.x, $SHADER_SPECIFIC_CONST_2, $worldPos +dp4 oT1.y, $SHADER_SPECIFIC_CONST_3, $worldPos +dp4 oT2.x, $SHADER_SPECIFIC_CONST_4, $worldPos +dp4 oT2.y, $SHADER_SPECIFIC_CONST_5, $worldPos + +&FreeRegister( \$worldPos ); diff --git a/mp/src/materialsystem/stdshaders/eyes_dx6.cpp b/mp/src/materialsystem/stdshaders/eyes_dx6.cpp new file mode 100644 index 00000000..f5454595 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_dx6.cpp @@ -0,0 +1,251 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Teeth renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Eyes, Eyes_dx6 ) + +BEGIN_VS_SHADER( Eyes_dx6, + "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + LoadTexture( IRIS ); + } + + void SetTextureTransform( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + MaterialMatrixMode_t textureTransform, int uparam, int vparam ) + { + Vector4D u, v; + params[uparam]->GetVecValue( u.Base(), 4 ); + params[vparam]->GetVecValue( v.Base(), 4 ); + + // Need to transform these puppies into camera space + // they are defined in world space + VMatrix mat, invTrans; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mat.m[0] ); + mat = mat.Transpose(); + + // Compute the inverse transpose of the matrix + // NOTE: I only have to invert it here because VMatrix is transposed + // with respect to what gets returned from GetMatrix. + mat.InverseGeneral( invTrans ); + invTrans = invTrans.Transpose(); + + // Transform the u and v planes into view space + Vector4D uview, vview; + uview.AsVector3D() = invTrans.VMul3x3( u.AsVector3D() ); + vview.AsVector3D() = invTrans.VMul3x3( v.AsVector3D() ); + uview[3] = u[3] - DotProduct( mat.GetTranslation(), uview.AsVector3D() ); + vview[3] = v[3] - DotProduct( mat.GetTranslation(), vview.AsVector3D() ); + + float m[16]; + m[0] = uview[0]; m[1] = vview[0]; m[2] = 0.0f; m[3] = 0.0f; + m[4] = uview[1]; m[5] = vview[1]; m[6] = 0.0f; m[7] = 0.0f; + m[8] = uview[2]; m[9] = vview[2]; m[10] = 1.0f; m[11] = 0.0f; + m[12] = uview[3]; m[13] = vview[3]; m[14] = 0.0f; m[15] = 1.0f; + + pShaderAPI->MatrixMode( textureTransform ); + pShaderAPI->LoadMatrix( m ); + } + + void DrawFlashlight_Iris( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + + // Alpha blend + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_NORMAL; + pShaderShadow->DrawFlags( flags ); + FogToBlack(); + + pShaderShadow->EnableLighting( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + // alpha stage 0 + // get alpha from constant alpha + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + + // alpha stage 1 + // get alpha from $basetexture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Shove the view position into texcoord 0 before the texture matrix. + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + + // iris transform + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, true ); + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE1, SHADER_TEXGENPARAM_EYE_LINEAR ); + + } + DYNAMIC_STATE + { + SetFlashlightFixedFunctionTextureTransform( MATERIAL_TEXTURE0 ); + + // NOTE: This has to come after the loadmatrix since the loadmatrix screws with the + // transform flags!!!!!! + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 3, true ); + + BindTexture( SHADER_SAMPLER0, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + + BindTexture( SHADER_SAMPLER1, IRIS, IRISFRAME ); + SetTextureTransform( params, pShaderAPI, MATERIAL_TEXTURE1, IRISU, IRISV ); + } + Draw(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // whites + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true ); + + // iris + DrawFlashlight_Iris( params, pShaderAPI, pShaderShadow ); + } + + void DrawUsingSoftwareLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // whites + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + + // iris + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, IRIS, IRISFRAME ); + SetTextureTransform( params, pShaderAPI, MATERIAL_TEXTURE0, IRISU, IRISV ); + } + Draw(); + + // Glint + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, 1.0f ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, GLINT ); + SetTextureTransform( params, pShaderAPI, MATERIAL_TEXTURE0, GLINTU, GLINTV ); + } + Draw( ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawUsingSoftwareLighting( params, pShaderAPI, pShaderShadow ); + } + + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp new file mode 100644 index 00000000..97e6ed32 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp @@ -0,0 +1,550 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "BaseVSShader.h" +#include "tier1/convar.h" +#include "mathlib/vmatrix.h" +#include "eyes_dx8_dx9_helper.h" +#include "cpp_shader_constant_register_map.h" +#include "Eyes.inc" +#include "eyes_flashlight_vs11.inc" +#include "eyes_flashlight_ps11.inc" + +#ifdef STDSHADER_DX9_DLL_EXPORT + +#include "eyes_vs20.inc" +#include "eyes_ps20.inc" +#include "eyes_ps20b.inc" +#include "eyes_flashlight_vs20.inc" +#include "eyes_flashlight_ps20.inc" +#include "eyes_flashlight_ps20b.inc" + +#ifndef _X360 +#include "eyes_vs30.inc" +#include "eyes_ps30.inc" +#include "eyes_flashlight_vs30.inc" +#include "eyes_flashlight_ps30.inc" +#endif + +#endif + +ConVar r_flashlight_version2( "r_flashlight_version2", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ); + +void InitParamsEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Eyes_DX8_DX9_Vars_t &info ) +{ + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + Assert( info.m_nIntro != -1 ); + if( info.m_nIntro != -1 && !params[info.m_nIntro]->IsDefined() ) + { + params[info.m_nIntro]->SetIntValue( 0 ); + } +} + +void InitEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, Eyes_DX8_DX9_Vars_t &info ) +{ + pShader->LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nIris, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nGlint ); + + // Be sure dilation is zeroed if undefined + if( !params[info.m_nDilation]->IsDefined() ) + { + params[info.m_nDilation]->SetFloatValue( 0.0f ); + } +} + +static void SetDepthFlashlightParams( CBaseVSShader *pShader, IShaderDynamicAPI *pShaderAPI, const VMatrix& worldToTexture, const FlashlightState_t& flashlightState ) +{ + float atten[4], pos[4], tweaks[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } +} + + +static void DrawFlashlight( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + if( pShaderShadow ) + { + pShaderShadow->EnableDepthWrites( false ); + + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Write over the eyes that were already there + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Spot + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Base + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Normalizing cubemap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Iris + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( bDX9 ) + { + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + } +#endif + + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Spot + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Iris + pShaderShadow->EnableSRGBWrite( true ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Shadow noise rotation map + } + } + else +#endif + { + // DX8 uses old asm shaders + eyes_flashlight_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "eyes_flashlight_vs11", vshIndex.GetIndex() ); + + eyes_flashlight_ps11_Static_Index pshIndex; + pShaderShadow->SetPixelShader( "eyes_flashlight_ps11", pshIndex.GetIndex() ); + } + + pShader->FogToBlack(); + } + else + { + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + if ( !bDX9 ) + { + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 0, true ); + } + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + pShader->BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture, info.m_nFrame ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nIris, info.m_nIrisFrame ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( bDX9 ) + { + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + } +#endif + +// float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), 0.0f, 0.0f, 0.0f}; +// pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + + SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + + SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState ); + } +#endif + } + else // older asm shaders for DX8 +#endif + { + eyes_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + eyes_flashlight_ps11_Dynamic_Index pshIndex; + pShaderAPI->SetPixelShaderIndex( pshIndex.GetIndex() ); + } + + // This uses from VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 to VERTEX_SHADER_SHADER_SPECIFIC_CONST_5 + pShader->SetFlashlightVertexShaderConstants( false, -1, false, -1, false ); + + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, info.m_nEyeUp ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, info.m_nIrisV ); + } + pShader->Draw(); +} + +static void DrawUsingVertexShader( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Glint + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + pShaderShadow->EnableAlphaWrites( true ); //we end up hijacking destination alpha for opaques most of the time. + +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( bDX9 ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( eyes_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[info.m_nIntro]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( eyes_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( eyes_ps20b ); + SET_STATIC_PIXEL_SHADER( eyes_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eyes_ps20 ); + SET_STATIC_PIXEL_SHADER( eyes_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eyes_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[info.m_nIntro]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eyes_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( eyes_ps30 ); + SET_STATIC_PIXEL_SHADER( eyes_ps30 ); + } +#endif + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // White + pShaderShadow->EnableSRGBWrite( true ); + } + else +#endif + { + eyes_Static_Index vshIndex; + vshIndex.SetHALF_LAMBERT( IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + pShaderShadow->SetVertexShader( "Eyes", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "Eyes_Overbright2" ); + } + + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nFrame ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nGlint ); + pShader->SetAmbientCubeDynamicStateVertexShader(); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nEyeUp ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nGlintU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, info.m_nGlintV ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + if( bDX9 ) + { + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( eyes_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_vs30 ); + } +#endif + + // Get luminance of ambient cube and saturate it + float fGlintDamping = max(0.0f, min( pShaderAPI->GetAmbientLightCubeLuminance(), 1.0f ) ); + const float fDimGlint = 0.01f; + + // Remap so that glint damping smooth steps to zero for low luminances + if ( fGlintDamping > fDimGlint ) + fGlintDamping = 1.0f; + else + fGlintDamping *= SimpleSplineRemapVal( fGlintDamping, 0.0f, fDimGlint, 0.0f, 1.0f ); + + // Special constant for DX9 eyes: { Dilation, ambient, x, x }; + float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), fGlintDamping, 0.0f, 0.0f}; + pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps30 ); + } +#endif + + Assert( info.m_nIntro != -1 ); + if( params[info.m_nIntro]->GetIntValue() ) + { + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[info.m_nEntityOrigin]->IsDefined() ); + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, timeVec, 1 ); + } + } + else +#endif + { + eyes_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetLIGHT_COMBO( pShaderAPI->GetCurrentLightCombo() ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + pShader->Draw(); +} + +static void DrawEyes_DX8_DX9_Internal( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bHasFlashlight, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + if( !bHasFlashlight ) + { + DrawUsingVertexShader( bDX9, pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + DrawFlashlight( bDX9, pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +} + +extern ConVar r_flashlight_version2; +void DrawEyes_DX8_DX9( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawEyes_DX8_DX9_Internal( bDX9, pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawEyes_DX8_DX9_Internal( bDX9, pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression ); +} + + diff --git a/mp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.h b/mp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.h new file mode 100644 index 00000000..daf7c124 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef EYES_DX8_DX9_HELPER_H +#define EYES_DX8_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Eyes_DX8_DX9_Vars_t +{ + Eyes_DX8_DX9_Vars_t() { memset( this, 0xFF, sizeof(Eyes_DX8_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nFrame; + int m_nIris; + int m_nIrisFrame; + int m_nGlint; + int m_nEyeOrigin; + int m_nEyeUp; + int m_nIrisU; + int m_nIrisV; + int m_nGlintU; + int m_nGlintV; + int m_nDilation; + int m_nIntro; + int m_nEntityOrigin; + int m_nWarpParam; +}; + +void InitParamsEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eyes_DX8_DX9_Vars_t &info ); +void InitEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, Eyes_DX8_DX9_Vars_t &info ); +void DrawEyes_DX8_DX9( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EYES_DX8_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/eyes_dx9.cpp b/mp/src/materialsystem/stdshaders/eyes_dx9.cpp new file mode 100644 index 00000000..b33ec804 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_dx9.cpp @@ -0,0 +1,84 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: eye renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "eyes_dx8_dx9_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( eyes, Eyes_dx9 ) + +BEGIN_VS_SHADER( Eyes_dx9, "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Pupil dilation (0 is none, 1 is maximal)" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + void SetupVars( Eyes_DX8_DX9_Vars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nGlint = GLINT; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nEyeUp = EYEUP; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nGlintU = GLINTU; + info.m_nGlintV = GLINTV; + info.m_nDilation = DILATION; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + } + + SHADER_INIT_PARAMS() + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitParamsEyes_DX8_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "Eyes_dx8"; + + return 0; + } + + SHADER_INIT + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitEyes_DX8_DX9( this, params, info ); + } + + + SHADER_DRAW + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + DrawEyes_DX8_DX9( true, this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/eyes_flashlight2_ps11.psh b/mp/src/materialsystem/stdshaders/eyes_flashlight2_ps11.psh new file mode 100644 index 00000000..3b02fbb3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_flashlight2_ps11.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw stuff +;------------------------------------------------------------------------------ + +tex t0 ; Contains spotlight +tex t1 ; Contains base texture +tex t2 ; Normalize world pos to light +tex t3 ; Sample iris + +dp3 r0, t2_bx2, v0_bx2 ; r0 = N dot L +lrp r1.rgb, t3.a, t3, t1 ; r1 = lerp( baseColor, irisSample.xyz, irisSample.a ) +mul r0.rgb, r0_sat, r1 ; Saturate ( N dot L )* lerp +mul r0.rgb, r0, v0.a ; *= attenuation +mul_x2 r0.rgb, r0, t0 + ; *= 2 * spotlight +mov r0.a, t1.a diff --git a/mp/src/materialsystem/stdshaders/eyes_flashlight_inc.fxc b/mp/src/materialsystem/stdshaders/eyes_flashlight_inc.fxc new file mode 100644 index 00000000..7629f72f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_flashlight_inc.fxc @@ -0,0 +1,92 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + + +const float4 g_vShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +sampler SpotSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); +sampler IrisSampler : register( s3 ); + +#if FLASHLIGHTSHADOWS && (!SHADER_MODEL_PS_1_1) && (!SHADER_MODEL_PS_1_4) && (!SHADER_MODEL_PS_2_0) +sampler FlashlightDepthSampler : register( s4 ); +sampler RandomRotationSampler : register( s5 ); +#endif + +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + +#else + const float4 g_FogParams : register( PSREG_FOG_PARAMS ); + const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +#endif + +struct PS_INPUT +{ + float4 spotTexCoord : TEXCOORD0; + float2 baseTexCoord : TEXCOORD1; + float2 irisTexCoord : TEXCOORD3; +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + float3 vertAtten : COLOR0; +#else + float3 vertAtten : TEXCOORD4; + float3 worldPos : TEXCOORD5; + float3 projPos : TEXCOORD7; +#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if defined(SHADER_MODEL_PS_2_0) + float3 spotColor = tex2Dproj( SpotSampler, i.spotTexCoord.xyzw ) * cFlashlightColor; +#elif ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + float3 spotColor = tex2D( SpotSampler, vProjCoords ) * cFlashlightColor; +#else + float3 spotColor = tex2D( SpotSampler, i.spotTexCoord ); +#endif + + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + float4 irisSample = tex2D( IrisSampler, i.irisTexCoord ); + + float3 outcolor = float3(1,1,1); + +#if !defined( SHADER_MODEL_PS_1_1 ) && !defined( SHADER_MODEL_PS_1_4 ) + if( i.spotTexCoord.w <= 0.0f ) + { + outcolor = float3(0,0,0); + } +#endif + + // Composite the iris and sclera together +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + float3 albedo = lerp( baseSample.xyz, irisSample.xyz, irisSample.a ); +#else + float3 albedo = lerp( baseSample.xyz, irisSample.xyz * 0.5f, irisSample.a ); // dim down the iris in HDR +#endif + + // Do shadow depth mapping... +#if FLASHLIGHTSHADOWS && ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos.xy / i.projPos.z, FLASHLIGHTDEPTHFILTERMODE, g_vShadowTweaks, true ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = lerp( flAttenuated, flShadow, dot(i.vertAtten, float3(0.30f, 0.59f, 0.11f) ) ); // Blend between shadow and above, according to light attenuation + outcolor *= flShadow * spotColor * albedo; +#else + outcolor *= spotColor * albedo; +#endif + + // NOTE!! This has to be last to avoid loss of range. + outcolor *= i.vertAtten; +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + return float4( outcolor, baseSample.a ); +#else + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos.z, i.projPos.z ); + return FinalOutput( float4( outcolor, 1.0f ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +#endif + +} diff --git a/mp/src/materialsystem/stdshaders/eyes_flashlight_ps11.fxc b/mp/src/materialsystem/stdshaders/eyes_flashlight_ps11.fxc new file mode 100644 index 00000000..25e0702e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_flashlight_ps11.fxc @@ -0,0 +1,9 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#define HDRTYPE HDR_TYPE_NONE + +#include "eyes_flashlight_inc.fxc" diff --git a/mp/src/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc b/mp/src/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc new file mode 100644 index 00000000..eb00fc04 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc @@ -0,0 +1,15 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +#include "eyes_flashlight_inc.fxc" diff --git a/mp/src/materialsystem/stdshaders/eyes_flashlight_vs11.vsh b/mp/src/materialsystem/stdshaders/eyes_flashlight_vs11.vsh new file mode 100644 index 00000000..48c4cd57 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_flashlight_vs11.vsh @@ -0,0 +1,115 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos ); + +alloc $worldPos +alloc $projPos + + +&SkinPosition( $worldPos ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 + +;------------------------------------------------------------------------------ +; Normal is based on vertex position +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$normalDotUp ); + +sub $worldNormal, $worldPos, $SHADER_SPECIFIC_CONST_6 ; Normal = (Pos - Eye origin) +dp3 $normalDotUp, $worldNormal, $SHADER_SPECIFIC_CONST_7 ; Normal -= 0.5f * (Normal dot Eye Up) * Eye Up +mul $normalDotUp, $normalDotUp, $cHalf +mad $worldNormal, -$normalDotUp, $SHADER_SPECIFIC_CONST_7, $worldNormal + +&FreeRegister( \$normalDotUp ); + +; normalize the normal +&Normalize( $worldNormal ); + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +; base tex coords +mov oT1.xy, $vTexCoord0 + +; spotlight texcoords +dp4 oT0.x, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp4 oT0.z, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp4 oT0.w, $worldPos, $SHADER_SPECIFIC_CONST_4 + +local( $worldPosToLightVector, $distFactors ); + +alloc $worldPosToLightVector + +sub $worldPosToLightVector, $SHADER_SPECIFIC_CONST_0.xyz, $worldPos + +local( $distatten ); +alloc $distatten +; $distatten = [ 1, 1/dist, 1/distsquared ] + +; dist squared +dp3 $distatten.z, $worldPosToLightVector, $worldPosToLightVector + +; oodist +rsq $distatten.y, $distatten.z + +mov $distatten.x, $cOne + +local( $dist ); +alloc $dist +mul $dist.x, $distatten.z, $distatten.y + +rcp $distatten.z, $distatten.z ; 1/distsquared + +local( $endFalloffFactor ); +alloc $endFalloffFactor + +; ( dist - farZ ) +sub $endFalloffFactor.x, $dist.x, $SHADER_SPECIFIC_CONST_5.w +; 1 / ( (0.6f * farZ) - farZ) +mul $endFalloffFactor, $endFalloffFactor.x, $SHADER_SPECIFIC_CONST_0.w +max $endFalloffFactor, $endFalloffFactor, $cZero +min $endFalloffFactor, $endFalloffFactor, $cOne + +local( $vertAtten ); +alloc $vertAtten +dp3 $vertAtten, $distatten, $SHADER_SPECIFIC_CONST_5 +mul $vertAtten, $vertAtten, $endFalloffFactor + +; Normalize L +&Normalize( $worldPosToLightVector ); + +; N.L +dp3 $worldNormal, $worldNormal, $worldPosToLightVector + +; Modulate distance attenuation with N.L +mul oD0, $vertAtten, $worldNormal + +; iris +dp4 oT3.x, $SHADER_SPECIFIC_CONST_8, $worldPos +dp4 oT3.y, $SHADER_SPECIFIC_CONST_9, $worldPos + +free $dist +free $endFalloffFactor +free $worldPos +free $worldNormal +free $projPos +free $worldPosToLightVector +free $distatten +free $vertAtten diff --git a/mp/src/materialsystem/stdshaders/eyes_flashlight_vs20.fxc b/mp/src/materialsystem/stdshaders/eyes_flashlight_vs20.fxc new file mode 100644 index 00000000..e2e37dc1 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_flashlight_vs20.fxc @@ -0,0 +1,145 @@ +// ------------------------------------------------------------------------------ +// $cLight0Pos = world space light position +// $SHADER_SPECIFIC_CONST_1 = spotlight projection +// $SHADER_SPECIFIC_CONST_2 = spotlight projection +// $SHADER_SPECIFIC_CONST_3 = spotlight projection +// $SHADER_SPECIFIC_CONST_4 = spotlight projection +// $SHADER_SPECIFIC_CONST_5 = far z +// $SHADER_SPECIFIC_CONST_6 = eyeball origin +// $SHADER_SPECIFIC_CONST_7 = eyeball up * 0.5 +// $SHADER_SPECIFIC_CONST_8 = iris projection U +// $SHADER_SPECIFIC_CONST_9 = iris projection V +// ------------------------------------------------------------------------------ + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cLightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cSpotlightProj1 : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cSpotlightProj2 : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cSpotlightProj3 : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cSpotlightProj4 : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cFlashlighAtten : register( SHADER_SPECIFIC_CONST_5 ); // const, linear, quadratic & farZ +const float4 cIrisProjectionU : register( SHADER_SPECIFIC_CONST_8 ); +const float4 cIrisProjectionV : register( SHADER_SPECIFIC_CONST_9 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vNormal : NORMAL; + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; // Fixed-function fog factor +#endif + float4 spotTexCoord : TEXCOORD0; // Spotlight texture coordinates + float2 baseTexCoord : TEXCOORD1; // Base texture coordinates + float2 irisTexCoord : TEXCOORD3; // Iris texture coordinates + float3 vertAtten : TEXCOORD4; // vertex attenuation + float3 worldPos : TEXCOORD5; + float3 projPosXYZ : TEXCOORD7; +}; + + +float RemapValClamped_01( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + worldNormal = normalize( worldNormal ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.projPosXYZ = projPos.xyz; + o.worldPos = worldPos.xyz; + +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, o.projPos, g_FogType ); +#endif + + // Base texture coordinates + o.baseTexCoord = v.vTexCoord0; + + // Spotlight texture coordinates + o.spotTexCoord.x = dot( cSpotlightProj1, float4(worldPos, 1) ); + o.spotTexCoord.y = dot( cSpotlightProj2, float4(worldPos, 1) ); + o.spotTexCoord.z = dot( cSpotlightProj3, float4(worldPos, 1) ); + o.spotTexCoord.w = dot( cSpotlightProj4, float4(worldPos, 1) ); + + // Compute vector to light + float3 vWorldPosToLightVector = cLightPosition.xyz - worldPos; + + float3 vDistAtten = float3(1, 1, 1); + vDistAtten.z = dot( vWorldPosToLightVector, vWorldPosToLightVector ); // distsquared + vDistAtten.y = rsqrt( vDistAtten.z ); // 1 / dist + + float flDist = vDistAtten.z * vDistAtten.y; // dist + vDistAtten.z = 1.0f / vDistAtten.z; // 1 / distsquared + + float fFarZ = cFlashlighAtten.w; + + float endFalloffFactor = RemapValClamped_01( flDist, fFarZ, 0.6 * fFarZ ); + o.vertAtten.xyz = endFalloffFactor * dot( vDistAtten, cFlashlighAtten.xyz ); + + o.vertAtten *= dot( normalize( vWorldPosToLightVector ), worldNormal ); + + o.irisTexCoord.x = dot( cIrisProjectionU, float4(worldPos, 1) ); + o.irisTexCoord.y = dot( cIrisProjectionV, float4(worldPos, 1) ); + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/eyes_ps2x.fxc b/mp/src/materialsystem/stdshaders/eyes_ps2x.fxc new file mode 100644 index 00000000..d71d813f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/eyes_ps2x.fxc @@ -0,0 +1,68 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler IrisSampler : register( s1 ); +sampler GlintSampler : register( s2 ); +const float4 cEyeScalars : register( c0 ); // { Dilation, ambient, x, x } + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float2 irisTexCoord : TEXCOORD1; + float2 glintTexCoord : TEXCOORD2; + float3 vertAtten : TEXCOORD3; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +#define fDilationFactor cEyeScalars.x +#define fGlintDamping cEyeScalars.y + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + float4 glintSample = tex2D( GlintSampler, i.glintTexCoord ); +/* + // Dilate the pupil/iris texture (1 is max dilation, 0 is none) + float2 biasedCoords = i.irisTexCoord * 2.0f - 1.0f; // -1 to +1 range + float fDilatability = saturate(0.8f - sqrt(dot(biasedCoords, biasedCoords) )); // 1 in the center, fading out to 0 at 0.8 from center, since irises are inset into maps + float2 scaledCoords = biasedCoords * (1 + fDilatability); // Maximal dilation + + // Blend undilated and maximally dilated based upon dilation factor + float2 dilatedCoords = lerp( scaledCoords, biasedCoords, 1.0f-saturate(cDilationFactor.x)); + dilatedCoords = dilatedCoords * 0.5f + 0.5f; // Back to 0..1 range +*/ + + float4 irisSample = tex2D( IrisSampler, i.irisTexCoord ); // Sample the iris map using dilated coordinates + + float4 result; + result.rgb = lerp( baseSample.rgb, irisSample.rgb, irisSample.a ); + result.rgb *= i.vertAtten; + result.rgb += glintSample.rgb * fGlintDamping; + result.a = baseSample.a; + + bool bWriteDepthToAlpha = false; + + // ps_2_b and beyond +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) + bWriteDepthToAlpha = WRITE_DEPTH_TO_DESTALPHA != 0; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w ); +} diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_helper.cpp b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_helper.cpp new file mode 100644 index 00000000..9b02330a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_helper.cpp @@ -0,0 +1,271 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Flesh Interior Pass + "$FleshInteriorEnabled" "1" // Enables effect + "$FleshInteriorTexture" "models/Alyx/alyx_flesh_color" // Mask in alpha + "$FleshNormalTexture" "models/Alyx/alyx_flesh_normal" + "$FleshBorderTexture1D" "models/Alyx/alyx_flesh_border" + "$FleshInteriorNoiseTexture" "Engine/noise-blur-256x256" + "$FleshSubsurfaceTexture" "models/Alyx/alyx_flesh_subsurface" + "$FleshBorderNoiseScale" "1.5" // Flesh Noise UV scalar for border + "$FleshBorderWidth" "0.3" // Width of flesh border + "$FleshBorderSoftness" "0.42" // Border softness must be greater than 0.0 and up tp 0.5 + "$FleshBorderTint" "[1 1 1]" // Tint / brighten the border 1D texture + "$FleshGlossBrightness" "0.66" // Change the brightness of the glossy layer + "$FleshDebugForceFleshOn" "0" // DEBUG: This will force on full flesh for testing + "$FleshScrollSpeed" "1.0" + "Proxies" + { + "FleshInterior" + { + } + } + + #include "flesh_interior_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + Add this above SHADER_INIT_PARAMS() + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + } + + In SHADER_INIT_PARAMS() + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + + At the very end of SHADER_DRAW + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "convar.h" +#include "flesh_interior_blended_pass_helper.h" + +// Auto generated inc files +#include "flesh_interior_blended_pass_dx8_vs11.inc" + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + SET_PARAM_STRING_IF_NOT_DEFINED( info.m_nFleshCubeTexture, "env_cubemap" ); // Default to in-game env map + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderNoiseScale, kDefaultBorderNoiseScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflDebugForceFleshOn, kDefaultDebugForceFleshOn ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius1, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius2, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius3, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius4, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncSubsurfaceTint, kDefaultSubsurfaceTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderWidth, kDefaultBorderWidth ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderSoftness, kDefaultBorderSoftness ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncBorderTint, kDefaultBorderTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlobalOpacity, kDefaultGlobalOpacity ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlossBrightness, kDefaultGlossBrightness ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflScrollSpeed, kDefaultScrollSpeed ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ) +{ + // Load textures + pShader->LoadTexture( info.m_nFleshTexture ); + //pShader->LoadTexture( info.m_nFleshNoiseTexture ); + //pShader->LoadTexture( info.m_nFleshBorderTexture1D ); + //pShader->LoadTexture( info.m_nFleshNormalTexture ); + //pShader->LoadTexture( info.m_nFleshSubsurfaceTexture ); + //pShader->LoadCubeMap( info.m_nFleshCubeTexture ); +} + +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState(); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + flesh_interior_blended_pass_dx8_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "flesh_interior_blended_pass_dx8_vs11", vshIndex.GetIndex() ); + + // Pixel Shader + pShaderShadow->SetPixelShader( "flesh_interior_blended_pass_dx8_ps11", 0 ); + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + + // Set Vertex Shader Combos + flesh_interior_blended_pass_dx8_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + // Set Vertex Shader Constants + + // Time % 1000 + float flCurrentTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + flCurrentTime *= IS_PARAM_DEFINED( info.m_nflScrollSpeed ) ? params[info.m_nflScrollSpeed]->GetFloatValue() : kDefaultScrollSpeed; // This is a dirty hack, but it works well enough + + float vVsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vVsConst0[0] = flCurrentTime; + vVsConst0[0] -= (float)( (int)( vVsConst0[0] / 1000.0f ) ) * 1000.0f; + + // Flesh effect centers and radii + float vVsConst1[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius1 ) ) + { + params[info.m_nvEffectCenterRadius1]->GetVecValue( vVsConst1, 4 ); + if ( vVsConst1[3] < 0.001f ) + vVsConst1[3] = 0.001f; + vVsConst1[3] = 1.0f / vVsConst1[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vVsConst1, 1 ); + + float vVsConst2[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius2 ) ) + { + params[info.m_nvEffectCenterRadius2]->GetVecValue( vVsConst2, 4 ); + if ( vVsConst2[3] < 0.001f ) + vVsConst2[3] = 0.001f; + vVsConst2[3] = 1.0f / vVsConst2[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vVsConst2, 2 ); + + float vVsConst3[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius3 ) ) + { + params[info.m_nvEffectCenterRadius3]->GetVecValue( vVsConst3, 4 ); + if ( vVsConst3[3] < 0.001f ) + vVsConst3[3] = 0.001f; + vVsConst3[3] = 1.0f / vVsConst3[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vVsConst3, 3 ); + + float vVsConst4[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius4 ) ) + { + params[info.m_nvEffectCenterRadius4]->GetVecValue( vVsConst4, 4 ); + if ( vVsConst4[3] < 0.001f ) + vVsConst4[3] = 0.001f; + vVsConst4[3] = 1.0f / vVsConst4[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, vVsConst4, 4 ); + + // Set Pixel Shader Combos + /* None */ + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nFleshTexture ); + + // Set Pixel Shader Constants + + // Border color tint + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_ncBorderTint ) ? params[info.m_ncBorderTint]->GetVecValue() : kDefaultBorderTint, 1 ); + + // Global opacity + float vPsConst4[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst4[0] = IS_PARAM_DEFINED( info.m_nflGlobalOpacity ) ? params[info.m_nflGlobalOpacity]->GetFloatValue() : kDefaultGlobalOpacity; + pShaderAPI->SetPixelShaderConstant( 4, vPsConst4, 1 ); + + float vPsConst5[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + pShaderAPI->SetPixelShaderConstant( 5, vPsConst5, 1 ); + } + pShader->Draw(); +} diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_ps11.psh b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_ps11.psh new file mode 100644 index 00000000..fc7e32a9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_ps11.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; c5 1, 1, 1, 1 +;------------------------------------------------------------------------------ + +tex t0 ; Base color + +mul r0, v0, v0 ; // Mask^2 +mul r0, r0, r0 ; // Mask^4 +sub r0, c5, r0 ; // 1.0 - Mask^4 + +mul r0.rgb, r0, t0 ; // * Flesh texture color +mul r0.a, r0.a, t0.a ; // * Flesh X-rated mask +mul r0.a, r0.a, v1.a ; // * Fresnel mask diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_vs11.vsh b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_vs11.vsh new file mode 100644 index 00000000..53b6d87d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_vs11.vsh @@ -0,0 +1,114 @@ +# DYNAMIC: "SKINNING" "0..1" + +vs.1.1 +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$projPos ); + +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +if( $SKINNING == 1 ) +{ + &Normalize( $worldNormal ); +} + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog - don't bother with water fog for intro effects +;------------------------------------------------------------------------------ +&DepthFog( $projPos, "oFog" ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Flesh area +;------------------------------------------------------------------------------ +; // Store the closest effect intensity +; o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius1.xyz ) * g_vEffectCenterOoRadius1.w ); +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius2.xyz ) * g_vEffectCenterOoRadius2.w ); +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius3.xyz ) * g_vEffectCenterOoRadius3.w ); +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius4.xyz ) * g_vEffectCenterOoRadius4.w ); + +alloc $tmp1 +alloc $flEffect + +mov $flEffect, $cTwo +mad $flEffect, $flEffect, $cTwo, $cTwo + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_1.w +min $flEffect, $flEffect, $tmp1.w + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_2.w +min $flEffect, $flEffect, $tmp1.w + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_3.w +min $flEffect, $flEffect, $tmp1.w + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_4 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_4.w +min $flEffect, $flEffect, $tmp1.w + +mov oD0, $flEffect + +; float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); +; o.flDistanceToEffectCenter_flFresnelEffect.y = pow( saturate( dot( -vWorldViewVector.xyz, vWorldNormal.xyz ) ), 1.5f ); + +sub $tmp1, $worldPos, $cEyePos +&Normalize( $tmp1 ); +dp3 $tmp1, -$tmp1, $worldNormal +max $tmp1, $tmp1, $cZero +mul $tmp1, $tmp1, $tmp1 +mov oD1, $tmp1 + +free $tmp1 +free $flEffect + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +mov oT0.xy, $vTexCoord0 + +alloc $tmp2 + +dp4 $tmp2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 $tmp2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +add oT1.xy, $tmp2, $SHADER_SPECIFIC_CONST_4 + +free $tmp2 + +; YUCK! This is to make texcoords continuous for mat_softwaretl +mov oT2, $cZero + +&FreeRegister( \$worldPos ); +&FreeRegister( \$worldNormal ); diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp new file mode 100644 index 00000000..03ae509d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp @@ -0,0 +1,355 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Flesh Interior Pass + "$FleshInteriorEnabled" "1" // Enables effect + "$FleshInteriorTexture" "models/Alyx/alyx_flesh_color" // Mask in alpha + "$FleshNormalTexture" "models/Alyx/alyx_flesh_normal" + "$FleshBorderTexture1D" "models/Alyx/alyx_flesh_border" + "$FleshInteriorNoiseTexture" "Engine/noise-blur-256x256" + "$FleshSubsurfaceTexture" "models/Alyx/alyx_flesh_subsurface" + "$FleshBorderNoiseScale" "1.5" // Flesh Noise UV scalar for border + "$FleshBorderWidth" "0.3" // Width of flesh border + "$FleshBorderSoftness" "0.42" // Border softness must be greater than 0.0 and up tp 0.5 + "$FleshBorderTint" "[1 1 1]" // Tint / brighten the border 1D texture + "$FleshGlossBrightness" "0.66" // Change the brightness of the glossy layer + "$FleshDebugForceFleshOn" "0" // DEBUG: This will force on full flesh for testing + "$FleshScrollSpeed" "1.0" + "Proxies" + { + "FleshInterior" + { + } + } + + #include "flesh_interior_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + Add this above SHADER_INIT_PARAMS() + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + } + + In SHADER_INIT_PARAMS() + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + + At the very end of SHADER_DRAW + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "convar.h" +#include "flesh_interior_blended_pass_helper.h" + +// Auto generated inc files +#include "flesh_interior_blended_pass_vs20.inc" +#include "flesh_interior_blended_pass_ps20.inc" +#include "flesh_interior_blended_pass_ps20b.inc" + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + SET_PARAM_STRING_IF_NOT_DEFINED( info.m_nFleshCubeTexture, "env_cubemap" ); // Default to in-game env map + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderNoiseScale, kDefaultBorderNoiseScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflDebugForceFleshOn, kDefaultDebugForceFleshOn ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius1, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius2, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius3, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius4, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncSubsurfaceTint, kDefaultSubsurfaceTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderWidth, kDefaultBorderWidth ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderSoftness, kDefaultBorderSoftness ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncBorderTint, kDefaultBorderTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlobalOpacity, kDefaultGlobalOpacity ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlossBrightness, kDefaultGlossBrightness ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflScrollSpeed, kDefaultScrollSpeed ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ) +{ + // Load textures + pShader->LoadTexture( info.m_nFleshTexture, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nFleshNoiseTexture ); + pShader->LoadTexture( info.m_nFleshBorderTexture1D, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nFleshNormalTexture ); + pShader->LoadTexture( info.m_nFleshSubsurfaceTexture, TEXTUREFLAGS_SRGB ); + pShader->LoadCubeMap( info.m_nFleshCubeTexture, TEXTUREFLAGS_SRGB ); +} + +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState(); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + SET_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + SET_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Noise texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); // Normal texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + // Set Vertex Shader Combos + LightState_t lightState = { 0, false, false }; + pShaderAPI->GetDX9LightState( &lightState ); + DECLARE_DYNAMIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + + // Set Vertex Shader Constants + pShader->SetAmbientCubeDynamicStateVertexShader(); + + // Time % 1000 + float flCurrentTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + flCurrentTime *= IS_PARAM_DEFINED( info.m_nflScrollSpeed ) ? params[info.m_nflScrollSpeed]->GetFloatValue() : kDefaultScrollSpeed; // This is a dirty hack, but it works well enough + + float vVsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vVsConst0[0] = flCurrentTime; + vVsConst0[0] -= (float)( (int)( vVsConst0[0] / 1000.0f ) ) * 1000.0f; + + // Noise UV scroll + vVsConst0[1] = flCurrentTime / 100.0f; + vVsConst0[1] -= (float)( (int)( vVsConst0[1] ) ); + + // Border noise scale + vVsConst0[2] = IS_PARAM_DEFINED( info.m_nflBorderNoiseScale ) ? params[info.m_nflBorderNoiseScale]->GetFloatValue() : kDefaultBorderNoiseScale; + + // Debug force flesh on + vVsConst0[3] = IS_PARAM_DEFINED( info.m_nflDebugForceFleshOn ) ? params[info.m_nflDebugForceFleshOn]->GetFloatValue() : kDefaultDebugForceFleshOn; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vVsConst0, 1 ); + + // Flesh effect centers and radii + float vVsConst1[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius1 ) ) + { + params[info.m_nvEffectCenterRadius1]->GetVecValue( vVsConst1, 4 ); + if ( vVsConst1[3] < 0.001f ) + vVsConst1[3] = 0.001f; + vVsConst1[3] = 1.0f / vVsConst1[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vVsConst1, 1 ); + + float vVsConst2[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius2 ) ) + { + params[info.m_nvEffectCenterRadius2]->GetVecValue( vVsConst2, 4 ); + if ( vVsConst2[3] < 0.001f ) + vVsConst2[3] = 0.001f; + vVsConst2[3] = 1.0f / vVsConst2[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vVsConst2, 2 ); + + float vVsConst3[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius3 ) ) + { + params[info.m_nvEffectCenterRadius3]->GetVecValue( vVsConst3, 4 ); + if ( vVsConst3[3] < 0.001f ) + vVsConst3[3] = 0.001f; + vVsConst3[3] = 1.0f / vVsConst3[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vVsConst3, 3 ); + + float vVsConst4[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius4 ) ) + { + params[info.m_nvEffectCenterRadius4]->GetVecValue( vVsConst4, 4 ); + if ( vVsConst4[3] < 0.001f ) + vVsConst4[3] = 0.001f; + vVsConst4[3] = 1.0f / vVsConst4[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, vVsConst4, 4 ); + + // Set Pixel Shader Combos + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + } + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nFleshTexture ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nFleshNoiseTexture ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nFleshBorderTexture1D ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nFleshNormalTexture ); + pShader->BindTexture( SHADER_SAMPLER4, info.m_nFleshSubsurfaceTexture ); + pShader->BindTexture( SHADER_SAMPLER5, info.m_nFleshCubeTexture ); + + // Set Pixel Shader Constants + + // Subsurface tint + pShaderAPI->SetPixelShaderConstant( 0, IS_PARAM_DEFINED( info.m_ncSubsurfaceTint ) ? params[info.m_ncSubsurfaceTint]->GetVecValue() : kDefaultSubsurfaceTint, 1 ); + + // Border width + float vPsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst1[0] = IS_PARAM_DEFINED( info.m_nflBorderWidth ) ? params[info.m_nflBorderWidth]->GetFloatValue() : kDefaultBorderWidth; + vPsConst1[0] = 1.0f / vPsConst1[0]; // ( 1.0f / g_flBorderWidthFromVmt ) + vPsConst1[1] = vPsConst1[0] - 1.0f; // ( 1.0f / g_flBorderWidthFromVmt ) - 1.0f + pShaderAPI->SetPixelShaderConstant( 1, vPsConst1, 1 ); + + // Border softness + float vPsConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst2[0] = IS_PARAM_DEFINED( info.m_nflBorderSoftness ) ? params[info.m_nflBorderSoftness]->GetFloatValue() : kDefaultBorderSoftness; + if ( vPsConst2[0] < 0.01f ) + vPsConst2[0] = 0.01f; + else if ( vPsConst2[0] > 0.5f ) + vPsConst2[0] = 0.5f; + pShaderAPI->SetPixelShaderConstant( 2, vPsConst2, 1 ); + + // Border color tint + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_ncBorderTint ) ? params[info.m_ncBorderTint]->GetVecValue() : kDefaultBorderTint, 1 ); + + // Global opacity + float vPsConst4[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst4[0] = IS_PARAM_DEFINED( info.m_nflGlobalOpacity ) ? params[info.m_nflGlobalOpacity]->GetFloatValue() : kDefaultGlobalOpacity; + pShaderAPI->SetPixelShaderConstant( 4, vPsConst4, 1 ); + + // Gloss brightness + float vPsConst5[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst5[0] = IS_PARAM_DEFINED( info.m_nflGlossBrightness ) ? params[info.m_nflGlossBrightness]->GetFloatValue() : kDefaultGlossBrightness; + pShaderAPI->SetPixelShaderConstant( 5, vPsConst5, 1 ); + } + pShader->Draw(); +} diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h new file mode 100644 index 00000000..92b8d57a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h @@ -0,0 +1,68 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef FLESH_INTERIOR_BLENDED_PASS_HELPER_H +#define FLESH_INTERIOR_BLENDED_PASS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct FleshInteriorBlendedPassVars_t +{ + FleshInteriorBlendedPassVars_t() { memset( this, 0xFF, sizeof(FleshInteriorBlendedPassVars_t) ); } + + int m_nFleshTexture; + int m_nFleshNoiseTexture; + int m_nFleshBorderTexture1D; + int m_nFleshNormalTexture; + int m_nFleshSubsurfaceTexture; + int m_nFleshCubeTexture; + + int m_nflBorderNoiseScale; + int m_nflDebugForceFleshOn; + int m_nvEffectCenterRadius1; + int m_nvEffectCenterRadius2; + int m_nvEffectCenterRadius3; + int m_nvEffectCenterRadius4; + + int m_ncSubsurfaceTint; + int m_nflBorderWidth; + int m_nflBorderSoftness; // > 0.0f && < 0.5f ! + int m_ncBorderTint; + int m_nflGlobalOpacity; + int m_nflGlossBrightness; + int m_nflScrollSpeed; + + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultBorderNoiseScale = 1.5f; +static const float kDefaultDebugForceFleshOn = 0.0f; +static const float kDefaultEffectCenterRadius[4] = { 0.0f, 0.0f, 0.0f, 0.0001f }; // Disabled by default +static const float kDefaultSubsurfaceTint[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Disabled by default +static const float kDefaultBorderWidth = 0.3f; +static const float kDefaultBorderSoftness = 0.42f; // > 0.0f && < 0.5f ! +static const float kDefaultBorderTint[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; +static const float kDefaultGlobalOpacity = 1.0f; +static const float kDefaultGlossBrightness = 0.66f; +static const float kDefaultScrollSpeed = 1.0f; + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ); +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ); +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // FLESH_INTERIOR_BLENDED_PASS_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc new file mode 100644 index 00000000..3e288e56 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc @@ -0,0 +1,127 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// +// Includes ======================================================================================= +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tBaseSampler : register( s0 ); +sampler g_tNoiseSampler : register( s1 ); +sampler g_tBorder1DSampler : register( s2 ); +sampler g_tNormalSampler : register( s3 ); +sampler g_tSubsurfaceSampler: register( s4 ); +sampler g_tCubeSampler : register( s5 ); + +// Shaders Constants and Globals ================================================================== +const float3 g_cSubsurfaceTint : register( c0 ); +const float2 g_flBorderWidth : register( c1 ); //{ 1.0f / g_flBorderWidthFromVmt, ( 1.0f / g_flBorderWidthFromVmt ) - 1.0f }; +const float g_flBorderSoftness : register( c2 ); +const float3 g_cBorderTint : register( c3 ); +const float g_flGlobalOpacity : register( c4 ); +const float g_flGlossBrightness : register( c5 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 flDistanceToEffectCenter_flFresnelEffect : TEXCOORD1; + float4 vNoiseTexCoord : TEXCOORD2; + float3 vTangentViewVector : TEXCOORD3; + float3 cVertexLight : TEXCOORD4; + float3x3 mTangentSpaceTranspose : TEXCOORD5; + // second row : TEXCOORD6; + // third row : TEXCOORD7; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Color texture + float4 cBaseColor = tex2D( g_tBaseSampler, i.vTexCoord0.xy ); + float flFleshMaskFromTexture = cBaseColor.a; + + // Subsurface colors + float4 cSubsurfaceColor = tex2D( g_tSubsurfaceSampler, i.vTexCoord0.xy ); + cBaseColor.rgb += cBaseColor.rgb * cSubsurfaceColor.rgb * g_cSubsurfaceTint.rgb; + + // Scroll noise textures to ripple border of opening + float flNoise0 = tex2D( g_tNoiseSampler, i.vNoiseTexCoord.xy ).g; // Use green so we can DXT1 if we want + float flNoise1 = tex2D( g_tNoiseSampler, i.vNoiseTexCoord.wz ).g; // Use green so we can DXT1 if we want + float flNoise = ( flNoise0 + flNoise1 ) * 0.5f; + + // Generate 0-1 mask from distance computed in the VS + float flClampedInputMask = 0.0f; + flClampedInputMask = 1.0f - saturate( i.flDistanceToEffectCenter_flFresnelEffect.x ); + flClampedInputMask *= i.flDistanceToEffectCenter_flFresnelEffect.y; + flClampedInputMask *= flFleshMaskFromTexture; + + // Noise mask - Only apply noise around border of sphere + float flBorderMask = saturate( ( 1.0f - flClampedInputMask ) * g_flBorderWidth.x - g_flBorderWidth.y ); + float flNoiseMask = 1.0f - abs( ( flBorderMask * 2.0f ) - 1.0f ); + + // This is used to lerp in the 1D border texture over the flesh color + float flBorderMaskWithNoise = ( 1.0f - smoothstep( flNoiseMask - g_flBorderSoftness, flNoiseMask + g_flBorderSoftness, flNoise.r ) ) * flNoiseMask; + + // Border color + float vBorderUv = ( sign( flBorderMask - 0.5 ) * (1.0f - pow( flBorderMaskWithNoise, 4.0f )) * 0.5f ) + 0.5f; + float4 cBorderColor = 2.0f * tex2D( g_tBorder1DSampler, vBorderUv ); + cBorderColor.rgb *= g_cBorderTint; + cBorderColor.rgb *= flNoise; + + // Normal map + float4 vNormalMapValue = tex2D( g_tNormalSampler, i.vTexCoord0.xy ); + float3 vTangentNormal = ( vNormalMapValue.xyz * 2.0f ) - 1.0f; + vTangentNormal.xy += ( flNoise * 1.5f ) - 0.75f; // NOTE: This will denormalize the normal. + //float3 vWorldNormal = mul( i.mTangentSpaceTranspose, vTangentNormal.xyz ); + + // Specular gloss layer + float3 vTangentReflectionVector = reflect( i.vTangentViewVector.xyz, vTangentNormal.xyz ); + //vTangentReflectionVector.xy += ( flNoise * 1.5f ) - 0.75f; + float3 vWorldReflectionVector = mul( i.mTangentSpaceTranspose, vTangentReflectionVector.xyz ); + float3 cGlossLayer = ENV_MAP_SCALE * texCUBE( g_tCubeSampler, vWorldReflectionVector.xyz ).rgb; + cGlossLayer.rgb *= g_flGlossBrightness; + + // Gloss mask is just hard-coded fresnel for now + float flGlossMask = pow( saturate( dot( vTangentNormal.xyz, -i.vTangentViewVector.xyz ) ), 8.0f ); + + // Opacity + float flOpacity = 1.0f; + flOpacity = max( flBorderMaskWithNoise, step( flBorderMask, 0.5f ) ); + + // Apply global opacity + flOpacity *= g_flGlobalOpacity; + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cBaseColor.rgb * i.cVertexLight.rgb; + result.rgb += cGlossLayer.rgb * flGlossMask; + result.rgb *= pow( 1.0f - flBorderMaskWithNoise, 2.0f ); // Darken near border + result.rgb = lerp( result.rgb, cBorderColor.rgb, saturate( vBorderUv * 2.0f ) ); // bring in transition 1D texture + + //result.rgb = flClampedInputMask; + //result.rgb = flBorderMask; + //result.rgb = saturate( flClampedInputMask * 2.0f ); + //result.rgb = i.flDistanceToEffectCenter_flFresnelEffect.x;// * i.flDistanceToEffectCenter_flFresnelEffect.y; + //result.rgb = i.flDistanceToEffectCenter_flFresnelEffect.y * g_flBorderWidth.x - g_flBorderWidth.y; + //result.rgb = flNoiseMask; + //result.rgb = flBorderMaskWithNoise; + //result.rgb = flOpacity; + //result.rgb = flBorderUv; + //result.rgb = cBorderColor; + //result.rgb = -i.vTangentViewVector.z; + //result.rgb = vNormalMapValue.xyz; + //result.rgb = vTangentNormal.xyz; + //result.rgb = flGlossLayer; + //result.rgb = i.cVertexLight.rgb; + //result.rgb = texCUBE( g_tCubeSampler, vTangentNormal.xyz ).rgb; + //result.rgb = i.vTangentViewVector.x; + //result.rgb = cGlossLayer.rgb; + + // Set alpha for blending + result.a = flOpacity; + //result.a = 1.0f; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} diff --git a/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc new file mode 100644 index 00000000..2a361b01 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc @@ -0,0 +1,155 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const int g_iFogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 g_vConst0 : register( SHADER_SPECIFIC_CONST_0 ); +#define g_flTime g_vConst0.x +#define g_flNoiseUvScroll g_vConst0.y +#define g_flBorderNoiseScale g_vConst0.z +#define g_flDebugForceFleshOn g_vConst0.w + +const float4 g_vEffectCenterOoRadius1 : register( SHADER_SPECIFIC_CONST_1 ); //= { -295.0f, -5.0f, 40.0f, 1.0f/20.0f }; +const float4 g_vEffectCenterOoRadius2 : register( SHADER_SPECIFIC_CONST_2 ); //= { -295.0f, 15.0f, 40.0f, 1.0f/10.0f }; +const float4 g_vEffectCenterOoRadius3 : register( SHADER_SPECIFIC_CONST_3 ); //= { -295.0f, 35.0f, 40.0f, 1.0f/10.0f }; +const float4 g_vEffectCenterOoRadius4 : register( SHADER_SPECIFIC_CONST_4 ); //= { -295.0f, 55.0f, 40.0f, 1.0f/10.0f }; + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float3 vPosFlex : POSITION1; // Delta positions for flexing + float4 vTangent : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float2 vTexCoord0 : TEXCOORD0; + float2 flDistanceToEffectCenter_flFresnelEffect : TEXCOORD1; + float4 vNoiseTexCoord : TEXCOORD2; + float3 vTangentViewVector : TEXCOORD3; + float3 cVertexLight : TEXCOORD4; + float3x3 mTangentSpaceTranspose : TEXCOORD5; + // second row : TEXCOORD6; + // third row : TEXCOORD7; + +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Flexes coming in from a separate stream (contribution masked by cFlexScale.x) + float4 vObjPosition = i.vPos; + vObjPosition.xyz += i.vPosFlex.xyz * cFlexScale.x; + + float3 vObjNormal; + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vTangent, vObjNormal, vObjTangent ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal, vObjTangent, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // Pass through tex coords + o.vTexCoord0.xy = i.vTexCoord0.xy; + + // Store the closest effect intensity + o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius1.xyz ) * g_vEffectCenterOoRadius1.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius2.xyz ) * g_vEffectCenterOoRadius2.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius3.xyz ) * g_vEffectCenterOoRadius3.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius4.xyz ) * g_vEffectCenterOoRadius4.w ); + + /* + // Test values for development in Alyx_interior map + o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + float3 vTestPosition = { -295.0f, -5.0f, 40.0f }; + float flMinY = -5.0f; + float flMaxY = 66.0f; + vTestPosition.y = lerp( flMinY, flMaxY, ( abs( frac( g_flTime / 20.0f ) * 2.0 - 1.0 ) ) ); + //vTestPosition.y = lerp( flMinY, flMaxY, 0.65f ); + + //1.0f - saturate( i.flDistanceToEffectCenter_flFresnelEffect.x * 4.0f - 3.0f ) + + //o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + + const float g_flInteriorRadius = 20.0f; + if ( g_flInteriorRadius ) + { + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - vTestPosition.xyz ) / g_flInteriorRadius ); + } + + const float g_flInteriorRadius2 = 14.0f; + if ( g_flInteriorRadius2 ) + { + vTestPosition.y = lerp( flMinY, flMaxY, 0.65f ); + //vTestPosition.z = lerp( 37, 45, ( abs( frac( g_flTime / 4.0f ) * 2.0 - 1.0 ) ) ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - vTestPosition.xyz ) / g_flInteriorRadius2 ); + } + //*/ + + if ( g_flDebugForceFleshOn ) + { + o.flDistanceToEffectCenter_flFresnelEffect.x = 0.0f; + } + + // Fresnel mask + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + o.flDistanceToEffectCenter_flFresnelEffect.y = pow( saturate( dot( -vWorldViewVector.xyz, vWorldNormal.xyz ) ), 1.5f ); + + // Noise UV + o.vNoiseTexCoord.xy = o.vTexCoord0.xy * g_flBorderNoiseScale + g_flNoiseUvScroll; + o.vNoiseTexCoord.zw = o.vTexCoord0.xy * g_flBorderNoiseScale - g_flNoiseUvScroll; // Will fetch as wz to avoid matching layers + + // Tangent view vector + o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized( vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Compute vertex lighting + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + +#if ( USE_STATIC_CONTROL_FLOW ) || defined ( SHADER_MODEL_VS_3_0 ) + o.cVertexLight.rgb = DoLighting( vWorldPosition, vWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert ); +#else + o.cVertexLight.rgb = DoLightingUnrolled( vWorldPosition, vWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); +#endif + + // Tangent space transform + o.mTangentSpaceTranspose[0] = float3( vWorldTangent.x, vWorldBinormal.x, vWorldNormal.x ); + o.mTangentSpaceTranspose[1] = float3( vWorldTangent.y, vWorldBinormal.y, vWorldNormal.y ); + o.mTangentSpaceTranspose[2] = float3( vWorldTangent.z, vWorldBinormal.z, vWorldNormal.z ); + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_basealphamaskedenvmap.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_basealphamaskedenvmap.psh new file mode 100644 index 00000000..fbb4393f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_basealphamaskedenvmap.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r1, t2, 1-t3.a ; envmap * envmapmask alpha +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_basetextureblend.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_basetextureblend.psh new file mode 100644 index 00000000..9380ec63 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_basetextureblend.psh @@ -0,0 +1,9 @@ +ps.1.1 + +tex t0 ; base 1 +tex t1 ; base 2 + +mov r1, t1 +lrp r0, 1-v0.a, t0, r1 +mul r0, r0, c0 + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal.cpp b/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal.cpp new file mode 100644 index 00000000..9e74b5cf --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal.cpp @@ -0,0 +1,135 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "lightmappedgeneric_decal.inc" +#include "mathlib/bumpvects.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( LightmappedGeneric_Decal, + "Help for LightmappedGeneric_Decal" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + SET_FLAGS( MATERIAL_VAR_DECAL ); + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if ( !params[BASETEXTURE]->GetTextureValue()->IsTranslucent() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + } + + void DrawDecal( IMaterialVar **params, IShaderDynamicAPI *pShaderAPI, IShaderShadow *pShaderShadow ) + { + if( IsSnapshotting() ) + { + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + SetNormalBlendingShadowState( BASETEXTURE, true ); + + int pTexCoords[3] = { 2, 2, 1 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION | VERTEX_COLOR, 3, pTexCoords, 0 ); + + lightmappedgeneric_decal_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "LightmappedGeneric_Decal", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "LightmappedGeneric_Decal" ); + FogToFogColor(); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Load the z^2 components of the lightmap coordinate axes only + // This is (N dot basis)^2 + Vector vecZValues( g_localBumpBasis[0].z, g_localBumpBasis[1].z, g_localBumpBasis[2].z ); + vecZValues *= vecZValues; + + Vector4D basis[3]; + basis[0].Init( vecZValues.x, vecZValues.x, vecZValues.x, 0.0f ); + basis[1].Init( vecZValues.y, vecZValues.y, vecZValues.y, 0.0f ); + basis[2].Init( vecZValues.z, vecZValues.z, vecZValues.z, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 0, (float*)basis, 3 ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_decal_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + if( UsingFlashlight( params ) ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + } + else + { + DrawDecal( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc new file mode 100644 index 00000000..fd457be8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc @@ -0,0 +1,59 @@ +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler LightMap0Sampler : register( s1 ); +sampler LightMap1Sampler : register( s2 ); +sampler LightMap2Sampler : register( s3 ); + +const float4 g_LightMap0Color : register( c0 ); +const float4 g_LightMap1Color : register( c1 ); +const float4 g_LightMap2Color : register( c2 ); +const float4 g_ModulationColor : register( c3 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + + +struct PS_INPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + float4 worldPos_projPosZ : TEXCOORD4; // Necessary for pixel fog + + float4 vColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 resultColor; + + // output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + + // lightmapColor[1] * ( ( N dot basis[1] )^2 ) + + // lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + resultColor = tex2D( LightMap0Sampler, i.vTexCoord1 ) * g_LightMap0Color; + resultColor = (tex2D( LightMap1Sampler, i.vTexCoord2 ) * g_LightMap1Color) + resultColor; + resultColor = (tex2D( LightMap2Sampler, i.vTexCoord3 ) * g_LightMap2Color) + resultColor; + + // Modulate by decal texture + float4 decalColor = tex2D( BaseTextureSampler, i.vTexCoord0 ); + resultColor.rgb = resultColor * decalColor; + resultColor.a = decalColor.a; + + // Modulate by constant color + resultColor = resultColor * g_ModulationColor; + + // Modulate by per-vertex factor + resultColor = resultColor * i.vColor; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc new file mode 100644 index 00000000..0b7db284 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc @@ -0,0 +1,74 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cShaderConst0 : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cShaderConst1 : register( SHADER_SPECIFIC_CONST_1 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + + float4 worldPos_projPosZ : TEXCOORD4; // Necessary for pixel fog + + float4 vColor : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + + // Compute the texture coordinates given the offset between + // each bumped lightmap + float2 offset; + offset.x = v.vTexCoord2.x; + offset.y = 0.0f; + + o.vTexCoord0.x = dot( v.vTexCoord0, cShaderConst0 ); + o.vTexCoord0.y = dot( v.vTexCoord0, cShaderConst1 ); + + o.vTexCoord1 = offset + v.vTexCoord1.xy; + o.vTexCoord2 = (offset * 2.0) + v.vTexCoord1.xy; + o.vTexCoord3 = (offset * 3.0) + v.vTexCoord1.xy; + + o.vColor = v.vColor; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx6.cpp b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx6.cpp new file mode 100644 index 00000000..f55f8883 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx6.cpp @@ -0,0 +1,288 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( LightmappedGeneric, LightmappedGeneric_DX6 ) + +BEGIN_SHADER( LightmappedGeneric_DX6, + "Help for LightmappedGeneric_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "90", "Do specular pass only on dxlevel or higher (ie.80, 81, 90)" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( params[BASETEXTURE]->IsDefined() ) + { + if( !IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) + { + params[ENVMAP]->SetUndefined(); + params[ENVMAPMASK]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + LoadCubeMap( ENVMAP ); + } + else + { + LoadTexture( ENVMAP ); + } + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + { + LoadTexture( ENVMAPMASK ); + } + } + } + + SHADER_FALLBACK + { + return 0; + } + + int GetDrawFlagsPass1(IMaterialVar** params) + { + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD0; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + if (params[BASETEXTURE]->IsTexture()) + flags |= SHADER_DRAW_TEXCOORD1; + return flags; + } + + void DrawLightmapOnly( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + + SetModulationShadowState(); + SetDefaultBlendingShadowState( ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) ); + DefaultFog(); + } + DYNAMIC_STATE + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + SetModulationDynamicState(); + } + Draw(); + } + + void DrawBaseTimesLightmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Base times lightmap + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Alpha blending + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + // Independenly configure alpha and color + pShaderShadow->EnableAlphaPipe( true ); + + // color channel + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->EnableConstantColor( IsColorModulating() ); + + // alpha channel + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + if ((! IsColorModulating()) && ( ! IsAlphaModulating())) + pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) ); + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, TextureIsTranslucent(BASETEXTURE, true) ); + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, false ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD1; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + { + if ( (! IsColorModulating()) && ( ! IsAlphaModulating())) + flags |= SHADER_DRAW_COLOR; + + } + if (params[BASETEXTURE]->IsTexture()) + { + flags |= SHADER_DRAW_TEXCOORD0; + } + + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + SetModulationDynamicState(); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableAlphaPipe( false ); + } + } + + void DrawMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Pass 1 : Base * lightmap or just lightmap + if ( params[BASETEXTURE]->IsTexture() ) + { + DrawBaseTimesLightmap( params, pShaderAPI, pShaderShadow ); + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Draw the selfillum pass + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + else + { + DrawLightmapOnly( params, pShaderAPI, pShaderShadow ); + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + + // Pass 2 : Masked environment map + if (params[ENVMAP]->IsTexture()) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + } + else + { + // Base * Lightmap + env + DrawMode1( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// This allows us to use a block labelled 'Water_DX60' in the water materials +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( Water_DX60, LightmappedGeneric_DX6, "Help for Water_DX60" ) +END_INHERITED_SHADER + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp new file mode 100644 index 00000000..8464f94f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp @@ -0,0 +1,802 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + + +#include "lightmappedgeneric_vs11.inc" +#include "unlitgeneric_vs11.inc" +#include "worldvertextransition_seamless.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +DEFINE_FALLBACK_SHADER( LightmappedGeneric, LightmappedGeneric_DX8 ) + +BEGIN_VS_SHADER( LightmappedGeneric_DX8, + "Help for LightmappedGeneric_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "amount of detail texture to apply" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_INTEGER, "90", "Do specular pass only on dxlevel or higher (ie.80, 81, 90)" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_BOOL, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( FORCEBUMP, SHADER_PARAM_TYPE_BOOL, "0", "0 == Do bumpmapping if the card says it can handle it. 1 == Always do bumpmapping." ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + END_SHADER_PARAMS + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + return g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined(); + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( ShouldUseBumpmapping( params ) && params[ALBEDO]->IsDefined() && + params[BASETEXTURE]->IsDefined() && + !( params[NODIFFUSEBUMPLIGHTING]->IsDefined() && params[NODIFFUSEBUMPLIGHTING]->GetIntValue() ) ) + { + params[BASETEXTURE]->SetStringValue( params[ALBEDO]->GetStringValue() ); + } + + if( IsUsingGraphics() && params[ENVMAP]->IsDefined() && !CanUseEditorMaterials() ) + { + if( stricmp( params[ENVMAP]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + { + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[DETAILBLENDFACTOR]->IsDefined() ) + { + params[DETAILBLENDFACTOR]->SetFloatValue( 1.0f ); + } + + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + { + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + + if( !params[ALPHATESTREFERENCE]->IsDefined() ) + { + params[ALPHATESTREFERENCE]->SetFloatValue( 0.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( ShouldUseBumpmapping( params ) && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && (params[ENVMAPOPTIONAL]->GetIntValue() > g_pHardwareConfig->GetDXSupportLevel()) ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + if( params[SEAMLESS_SCALE]->IsDefined() && params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + if( params[BUMPMAP]->IsDefined() ) + { + Warning( "Can't use $bumpmap with $seamless_scale for lightmappedgeneric_dx8. Implicitly disabling $bumpmap: %s\n", pMaterialName ); + params[BUMPMAP]->SetUndefined(); + } + if( params[ENVMAP]->IsDefined() ) + { + Warning( "Can't use $envmap with $seamless_scale for lightmappedgeneric_dx8. Implicitly disabling $envmap: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if ( !params[SEAMLESS_SCALE]->IsDefined() ) + { + // zero means don't do seamless mapping. + params[SEAMLESS_SCALE]->SetFloatValue( 0.0f ); + } + + // Get rid of envmap if we aren't using bumpmapping + // *and* we have normalmapalphaenvmapmask *and* we don't have envmapmask elsewhere + if ( params[ENVMAP]->IsDefined() && params[BUMPMAP]->IsDefined() && IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) && !ShouldUseBumpmapping( params ) ) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) && !params[ENVMAPMASK]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + } + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80) + return "LightmappedGeneric_DX6"; + + if ( IsPC() && g_pHardwareConfig->PreferReducedFillrate() ) + return "LightmappedGeneric_NoBump_DX8"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + + if( ShouldUseBumpmapping( params ) ) + { + LoadBumpMap( BUMPMAP ); + } + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + + if( ShouldUseBumpmapping( params ) ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + } + +#ifndef USE_HLSL_PIXEL_SHADERS + inline const char *GetPixelShaderName( IMaterialVar** params, bool bBumpedEnvMap ) + { + static char const* s_pPixelShaders[] = + { + // Unmasked + "LightmappedGeneric_EnvMapV2", + "LightmappedGeneric_SelfIlluminatedEnvMapV2", + + "LightmappedGeneric_BaseAlphaMaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedEnvMapV2", + + // Env map mask + "LightmappedGeneric_MaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2", + + "LightmappedGeneric_MaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2", + }; + + if (!params[BASETEXTURE]->IsTexture()) + { + if (params[ENVMAP]->IsTexture() && !bBumpedEnvMap ) + { + if (!params[ENVMAPMASK]->IsDefined() ) + { + return "LightmappedGeneric_EnvmapNoTexture"; + } + else + { + return "LightmappedGeneric_MaskedEnvmapNoTexture"; + } + } + else + { + return "LightmappedGeneric_NoTexture"; + } + } + else + { + if (params[ENVMAP]->IsTexture() && !bBumpedEnvMap ) + { + int pshIndex = 0; + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + pshIndex |= 0x1; + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pshIndex |= 0x2; + if (params[ENVMAPMASK]->IsTexture()) + pshIndex |= 0x4; + return s_pPixelShaders[pshIndex]; + } + else + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + return "LightmappedGeneric_SelfIlluminated"; + else + return "LightmappedGeneric"; + } + } + } +#endif + + void DrawUnbumpedUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + bool hasEnvmap = params[ENVMAP]->IsTexture() && !bBumpedEnvMap; + bool hasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasEnvmapCameraSpace = IS_FLAG_SET( MATERIAL_VAR_ENVMAPCAMERASPACE ); + bool hasEnvmapSphere = IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ); + + if ( hasEnvmap || hasBaseTexture || hasVertexColor || !bBumpedEnvMap ) + { + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + if ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + + // Base texture on stage 0 + if (params[BASETEXTURE]->IsTexture()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + + // Lightmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + + if ( hasEnvmap ) + { + fmt |= VERTEX_NORMAL; + + // envmap on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // envmapmask on stage 3 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + } + + if (params[BASETEXTURE]->IsTexture() || bBumpedEnvMap) + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetDefaultBlendingShadowState( ENVMAPMASK, false ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + { + fmt |= VERTEX_COLOR; + } + + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( hasEnvmap ); + vshIndex.SetENVMAPCAMERASPACE( hasEnvmap && hasEnvmapCameraSpace ); + vshIndex.SetENVMAPSPHERE( hasEnvmap && hasEnvmapSphere ); + vshIndex.SetVERTEXCOLOR( hasVertexColor ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetPixelShaderName( params, bBumpedEnvMap ); + pShaderShadow->SetPixelShader( pshName ); + DefaultFog(); + } + DYNAMIC_STATE + { + if (hasBaseTexture) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( hasEnvmap ) + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + if (params[ENVMAPMASK]->IsTexture() ) + BindTexture( SHADER_SAMPLER3, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || + IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + SetEnvMapTintPixelShaderDynamicState( 2, ENVMAPTINT, -1 ); + } + + if ( !hasEnvmap || hasBaseTexture || hasVertexColor ) + { + SetModulationVertexShaderDynamicState(); + } + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + if ( bBumpedEnvMap ) + { + DrawWorldBumpedSpecularLighting( + BUMPMAP, ENVMAP, BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + hasEnvmap || hasBaseTexture || hasVertexColor ); + } + } + + void DrawDetailNoEnvmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doSelfIllum ) + { + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Base texture on stage 0 + if (params[BASETEXTURE]->IsTexture()) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Lightmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Detail on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + fmt |= VERTEX_COLOR; + + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( true ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + if (!params[BASETEXTURE]->IsTexture()) + { + pShaderShadow->SetPixelShader("LightmappedGeneric_DetailNoTexture"); + } + else + { + if (!IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || (!doSelfIllum)) + { + pShaderShadow->SetPixelShader("LightmappedGeneric_Detail"); + } + else + { + pShaderShadow->SetPixelShader("LightmappedGeneric_DetailSelfIlluminated"); + } + } + DefaultFog(); + } + DYNAMIC_STATE + { + if (params[BASETEXTURE]->IsTexture()) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + BindTexture( SHADER_SAMPLER2, DETAIL, FRAME ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + + SetModulationVertexShaderDynamicState(); + EnablePixelShaderOverbright( 0, true, true ); + + if (doSelfIllum) + { + SetPixelShaderConstant( 1, SELFILLUMTINT ); + } + float c2[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c2[0] = c2[1] = c2[2] = c2[3] = params[DETAILBLENDFACTOR]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline const char *GetAdditiveEnvmapPixelShaderName( bool usingMask, + bool usingBaseTexture, bool usingBaseAlphaEnvmapMask ) + { + static char const* s_pPixelShaders[] = + { + "LightmappedGeneric_AddEnvmapNoTexture", + "LightmappedGeneric_AddEnvmapMaskNoTexture", + }; + + if ( !usingMask && usingBaseTexture && usingBaseAlphaEnvmapMask ) + return "LightmappedGeneric_AddBaseAlphaMaskedEnvMap"; + + int pshIndex = 0; + if (usingMask) + pshIndex |= 0x1; + return s_pPixelShaders[pshIndex]; + } + + void DrawAdditiveEnvmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + bool usingBaseTexture = params[BASETEXTURE]->IsTexture(); + bool usingMask = params[ENVMAPMASK]->IsTexture(); + bool usingBaseAlphaEnvmapMask = IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK); + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + + // envmap on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // envmapmask on stage 3 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + if (params[BASETEXTURE]->IsTexture()) + { + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetAdditiveBlendingShadowState( ENVMAPMASK, false ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // Compute the vertex shader index. + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( true ); + vshIndex.SetENVMAPCAMERASPACE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ); + vshIndex.SetENVMAPSPHERE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ); + vshIndex.SetVERTEXCOLOR( false ); + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetAdditiveEnvmapPixelShaderName( usingMask, + usingBaseTexture, usingBaseAlphaEnvmapMask ); + pShaderShadow->SetPixelShader( pshName ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + + if (usingMask || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + { + if (usingMask) + BindTexture( SHADER_SAMPLER3, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + SetPixelShaderConstant( 2, ENVMAPTINT ); + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + + SetModulationVertexShaderDynamicState(); + + // Compute the vertex shader index. + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + void DrawDetailMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + // Mode 1 : + // Pass 1 : B * L * D + Self Illum + // Pass 2 : Add E * M + + // Draw the detail w/ no envmap + DrawDetailNoEnvmap( params, pShaderAPI, pShaderShadow, true ); + + if ( !bBumpedEnvMap ) + { + DrawAdditiveEnvmap( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawWorldBumpedSpecularLighting( + BUMPMAP, ENVMAP, BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + true ); + } + } + + void DrawDetailUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + // We don't have enough textures; gotta do this in two passes if there's envmapping + if (!params[ENVMAP]->IsTexture()) + { + DrawDetailNoEnvmap( params, pShaderAPI, pShaderShadow, IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) ); + } + else + { + if (!params[BASETEXTURE]->IsTexture()) + { + // If there's an envmap but no base texture, ignore detail + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + else + { + DrawDetailMode1( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + } + + void DrawUnbumpedSeamlessUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // This is the seamless_scale version, which doesn't use $detail or $bumpmap + SHADOW_STATE + { + // three copies of the base texture for seamless blending + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_seamless_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_Seamless", vshIndex.GetIndex() ); + + int pshIndex = 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_Seamless", pshIndex ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + // Texture 0..2 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + float fSeamlessScale = params[SEAMLESS_SCALE]->GetFloatValue(); + float map_scale[4]= { fSeamlessScale, fSeamlessScale, fSeamlessScale, fSeamlessScale }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + + worldvertextransition_seamless_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + bool bBump = ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture() && + (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0); + bool bSSBump = bBump && ( params[SSBUMP]->GetIntValue() != 0 ); + + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + } + else if( bBump ) + { + DrawWorldBumpedUsingVertexShader( + BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, + ENVMAPFRAME, ENVMAPTINT, COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, FRESNELREFLECTION, + false, -1, -1, -1, bSSBump ); + } + else + { + bool bBumpedEnvMap = ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture() && params[ENVMAP]->IsTexture(); + if (!params[DETAIL]->IsTexture()) + { + if( params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + DrawUnbumpedSeamlessUsingVertexShader( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + else + { + DrawDetailUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// Version that doesn't do bumpmapping +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( LightmappedGeneric_NoBump_DX8, LightmappedGeneric_DX8, + "Help for LightmappedGeneric_NoBump_DX8" ) + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 80) + return "LightmappedGeneric_DX6"; + + return 0; + } + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + if ( !g_pConfig->UseBumpmapping() ) + return false; + + if ( !params[BUMPMAP]->IsDefined() ) + return false; + + return ( params[FORCEBUMP]->GetIntValue() != 0 ); + } + +END_INHERITED_SHADER diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp new file mode 100644 index 00000000..bac124a8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp @@ -0,0 +1,164 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "lightmappedgeneric_dx9_helper.h" + +static LightmappedGeneric_DX9_Vars_t s_info; + + +BEGIN_VS_SHADER( LightmappedGeneric, + "Help for LightmappedGeneric" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + + SHADER_PARAM( ALPHA2, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( BUMPMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( BUMPMASK, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/lightmappedtexture", "Blended texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $basetexture2" ) + SHADER_PARAM( BASETEXTURENOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BASETEXTURE2NOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "light munging lookup texture" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( MASKEDBLENDING, SHADER_PARAM_TYPE_INTEGER, "0", "blend using texture with no vertex alpha. For using texture blending on non-displacements" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") +END_SHADER_PARAMS + + void SetupVars( LightmappedGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + + info.m_nAlpha2 = ALPHA2; + + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTint = DETAILTINT; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoDiffuseBumpLighting = NODIFFUSEBUMPLIGHTING; + info.m_nBumpmap2 = BUMPMAP2; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBumpMask = BUMPMASK; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nBaseTexture2Frame = FRAME2; + info.m_nBaseTextureNoEnvmap = BASETEXTURENOENVMAP; + info.m_nBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP; + info.m_nDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nLightWarpTexture = LIGHTWARPTEXTURE; + info.m_nBlendModulateTexture = BLENDMODULATETEXTURE; + info.m_nMaskedBlending = MASKEDBLENDING; + info.m_nBlendMaskTransform = BLENDMASKTRANSFORM; + info.m_nSelfShadowedBumpFlag = SSBUMP; + info.m_nSeamlessMappingScale = SEAMLESS_SCALE; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + + info.m_nSoftEdges = SOFTEDGES; + info.m_nEdgeSoftnessStart = EDGESOFTNESSSTART; + info.m_nEdgeSoftnessEnd = EDGESOFTNESSEND; + info.m_nOutline = OUTLINE; + info.m_nOutlineColor = OUTLINECOLOR; + info.m_nOutlineAlpha = OUTLINEALPHA; + info.m_nOutlineStart0 = OUTLINESTART0; + info.m_nOutlineStart1 = OUTLINESTART1; + info.m_nOutlineEnd0 = OUTLINEEND0; + info.m_nOutlineEnd1 = OUTLINEEND1; + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "LightmappedGeneric_DX8"; + + return 0; + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + SetupVars( s_info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); + } + + SHADER_INIT + { + SetupVars( s_info ); + InitLightmappedGeneric_DX9( this, params, s_info ); + } + + SHADER_DRAW + { + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp new file mode 100644 index 00000000..9da6716d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp @@ -0,0 +1,1085 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//============================================================================= + +#include "lightmappedgeneric_dx9_helper.h" +#include "BaseVSShader.h" +#include "commandbuilder.h" +#include "convar.h" +#include "lightmappedgeneric_ps20.inc" +#include "lightmappedgeneric_vs20.inc" +#include "lightmappedgeneric_ps20b.inc" + +#include "tier0/memdbgon.h" + +ConVar mat_disable_lightwarp( "mat_disable_lightwarp", "0" ); +ConVar mat_disable_fancy_blending( "mat_disable_fancy_blending", "0" ); +ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +ConVar my_mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +extern ConVar r_flashlight_version2; + +class CLightmappedGeneric_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > m_SemiStaticCmdsOut; + + bool m_bVertexShaderFastPath; + bool m_bPixelShaderFastPath; + bool m_bPixelShaderForceFastPathBecauseOutline; + bool m_bFullyOpaque; + bool m_bFullyOpaqueWithoutAlphaTest; + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CLightmappedGeneric_DX9_Context( void ) + { + m_pStaticCmds = NULL; + } + + ~CLightmappedGeneric_DX9_Context( void ) + { + ResetStaticCmds(); + } + +}; + + +void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightmappedGeneric_DX9_Vars_t &info ) +{ + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() && + !( params[info.m_nNoDiffuseBumpLighting]->IsDefined() && params[info.m_nNoDiffuseBumpLighting]->GetIntValue() ) ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + if( pShader->IsUsingGraphics() && params[info.m_nEnvmap]->IsDefined() && !pShader->CanUseEditorMaterials() ) + { + if( stricmp( params[info.m_nEnvmap]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + } + + if ( (mat_disable_lightwarp.GetBool() ) && + (info.m_nLightWarpTexture != -1) ) + { + params[info.m_nLightWarpTexture]->SetUndefined(); + } + if ( (mat_disable_fancy_blending.GetBool() ) && + (info.m_nBlendModulateTexture != -1) ) + { + params[info.m_nBlendModulateTexture]->SetUndefined(); + } + + if( !params[info.m_nEnvmapTint]->IsDefined() ) + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[info.m_nNoDiffuseBumpLighting]->IsDefined() ) + params[info.m_nNoDiffuseBumpLighting]->SetIntValue( 0 ); + + if( !params[info.m_nSelfIllumTint]->IsDefined() ) + params[info.m_nSelfIllumTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[info.m_nDetailScale]->IsDefined() ) + params[info.m_nDetailScale]->SetFloatValue( 4.0f ); + + if ( !params[info.m_nDetailTint]->IsDefined() ) + params[info.m_nDetailTint]->SetVecValue( 1.0f, 1.0f, 1.0f, 1.0f ); + + InitFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + InitIntParam( info.m_nDetailTextureCombineMode, params, 0 ); + + if( !params[info.m_nFresnelReflection]->IsDefined() ) + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + + if( !params[info.m_nEnvmapMaskFrame]->IsDefined() ) + params[info.m_nEnvmapMaskFrame]->SetIntValue( 0 ); + + if( !params[info.m_nEnvmapFrame]->IsDefined() ) + params[info.m_nEnvmapFrame]->SetIntValue( 0 ); + + if( !params[info.m_nBumpFrame]->IsDefined() ) + params[info.m_nBumpFrame]->SetIntValue( 0 ); + + if( !params[info.m_nDetailFrame]->IsDefined() ) + params[info.m_nDetailFrame]->SetIntValue( 0 ); + + if( !params[info.m_nEnvmapContrast]->IsDefined() ) + params[info.m_nEnvmapContrast]->SetFloatValue( 0.0f ); + + if( !params[info.m_nEnvmapSaturation]->IsDefined() ) + params[info.m_nEnvmapSaturation]->SetFloatValue( 1.0f ); + + InitFloatParam( info.m_nAlphaTestReference, params, 0.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if( params[info.m_nBumpmap]->IsDefined() ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nEnvmap]->SetUndefined(); + } + + if( !params[info.m_nBaseTextureNoEnvmap]->IsDefined() ) + { + params[info.m_nBaseTextureNoEnvmap]->SetIntValue( 0 ); + } + if( !params[info.m_nBaseTexture2NoEnvmap]->IsDefined() ) + { + params[info.m_nBaseTexture2NoEnvmap]->SetIntValue( 0 ); + } + + if( ( info.m_nSelfShadowedBumpFlag != -1 ) && + ( !params[info.m_nSelfShadowedBumpFlag]->IsDefined() ) + ) + { + params[info.m_nSelfShadowedBumpFlag]->SetIntValue( 0 ); + } + // handle line art parms + InitFloatParam( info.m_nEdgeSoftnessStart, params, 0.5 ); + InitFloatParam( info.m_nEdgeSoftnessEnd, params, 0.5 ); + InitFloatParam( info.m_nOutlineAlpha, params, 1.0 ); +} + +void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ) +{ + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + } + + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap2]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap2 ); + } + + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpMask]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpMask ); + } + + if (params[info.m_nBaseTexture]->IsDefined()) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + + if (!params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[info.m_nBaseTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2, TEXTUREFLAGS_SRGB ); + } + + if (params[info.m_nLightWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nLightWarpTexture ); + } + + if ((info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsDefined()) ) + { + pShader->LoadTexture( info.m_nBlendModulateTexture ); + } + + if (params[info.m_nDetail]->IsDefined()) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + nDetailBlendMode = nDetailBlendMode > 1 ? 1 : nDetailBlendMode; + + pShader->LoadTexture( info.m_nDetail, nDetailBlendMode != 0 ? TEXTUREFLAGS_SRGB : 0 ); + } + + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if (params[info.m_nEnvmap]->IsDefined()) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + else + { + pShader->LoadTexture( info.m_nEnvmap ); + } + + if ( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if ( params[info.m_nEnvmapMask]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + } + } + else + { + params[info.m_nEnvmapMask]->SetUndefined(); + } + + // We always need this because of the flashlight. + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); +} + +void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** params, bool hasFlashlight, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, + CBasePerMaterialContextData **pContextDataPtr + ) +{ + CLightmappedGeneric_DX9_Context *pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr ); + if ( pShaderShadow || ( ! pContextData ) || pContextData->m_bMaterialVarsChanged || hasFlashlight ) + { + bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture(); + int nAlphaChannelTextureVar = hasBaseTexture ? (int)info.m_nBaseTexture : (int)info.m_nEnvmapMask; + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( nAlphaChannelTextureVar, hasBaseTexture ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bFullyOpaqueWithoutAlphaTest = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && (!hasFlashlight || IsX360()); //dest alpha is free for special use + bool bFullyOpaque = bFullyOpaqueWithoutAlphaTest && !bIsAlphaTested; + bool bNeedRegenStaticCmds = (! pContextData ) || pShaderShadow; + + if ( ! pContextData ) // make sure allocated + { + pContextData = new CLightmappedGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + + bool hasBump = ( params[info.m_nBumpmap]->IsTexture() ) && ( !g_pHardwareConfig->PreferReducedFillrate() ); + bool hasSSBump = hasBump && (info.m_nSelfShadowedBumpFlag != -1) && ( params[info.m_nSelfShadowedBumpFlag]->GetIntValue() ); + bool hasBaseTexture2 = hasBaseTexture && params[info.m_nBaseTexture2]->IsTexture(); + bool hasLightWarpTexture = params[info.m_nLightWarpTexture]->IsTexture(); + bool hasBump2 = hasBump && params[info.m_nBumpmap2]->IsTexture(); + bool hasDetailTexture = params[info.m_nDetail]->IsTexture(); + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + bool hasBumpMask = hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum && + !hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0); + bool bHasBlendModulateTexture = + (info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsTexture() ); + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if ( hasFlashlight && !IsX360() ) + { + // !!speed!! do this in the caller so we don't build struct every time + CBaseVSShader::DrawFlashlight_dx90_Vars_t vars; + vars.m_bBump = hasBump; + vars.m_nBumpmapVar = info.m_nBumpmap; + vars.m_nBumpmapFrame = info.m_nBumpFrame; + vars.m_nBumpTransform = info.m_nBumpTransform; + vars.m_nFlashlightTextureVar = info.m_nFlashlightTexture; + vars.m_nFlashlightTextureFrameVar = info.m_nFlashlightTextureFrame; + vars.m_bLightmappedGeneric = true; + vars.m_bWorldVertexTransition = hasBaseTexture2; + vars.m_nBaseTexture2Var = info.m_nBaseTexture2; + vars.m_nBaseTexture2FrameVar = info.m_nBaseTexture2Frame; + vars.m_nBumpmap2Var = info.m_nBumpmap2; + vars.m_nBumpmap2Frame = info.m_nBumpFrame2; + vars.m_nBump2Transform = info.m_nBumpTransform2; + vars.m_nAlphaTestReference = info.m_nAlphaTestReference; + vars.m_bSSBump = hasSSBump; + vars.m_nDetailVar = info.m_nDetail; + vars.m_nDetailScale = info.m_nDetailScale; + vars.m_nDetailTextureCombineMode = info.m_nDetailTextureCombineMode; + vars.m_nDetailTextureBlendFactor = info.m_nDetailTextureBlendFactor; + vars.m_nDetailTint = info.m_nDetailTint; + + if ( ( info.m_nSeamlessMappingScale != -1 ) ) + vars.m_fSeamlessScale = params[info.m_nSeamlessMappingScale]->GetFloatValue(); + else + vars.m_fSeamlessScale = 0.0; + pShader->DrawFlashlight_dx90( params, pShaderAPI, pShaderShadow, vars ); + return; + } + + pContextData->m_bFullyOpaque = bFullyOpaque; + pContextData->m_bFullyOpaqueWithoutAlphaTest = bFullyOpaqueWithoutAlphaTest; + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( hasBump && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + ITexture *pBumpTex = params[info.m_nBumpmap]->GetTextureValue(); + if ( pBumpTex ) + { + nNormalDecodeMode = pBumpTex->GetNormalDecodeMode(); + + if ( hasBump2 ) // Check encoding of secondary normal if there is oneg + { + ITexture *pBumpTex2 = params[info.m_nBumpmap]->GetTextureValue(); + if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) ) + { + DevMsg("LightmappedGeneric: Primary and Secondary normal map compression formats don't match. This is unsupported!\n"); + Assert(0); + } + } + } + } + + int nNormalMaskDecodeMode = 0; + if ( hasBumpMask && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + ITexture *pBumpMaskTex = params[info.m_nBumpMask]->GetTextureValue(); + if ( pBumpMaskTex ) + { + nNormalMaskDecodeMode = pBumpMaskTex->GetNormalDecodeMode(); + } + } + + bool bHasOutline = IsBoolSet( info.m_nOutline, params ); + pContextData->m_bPixelShaderForceFastPathBecauseOutline = bHasOutline; + bool bHasSoftEdges = IsBoolSet( info.m_nSoftEdges, params ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + + + float fDetailBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasDiffuseBumpmap = hasBump && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + + if ( bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + + if( !hasBaseTexture ) + { + if( hasEnvmap ) + { + // if we only have an envmap (no basetexture), then we want the albedo to be black. + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK ); + } + else + { + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + } + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( bSeamlessMapping ) + { + staticCmdsBuf.SetVertexShaderConstant4( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, + params[info.m_nSeamlessMappingScale]->GetFloatValue(),0,0,0 ); + } + staticCmdsBuf.StoreEyePosInPixelShaderConstant( 10 ); + staticCmdsBuf.SetPixelShaderFogParams( 11 ); + staticCmdsBuf.End(); + // now, copy buf + pContextData->m_pStaticCmds = new uint8[staticCmdsBuf.Size()]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + if ( pShaderShadow ) + { + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + pShader->SetDefaultBlendingShadowState( nAlphaChannelTextureVar, hasBaseTexture ); + + unsigned int flags = VERTEX_POSITION; + + // base texture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if ( hasLightWarpTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false ); + } + if ( bHasBlendModulateTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + } + + if ( hasBaseTexture2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true ); + } +// if( hasLightmap ) + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + else + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + } + + if( hasEnvmap || ( IsX360() && hasFlashlight ) ) + { + if( hasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + } + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + } + + int nDetailBlendMode = 0; + if ( hasDetailTexture ) + { + nDetailBlendMode = GetIntParam( info.m_nDetailTextureCombineMode, params ); + ITexture *pDetailTexture = params[info.m_nDetail]->GetTextureValue(); + if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP ) + { + if ( hasBump ) + nDetailBlendMode = 10; // ssbump + else + nDetailBlendMode = 11; // ssbump_nobump + } + } + + if( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); + bool bSRGBState = ( nDetailBlendMode == 1 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, bSRGBState ); + } + + if( hasBump || hasNormalMapAlphaEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Normal map alpha, in the compressed normal case + } + } + if( hasBump2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // Secondary normal alpha, in the compressed normal case + } + } + if( hasBumpMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); + if ( nNormalMaskDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // Normal mask alpha, in the compressed normal case + } + } + if( hasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + + if( hasFlashlight && IsX360() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } + + if( hasVertexColor || hasBaseTexture2 || hasBump2 ) + { + flags |= VERTEX_COLOR; + } + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + + int bumpmap_variant=(hasSSBump) ? 2 : hasBump; + bool bMaskedBlending=( (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() != 0) ); + + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, hasEnvmapMask ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, params[info.m_nEnvmap]->IsTexture() ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, hasBaseTexture2 || hasBump2 ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, hasBumpMask ); + + bool bReliefMapping = false; //( bumpmap_variant == 2 ) && ( ! bSeamlessMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( RELIEF_MAPPING, false );//bReliefMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP, params[info.m_nBaseTextureNoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending); + SET_STATIC_PIXEL_SHADER_COMBO( RELIEF_MAPPING, bReliefMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMASK_DECODE_MODE, (int) nNormalMaskDecodeMode ); +#ifdef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP, params[info.m_nBaseTextureNoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, 0 ); // No normal compression with ps_2_0 (yikes!) + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMASK_DECODE_MODE, 0 ); // No normal compression with ps_2_0 + SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + } + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff and writing depth to dest alpha + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + pShaderShadow->EnableSRGBWrite( true ); + + pShader->DefaultFog(); + + + } // end shadow state + } // end shadow || regen display list + if ( pShaderAPI && pContextData->m_bMaterialVarsChanged ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + bool bHasBlendMaskTransform= ( + (info.m_nBlendMaskTransform != -1) && + (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() ) && + ( ! (params[info.m_nBumpTransform]->MatrixIsIdentity() ) ) ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[info.m_nBaseTextureTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform2]->MatrixIsIdentity() && + params[info.m_nEnvmapMaskTransform]->MatrixIsIdentity() ); + + bHasTextureTransform |= bHasBlendMaskTransform; + + pContextData->m_bVertexShaderFastPath = !bHasTextureTransform; + + if( params[info.m_nDetail]->IsTexture() ) + { + pContextData->m_bVertexShaderFastPath = false; + } + if (bHasBlendMaskTransform) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, info.m_nBlendMaskTransform ); + } + + if ( ! pContextData->m_bVertexShaderFastPath ) + { + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + if (!bSeamlessMapping ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + // If we have a detail texture, then the bump texcoords are the same as the base texcoords. + if( hasBump && !hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform ); + } + else if ( hasBump2 ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform2 ); + } + } + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint ); + // set up shader modulation color + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + pShader->ComputeModulationColor( color ); + float flLScale = pShaderAPI->GetLightMapScaleFactor(); + color[0] *= flLScale; + color[1] *= flLScale; + color[2] *= flLScale; + + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + color[3] *= ( IS_PARAM_DEFINED( info.m_nAlpha2 ) && params[ info.m_nAlpha2 ]->GetFloatValue() > 0.0f ) ? params[ info.m_nAlpha2 ]->GetFloatValue() : 1.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, color ); + + if ( hasDetailTexture ) + { + float detailTintAndBlend[4] = {1, 1, 1, 1}; + + if ( info.m_nDetailTint != -1 ) + { + params[info.m_nDetailTint]->GetVecValue( detailTintAndBlend, 3 ); + } + + detailTintAndBlend[3] = fDetailBlendFactor; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 8, detailTintAndBlend ); + } + + float envmapTintVal[4]; + float selfIllumTintVal[4]; + params[info.m_nEnvmapTint]->GetVecValue( envmapTintVal, 3 ); + params[info.m_nSelfIllumTint]->GetVecValue( selfIllumTintVal, 3 ); + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + float envmapSaturation = params[info.m_nEnvmapSaturation]->GetFloatValue(); + float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue(); + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + pContextData->m_bPixelShaderFastPath = true; + bool bUsingContrast = hasEnvmap && ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) && (envmapSaturation != 1.0f); + bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f); + bool bUsingSelfIllumTint = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && (selfIllumTintVal[0] != 1.0f || selfIllumTintVal[1] != 1.0f || selfIllumTintVal[2] != 1.0f); + if ( bUsingContrast || bUsingFresnel || bUsingSelfIllumTint || !g_pConfig->bShowSpecular ) + { + pContextData->m_bPixelShaderFastPath = false; + } + if( !pContextData->m_bPixelShaderFastPath ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstants( 2, 3 ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapContrast]->GetVecValue() ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapSaturation]->GetVecValue() ); + float flFresnel = params[info.m_nFresnelReflection]->GetFloatValue(); + // [ 0, 0, 1-R(0), R(0) ] + pContextData->m_SemiStaticCmdsOut.OutputConstantData4( 0., 0., 1.0 - flFresnel, flFresnel ); + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, params[info.m_nSelfIllumTint]->GetVecValue() ); + } + else + { + if ( bHasOutline ) + { + float flOutlineParms[8] = { GetFloatParam( info.m_nOutlineStart0, params ), + GetFloatParam( info.m_nOutlineStart1, params ), + GetFloatParam( info.m_nOutlineEnd0, params ), + GetFloatParam( info.m_nOutlineEnd1, params ), + 0,0,0, + GetFloatParam( info.m_nOutlineAlpha, params ) }; + if ( info.m_nOutlineColor != -1 ) + { + params[info.m_nOutlineColor]->GetVecValue( flOutlineParms + 4, 3 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, flOutlineParms, 2 ); + } + + if ( bHasSoftEdges ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( + 4, GetFloatParam( info.m_nEdgeSoftnessStart, params ), + GetFloatParam( info.m_nEdgeSoftnessEnd, params ), + 0,0 ); + } + } + // texture binds + if( hasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + // handle mat_fullbright 2 + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + // BASE TEXTURE + if( hasSelfIllum ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + // BASE TEXTURE 2 + if( hasBaseTexture2 ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_GREY ); + } + + // DETAIL TEXTURE + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER12, TEXTURE_GREY ); + } + + // disable color modulation + float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + // turn off environment mapping + envmapTintVal[0] = 0.0f; + envmapTintVal[1] = 0.0f; + envmapTintVal[2] = 0.0f; + } + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale ); + } + + if( hasBaseTexture2 ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nBaseTexture2, info.m_nBaseTexture2Frame ); + } + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetail, info.m_nDetailFrame ); + } + + if( hasBump || hasNormalMapAlphaEnvmapMask ) + { + if( !g_pConfig->m_bFastNoBump ) + { + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pContextData->m_SemiStaticCmdsOut.BindMultiTexture( pShader, SHADER_SAMPLER4, SHADER_SAMPLER9, info.m_nBumpmap, info.m_nBumpFrame ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT ); + } + } + if( hasBump2 ) + { + if( !g_pConfig->m_bFastNoBump ) + { + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pContextData->m_SemiStaticCmdsOut.BindMultiTexture( pShader, SHADER_SAMPLER5, SHADER_SAMPLER10, info.m_nBumpmap2, info.m_nBumpFrame2 ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nBumpmap2, info.m_nBumpFrame2 ); + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALMAP_FLAT ); + } + } + if( hasBumpMask ) + { + if( !g_pConfig->m_bFastNoBump ) + { + if ( nNormalMaskDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + Assert(0); + //pContextData->m_SemiStaticCmdsOut.BindTexture( SHADER_SAMPLER8, SHADER_SAMPLER11, info.m_nBumpMask ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nBumpMask, -1 ); + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_NORMALMAP_FLAT ); + } + } + + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if ( hasLightWarpTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nLightWarpTexture, -1 ); + } + + if ( bHasBlendModulateTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBlendModulateTexture, -1 ); + } + + pContextData->m_SemiStaticCmdsOut.End(); + } + } + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + if( hasEnvmap ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + + bool bVertexShaderFastPath = pContextData->m_bVertexShaderFastPath; + + if( nFixedLightingMode != 0 ) + { + if ( pContextData->m_bPixelShaderForceFastPathBecauseOutline ) + nFixedLightingMode = 0; + else + bVertexShaderFastPath = false; + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( + LIGHTING_PREVIEW, + (nFixedLightingMode)?1:0 + ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_vs20 ); + + bool bPixelShaderFastPath = pContextData->m_bPixelShaderFastPath; + if( nFixedLightingMode !=0 ) + { + bPixelShaderFastPath = false; + } + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( pContextData->m_bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nFixedLightingMode ); + + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nFixedLightingMode ); + + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps20 ); + } + + if( hasFlashlight && IsX360() ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + DynamicCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 ); + + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + float atten[4], pos[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + DynamicCmdsOut.SetPixelShaderConstant( 13, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + DynamicCmdsOut.SetPixelShaderConstant( 14, pos, 1 ); + + pShader->BindTexture( SHADER_SAMPLER13, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER14, pFlashlightDepthTexture, 0 ); + DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER15, TEXTURE_SHADOW_NOISE_2D ); + + // Tweaks associated with a given flashlight + float tweaks[4]; + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + DynamicCmdsOut.SetPixelShaderConstant( 19, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + DynamicCmdsOut.SetPixelShaderConstant( 31, vScreenScale, 1 ); + } + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); + + if( IsPC() && (IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0) && pContextData->m_bFullyOpaqueWithoutAlphaTest ) + { + //Alpha testing makes it so we can't write to dest alpha + //Writing to depth makes it so later polygons can't write to dest alpha either + //This leads to situations with garbage in dest alpha. + + //Fix it now by converting depth to dest alpha for any pixels that just wrote. + pShader->DrawEqualDepthToDestAlpha(); + } +} + +void DrawLightmappedGeneric_DX9(CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, + CBasePerMaterialContextData **pContextDataPtr ) +{ + bool hasFlashlight = pShader->UsingFlashlight( params ); + if ( !IsX360() && !r_flashlight_version2.GetInt() ) + { + DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr ); + return; + } + + DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr ); +} diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h new file mode 100644 index 00000000..00375b9f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef LIGHTMAPPEDGENERIC_DX9_HELPER_H +#define LIGHTMAPPEDGENERIC_DX9_HELPER_H + +#include +#include "BaseVSShader.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct LightmappedGeneric_DX9_Vars_t +{ + LightmappedGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(LightmappedGeneric_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nSelfIllumTint; + + int m_nAlpha2; // Hack for DoD srgb blend issues on overlays + + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + int m_nDetailTint; + + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nFresnelReflection; + int m_nNoDiffuseBumpLighting; + int m_nBumpmap2; + int m_nBumpFrame2; + int m_nBumpTransform2; + int m_nBumpMask; + int m_nBaseTexture2; + int m_nBaseTexture2Frame; + int m_nBaseTextureNoEnvmap; + int m_nBaseTexture2NoEnvmap; + int m_nDetailAlphaMaskBaseTexture; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + int m_nLightWarpTexture; + int m_nBlendModulateTexture; + int m_nMaskedBlending; + int m_nBlendMaskTransform; + int m_nSelfShadowedBumpFlag; + int m_nSeamlessMappingScale; + int m_nAlphaTestReference; + + int m_nSoftEdges; + int m_nEdgeSoftnessStart; + int m_nEdgeSoftnessEnd; + + int m_nOutline; + int m_nOutlineColor; + int m_nOutlineAlpha; + int m_nOutlineStart0; + int m_nOutlineStart1; + int m_nOutlineEnd0; + int m_nOutlineEnd1; + +}; + +void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightmappedGeneric_DX9_Vars_t &info ); +void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ); +void DrawLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr ); + + +#endif // LIGHTMAPPEDGENERIC_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_envmap.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_envmap.psh new file mode 100644 index 00000000..1e4a2bc4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_envmap.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs11.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs11.fxc new file mode 100644 index 00000000..3a0d059d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs11.fxc @@ -0,0 +1,122 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "NORMALMAP" "0..1" +// STATIC: "WORLDVERTEXTRANSITION" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +const float3 g_FlashlightPos : register( SHADER_SPECIFIC_CONST_0 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_1 ); +const float4 g_FlashlightAttenuationFactors : register( SHADER_SPECIFIC_CONST_5 ); + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cNormalMapTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_8 ); + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + // If this is float4, and the input is float3, the w component default to one. + float4 vPos : POSITION; + float3 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; +#if NORMALMAP + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +#endif + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float4 spotTexCoord : TEXCOORD0; + float2 baseTexCoord : TEXCOORD1; +#if NORMALMAP + float3 tangentPosToLightVector : TEXCOORD2; + float2 normalMapTexCoord : TEXCOORD3; +#else + float3 worldPosToLightVector : TEXCOORD2; + float3 normal : TEXCOORD3; +#endif + float4 vertAtten : COLOR0; +}; + +float RemapValClamped( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float4 projPos; + float3 worldPos; + float3 worldNormal; + float3 eyeVector; + + projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + + worldPos = mul( v.vPos, cModel[0] ); + worldNormal = mul( v.vNormal, ( float3x3 )cModel[0] ); + +#if NORMALMAP + float3 worldTangentS = mul( v.vTangentS, cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, cModel[0] ); +#endif + +#if !defined( _X360 ) + o.fog = CalcFog( worldPos, projPos, g_FogType ); +#endif + + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + + float4 spotTexCoord = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.spotTexCoord = spotTexCoord.xyzw; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; +#if NORMALMAP + o.normalMapTexCoord.x = dot( v.vBaseTexCoord, cNormalMapTexCoordTransform[0] ) + cNormalMapTexCoordTransform[0].w; + o.normalMapTexCoord.y = dot( v.vBaseTexCoord, cNormalMapTexCoordTransform[1] ) + cNormalMapTexCoordTransform[1].w; + + o.tangentPosToLightVector.x = dot( worldPosToLightVector, worldTangentS ); + o.tangentPosToLightVector.y = dot( worldPosToLightVector, worldTangentT ); + o.tangentPosToLightVector.z = dot( worldPosToLightVector, worldNormal ); +#else + o.worldPosToLightVector = worldPosToLightVector; + o.normal = worldNormal; +#endif + + float3 delta = worldPosToLightVector; + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + float farZ = g_FlashlightAttenuationFactors.w; + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6 * farZ ); + o.vertAtten.xyz = saturate( endFalloffFactor * dot( g_FlashlightAttenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + +#if WORLDVERTEXTRANSITION + o.vertAtten.w = 1 - v.vColor.w; +#else +#if VERTEXCOLOR + o.vertAtten.w = v.vColor.w; +#else + o.vertAtten.w = 1.0f; +#endif +#endif + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc new file mode 100644 index 00000000..7d23bb95 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc @@ -0,0 +1,184 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "NORMALMAP" "0..1" +// STATIC: "WORLDVERTEXTRANSITION" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "DETAIL" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +const float3 g_FlashlightPos : register( SHADER_SPECIFIC_CONST_0 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_1 ); +const float4 g_FlashlightAttenuationFactors : register( SHADER_SPECIFIC_CONST_5 ); + +#if SEAMLESS +const float4 SeamlessScale : register( SHADER_SPECIFIC_CONST_6 ); +#define SEAMLESS_SCALE (SeamlessScale.x) +#endif +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cNormalMapOrDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_8 ); + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float3 vPos : POSITION; //This HAS to match lightmappedgeneric_vs20.fxc's position input. Otherwise depth fighting errors occur on the 360 + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; +#if WORLDVERTEXTRANSITION + float2 vLightmapTexCoord : TEXCOORD1; + float4 vColor : COLOR0; +#endif +#if NORMALMAP + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + + float4 spotTexCoord : TEXCOORD0; + +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD1; +#else + float2 baseTexCoord : TEXCOORD1; +#endif + +#if NORMALMAP + float3 tangentPosToLightVector : TEXCOORD2; + float2 normalMapTexCoord : TEXCOORD3; +#else + float3 worldPosToLightVector : TEXCOORD2; + float3 normal : TEXCOORD3; +#endif + + float2 detailCoords : TEXCOORD4; + float4 worldPos_worldTransition : TEXCOORD5; + float3 vProjPos : TEXCOORD6; + float4 fogFactorW : TEXCOORD7; +}; + +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; +} + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + float3 worldNormal; + float3 eyeVector; + + //Projection math HAS to match lightmappedgeneric_vs20.fxc's math exactly. Otherwise depth fighting errors occur on the 360 + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + o.vProjPos.xyz = projPos.xyw; + + worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + + o.worldPos_worldTransition = float4( worldPos.xyz, 1.0f ); + + o.fogFactorW = CalcFog( worldPos, projPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW.w; +#endif + +#if NORMALMAP + float3 worldTangentS = mul( v.vTangentS, cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, cModel[0] ); +#endif +#if SEAMLESS + float3 vNormal=normalize( worldNormal ); + o.fogFactorW.xyz = vNormal * vNormal; // sums to 1. + o.SeamlessTexCoord = SEAMLESS_SCALE*worldPos; + + // Generate new tangent and binormal with seamless projection + #if NORMALMAP + // Brute-force for prototype - This must match the projection in the pixel shader! + //float3 vVecX = { 1.0f, 0.0f, 0.0f }; + //float3 vVecY = { 0.0f, 1.0f, 0.0f }; + //float3 vVecZ = { 0.0f, 0.0f, 1.0f }; + //worldTangentS.xyz = normalize( ( o.fogFactorW.x * vVecZ.xyz ) + ( o.fogFactorW.y * vVecX.xyz ) + ( o.fogFactorW.z * vVecX.xyz ) ); + //worldTangentT.xyz = normalize( ( o.fogFactorW.x * vVecY.xyz ) + ( o.fogFactorW.y * vVecZ.xyz ) + ( o.fogFactorW.z * vVecY.xyz ) ); + + // Optimized version - This must match the projection in the pixel shader! + worldTangentS.xyz = normalize( float3( o.fogFactorW.y + o.fogFactorW.z, 0.0f, o.fogFactorW.x ) ); + worldTangentT.xyz = normalize( float3( 0.0f, o.fogFactorW.x + o.fogFactorW.z, o.fogFactorW.y ) ); + #endif +#else +#if (SEAMLESS == 0 ) + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; +#endif +#endif + + float4 spotTexCoord = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.spotTexCoord = spotTexCoord.xyzw; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; +#if NORMALMAP + +#if (DETAIL == 0) + o.normalMapTexCoord.x = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[0] ) + cNormalMapOrDetailTexCoordTransform[0].w; + o.normalMapTexCoord.y = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[1] ) + cNormalMapOrDetailTexCoordTransform[1].w; +#else + +#if SEAMLESS + o.normalMapTexCoord = v.vBaseTexCoord; +#else + o.normalMapTexCoord = o.baseTexCoord; +#endif + +#endif + + o.tangentPosToLightVector.x = dot( worldPosToLightVector, worldTangentS ); + o.tangentPosToLightVector.y = dot( worldPosToLightVector, worldTangentT ); + o.tangentPosToLightVector.z = dot( worldPosToLightVector, worldNormal ); +#else + o.worldPosToLightVector = worldPosToLightVector; + o.normal = worldNormal; +#endif + +#if DETAIL + o.detailCoords.x = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[0] ) + cNormalMapOrDetailTexCoordTransform[0].w; + o.detailCoords.y = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[1] ) + cNormalMapOrDetailTexCoordTransform[1].w; +#else + o.detailCoords = float2(0,0); +#endif + + //float3 delta = worldPosToLightVector; + //float distSquared = dot( delta, delta ); + //float dist = sqrt( distSquared ); + //float farZ = g_FlashlightAttenuationFactors.w; + //float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + //o.projPos_atten.w = endFalloffFactor * dot( g_FlashlightAttenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ); + //o.projPos_atten.w = saturate( o.projPos_atten.w ); + +#if WORLDVERTEXTRANSITION + o.worldPos_worldTransition.w = v.vColor.w; +#endif + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_inc.vsh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_inc.vsh new file mode 100644 index 00000000..a5d12a81 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_inc.vsh @@ -0,0 +1,110 @@ +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +; $SHADER_SPECIFIC_CONST_4 = Modulation color +;------------------------------------------------------------------------------ + +sub LightmappedGeneric +{ + local( $detail ) = shift; + local( $envmap ) = shift; + local( $envmapcameraspace ) = shift; + local( $envmapsphere ) = shift; + local( $vertexcolor ) = shift; + + local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + + &AllocateRegister( \$projPos ); + + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + mov oPos, $projPos + + &AllocateRegister( \$worldPos ); + + if( $DOWATERFOG == 1 ) + { + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 + } + &CalcFog( $worldPos, $projPos ); + &FreeRegister( \$projPos ); + + ;------------------------------------------------------------------------------ + ; Texture coordinates + ;------------------------------------------------------------------------------ + ; base texcoords + dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 + dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + ; lightmap texcoords + mov oT1, $vTexCoord1 + + if( $envmap ) + { + &AllocateRegister( \$worldNormal ); + + ; Transform the position + normal to world space + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + if( $DOWATERFOG ne 1 ) + { + dp4 $worldPos.z, $vPos, $cModel2 + } + + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + if( $envmapcameraspace ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + ; transform reflection vector into view space + dp3 oT2.x, $reflectionVector, $cViewModel0 + dp3 oT2.y, $reflectionVector, $cViewModel1 + dp3 oT2.z, $reflectionVector, $cViewModel2 + &FreeRegister( \$reflectionVector ); + } + elsif( $envmapsphere ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + &ComputeSphereMapTexCoords( $reflectionVector, "oT2" ); + &FreeRegister( \$reflectionVector ); + } + else + { + &ComputeReflectionVector( $worldPos, $worldNormal, "oT2" ); + } + ; envmap mask + dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 ; FIXME + dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 ; FIXME + +# &FreeRegister( \$worldPos ); + &FreeRegister( \$worldNormal ); + } + + &FreeRegister( \$worldPos ); # garymcthack + + if( $detail ) + { + dp4 oT2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 ; FIXME + dp4 oT2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 ; FIXME + } + + if( $vertexcolor ) + { + ; Modulation color + mul oD0, $vColor, $cModulationColor + } + else + { + ; Modulation color + mov oD0, $cModulationColor + } +} diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_overbright2_ps11.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_overbright2_ps11.fxc new file mode 100644 index 00000000..1dbb8b2f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_overbright2_ps11.fxc @@ -0,0 +1,12 @@ +sampler TextureSampler : register( s1 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord1 : TEXCOORD1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return tex2D( TextureSampler, i.vTexCoord1 ); +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_vs11.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_vs11.fxc new file mode 100644 index 00000000..afee6c9c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_vs11.fxc @@ -0,0 +1,51 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // YUCK! This is to make texcoords continuous for mat_softwaretl + o.vTexCoord0 = 0.0f; + o.vTexCoord1 = v.vTexCoord1; + + o.vDiffuse = 1.0f; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_maskedenvmap.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_maskedenvmap.psh new file mode 100644 index 00000000..4f72286f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_maskedenvmap.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasealphamaskedselfillum.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasealphamaskedselfillum.psh new file mode 100644 index 00000000..a525a7b2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasealphamaskedselfillum.psh @@ -0,0 +1,24 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +def c0 0.5f 0.5f 0.5f 1.0f + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mul r1.a, t0, v0 ; base times vertex alpha +; GR - workaround for const/lerp issues +mul r0.rgb, c1, t0 ; Self illum * tint ++mul_sat r0.a, c1, t0 +lrp r1.rgb, t0.a, r1, r0 ; Blend between self-illum + lightmap +lrp r0, r1.a, r1, c0 ; interpolate between grey + color diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasenotexture.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasenotexture.psh new file mode 100644 index 00000000..77b05b9f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasenotexture.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +def c2, 0.5f, 0.5f, 0.5f, 1.0f + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mov r1.a, v0 ; vertex alpha +lrp r0, r1.a, r1, c2 ; interpolate between grey + color diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc new file mode 100644 index 00000000..d5be9e5f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc @@ -0,0 +1,122 @@ +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "ENVMAP" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" + +// SKIP: !$ENVMAP && ( $BASEALPHAENVMAPMASK || $ENVMAPMASK ) +// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK +// SKIP: $SELFILLUM && $BASEALPHAENVMAPMASK +// SKIP: !$BASETEXTURE && $SELFILLUM + +const float3 g_OverbrightFactor : register( c0 ); +const float3 g_SelfIllumTint : register( c1 ); +const float3 g_EnvmapTint : register( c2 ); + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +sampler EnvmapMaskSampler : register( s3 ); + +//sampler DetailSampler : register( s3 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float2 lightmapTexCoord : TEXCOORD1; + float3 envmapTexCoord : TEXCOORD2; + float2 envmapMaskTexCoord : TEXCOORD3; + float4 vertexColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBaseTexture = BASETEXTURE ? true : false; + bool bEnvmap = ENVMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + +#if 1 + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bBaseTexture ) + { + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + } + + float3 specularFactor = 1.0f; + + if( bEnvmapMask ) + { + specularFactor *= tex2D( EnvmapMaskSampler, i.envmapMaskTexCoord ).xyz; + } + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - baseColor.a; // this blows! + } + + float3 diffuseLighting = tex2D( LightmapSampler, i.lightmapTexCoord ); + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + if( bBaseTexture ) + { + albedo *= baseColor; + if( !bBaseAlphaEnvmapMask && !bSelfIllum ) + { + alpha *= baseColor.a; + } + } + + // The vertex color contains the modulation color + vertex color combined + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + float3 diffuseComponent = ( albedo * diffuseLighting * 2.0f ) * g_OverbrightFactor; + + if( bSelfIllum ) + { + float3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + + if( bEnvmap ) + { + specularLighting = tex2D( EnvmapSampler, i.envmapTexCoord ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + } + + float3 result = diffuseComponent + specularLighting; + return float4( result, alpha ); +#endif + +#if 0 + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + float3 diffuseLighting = tex2D( LightmapSampler, i.lightmapTexCoord ); + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + float3 diffuseComponent = ( albedo * diffuseLighting * 2.0f ) * g_OverbrightFactor; + float3 result = diffuseComponent; + return float4( result, alpha ); +#endif + +#if 0 + float4 result; + + result.rgb = tex2D( LightmapSampler, i.lightmapTexCoord ).rgb * i.vertexColor.rgb; + result.a = i.vertexColor.a; + result.rgb = ( result.rgb * g_OverbrightFactor ) * 2.0f; + return result; +#endif +} + + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h b/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h new file mode 100644 index 00000000..585ea1f6 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h @@ -0,0 +1,583 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// SKIP: $BUMPMAP2 && $WARPLIGHTING +// SKIP: $WARPLIGHTING && $DETAILTEXTURE +// SKIP: $ENVMAPMASK && $BUMPMAP +// SKIP: $NORMALMAPALPHAENVMAPMASK && $BASEALPHAENVMAPMASK +// SKIP: $NORMALMAPALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM +// SKIP: !$FASTPATH && $FASTPATHENVMAPCONTRAST +// SKIP: !$FASTPATH && $FASTPATHENVMAPTINT +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: !$BUMPMAP && $BUMPMAP2 +// SKIP: $ENVMAPMASK && $BUMPMAP2 +// SKIP: $BASETEXTURENOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) +// SKIP: $BASETEXTURE2NOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) +// SKIP: $BASEALPHAENVMAPMASK && $BUMPMAP +// SKIP: $PARALLAXMAP && $DETAILTEXTURE +// SKIP: $SEAMLESS && $RELIEF_MAPPING +// SKIP: $SEAMLESS && $DETAILTEXTURE +// SKIP: $SEAMLESS && $MASKEDBLENDING +// SKIP: $BUMPMASK && ( $SEAMLESS || $DETAILTEXTURE || $SELFILLUM || $BASETEXTURENOENVMAP || $BASETEXTURE2 ) +// SKIP: !$BUMPMAP && ($NORMAL_DECODE_MODE == 1) +// SKIP: !$BUMPMAP && ($NORMAL_DECODE_MODE == 2) +// SKIP: !$BUMPMAP && ($NORMALMASK_DECODE_MODE == 1) +// SKIP: !$BUMPMAP && ($NORMALMASK_DECODE_MODE == 2) +// NOSKIP: $FANCY_BLENDING && (!$FASTPATH) + +// 360 compiler craps out on some combo in this family. Content doesn't use blendmode 10 anyway +// SKIP: $FASTPATH && $PIXELFOGTYPE && $BASETEXTURE2 && $DETAILTEXTURE && $CUBEMAP && ($DETAIL_BLEND_MODE == 10 ) [XBOX] + +// debug crap: +// NOSKIP: $DETAILTEXTURE +// NOSKIP: $CUBEMAP +// NOSKIP: $ENVMAPMASK +// NOSKIP: $BASEALPHAENVMAPMASK +// NOSKIP: $SELFILLUM + +#define USE_32BIT_LIGHTMAPS_ON_360 //uncomment to use 32bit lightmaps, be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp + +#include "common_ps_fxc.h" +#include "common_flashlight_fxc.h" +#include "common_lightmappedgeneric_fxc.h" + +#if SEAMLESS +#define USE_FAST_PATH 1 +#else +#define USE_FAST_PATH FASTPATH +#endif + +const HALF4 g_EnvmapTint : register( c0 ); + +#if USE_FAST_PATH == 1 + +# if FASTPATHENVMAPCONTRAST == 0 +static const HALF3 g_EnvmapContrast = { 0.0f, 0.0f, 0.0f }; +# else +static const HALF3 g_EnvmapContrast = { 1.0f, 1.0f, 1.0f }; +# endif +static const HALF3 g_EnvmapSaturation = { 1.0f, 1.0f, 1.0f }; +static const HALF g_FresnelReflection = 1.0f; +static const HALF g_OneMinusFresnelReflection = 0.0f; +static const HALF4 g_SelfIllumTint = { 1.0f, 1.0f, 1.0f, 1.0f }; +# if OUTLINE +const float4 g_OutlineParams : register( c2 ); +#define OUTLINE_MIN_VALUE0 g_OutlineParams.x +#define OUTLINE_MIN_VALUE1 g_OutlineParams.y +#define OUTLINE_MAX_VALUE0 g_OutlineParams.z +#define OUTLINE_MAX_VALUE1 g_OutlineParams.w + +const float4 g_OutlineColor : register( c3 ); +#define OUTLINE_COLOR g_OutlineColor + +# endif +# if SOFTEDGES +const float4 g_EdgeSoftnessParms : register( c4 ); +#define SOFT_MASK_MIN g_EdgeSoftnessParms.x +#define SOFT_MASK_MAX g_EdgeSoftnessParms.y +# endif +#else + +const HALF3 g_EnvmapContrast : register( c2 ); +const HALF3 g_EnvmapSaturation : register( c3 ); +const HALF4 g_FresnelReflectionReg : register( c4 ); +#define g_FresnelReflection g_FresnelReflectionReg.a +#define g_OneMinusFresnelReflection g_FresnelReflectionReg.b +const HALF4 g_SelfIllumTint : register( c7 ); +#endif + +const float4 g_DetailTint_and_BlendFactor : register( c8 ); +#define g_DetailTint (g_DetailTint_and_BlendFactor.rgb) +#define g_DetailBlendFactor (g_DetailTint_and_BlendFactor.w) + +const HALF3 g_EyePos : register( c10 ); +const HALF4 g_FogParams : register( c11 ); +const float4 g_TintValuesAndLightmapScale : register( c12 ); + +#define g_flAlpha2 g_TintValuesAndLightmapScale.w + +const float4 g_FlashlightAttenuationFactors : register( c13 ); +const float3 g_FlashlightPos : register( c14 ); +const float4x4 g_FlashlightWorldToTexture : register( c15 ); // through c18 +const float4 g_ShadowTweaks : register( c19 ); + + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +#if FANCY_BLENDING +sampler BlendModulationSampler : register( s3 ); +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s12 ); +#endif + +sampler BumpmapSampler : register( s4 ); +#if NORMAL_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMapSampler : register( s9 ); // alpha +#else +#define AlphaMapSampler BumpmapSampler +#endif + +#if BUMPMAP2 == 1 +sampler BumpmapSampler2 : register( s5 ); +#if NORMAL_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMapSampler2 : register( s10 ); // alpha +#else +#define AlphaMapSampler2 BumpmapSampler2 +#endif +#else +sampler EnvmapMaskSampler : register( s5 ); +#endif + + +#if WARPLIGHTING +sampler WarpLightingSampler : register( s6 ); +#endif +sampler BaseTextureSampler2 : register( s7 ); + +#if BUMPMASK == 1 +sampler BumpMaskSampler : register( s8 ); +#if NORMALMASK_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMaskSampler : register( s11 ); // alpha +#else +#define AlphaMaskSampler BumpMaskSampler +#endif +#endif + +#if defined( _X360 ) && FLASHLIGHT +sampler FlashlightSampler : register( s13 ); +sampler ShadowDepthSampler : register( s14 ); +sampler RandRotSampler : register( s15 ); +#endif + +struct PS_INPUT +{ +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD0; // zy xz + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; // envmap mask +#else + HALF2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. +#if ( RELIEF_MAPPING == 0 ) + HALF4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; +#endif +#endif +// CENTROID: TEXCOORD2 + HALF4 lightmapTexCoord1And2 : TEXCOORD2; +// CENTROID: TEXCOORD3 + HALF4 lightmapTexCoord3 : TEXCOORD3; + HALF4 worldPos_projPosZ : TEXCOORD4; + HALF3x3 tangentSpaceTranspose : TEXCOORD5; + // tangentSpaceTranspose : TEXCOORD6 + // tangentSpaceTranspose : TEXCOORD7 + HALF4 vertexColor : COLOR; + float4 vertexBlendX_fogFactorW : COLOR1; + + // Extra iterators on 360, used in flashlight combo +#if defined( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; + float4 vProjPos : TEXCOORD9; +#endif +}; + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +HALF4 main( PS_INPUT i ) : COLOR +#endif +{ + bool bBaseTexture2 = BASETEXTURE2 ? true : false; + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBumpmap = BUMPMAP ? true : false; + bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bBaseTextureNoEnvmap = BASETEXTURENOENVMAP ? true : false; + bool bBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP ? true : false; + + float4 baseColor = 0.0f; + float4 baseColor2 = 0.0f; + float4 vNormal = float4(0, 0, 1, 1); + float3 baseTexCoords = float3(0,0,0); + +#if SEAMLESS + baseTexCoords = i.SeamlessTexCoord.xyz; +#else + baseTexCoords.xy = i.baseTexCoord.xy; +#endif + + GetBaseTextureAndNormal( BaseTextureSampler, BaseTextureSampler2, BumpmapSampler, bBaseTexture2, bBumpmap || bNormalMapAlphaEnvmapMask, + baseTexCoords, i.vertexColor.rgb, baseColor, baseColor2, vNormal ); + +#if BUMPMAP == 1 // not ssbump + vNormal.xyz = vNormal.xyz * 2.0f - 1.0f; // make signed if we're not ssbump +#endif + + HALF3 lightmapColor1 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor2 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor3 = HALF3( 1.0f, 1.0f, 1.0f ); +#if LIGHTING_PREVIEW == 0 + if( bBumpmap && bDiffuseBumpmap ) + { + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + lightmapColor2 = LightMapSample( LightmapSampler, bumpCoord2 ); + lightmapColor3 = LightMapSample( LightmapSampler, bumpCoord3 ); + } + else + { + HALF2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + } +#endif + +#if RELIEF_MAPPING + // in the parallax case, all texcoords must be the same in order to free + // up an iterator for the tangent space view vector + HALF2 detailTexCoord = i.baseTexCoord.xy; + HALF2 bumpmapTexCoord = i.baseTexCoord.xy; + HALF2 envmapMaskTexCoord = i.baseTexCoord.xy; +#else + + #if ( DETAILTEXTURE == 1 ) + HALF2 detailTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.xy; + HALF2 bumpmapTexCoord = i.baseTexCoord.xy; + #elif ( BUMPMASK == 1 ) + HALF2 detailTexCoord = 0.0f; + HALF2 bumpmapTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.xy; + HALF2 bumpmap2TexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.wz; + #else + HALF2 detailTexCoord = 0.0f; + HALF2 bumpmapTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.xy; + #endif + + HALF2 envmapMaskTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.wz; +#endif // !RELIEF_MAPPING + + HALF4 detailColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); +#if DETAILTEXTURE + +#if SHADER_MODEL_PS_2_0 + detailColor = tex2D( DetailSampler, detailTexCoord ); +#else + detailColor = float4( g_DetailTint, 1.0f ) * tex2D( DetailSampler, detailTexCoord ); +#endif + +#endif + +#if ( OUTLINE || SOFTEDGES ) + float distAlphaMask = baseColor.a; + +# if OUTLINE + if ( ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && + ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) ) + { + float oFactor=1.0; + if ( distAlphaMask <= OUTLINE_MIN_VALUE1 ) + { + oFactor=smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask ); + } + else + { + oFactor=smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask ); + } + baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor ); + } +# endif +# if SOFTEDGES + baseColor.a *= smoothstep( SOFT_MASK_MAX, SOFT_MASK_MIN, distAlphaMask ); +# else + baseColor.a *= distAlphaMask >= 0.5; +# endif +#endif + + +#if LIGHTING_PREVIEW == 2 + baseColor.xyz=GammaToLinear(baseColor.xyz); +#endif + + float blendedAlpha = baseColor.a; + +#if MASKEDBLENDING + float blendfactor=0.5; +#else + float blendfactor=i.vertexBlendX_fogFactorW.r; +#endif + + if( bBaseTexture2 ) + { +#if (SELFILLUM == 0) && (PIXELFOGTYPE != PIXEL_FOG_TYPE_HEIGHT) && (FANCY_BLENDING) + float4 modt=tex2D(BlendModulationSampler,i.lightmapTexCoord3.zw); +#if MASKEDBLENDING + // FXC is unable to optimize this, despite blendfactor=0.5 above + //float minb=modt.g-modt.r; + //float maxb=modt.g+modt.r; + //blendfactor=smoothstep(minb,maxb,blendfactor); + blendfactor=modt.g; +#else + float minb=saturate(modt.g-modt.r); + float maxb=saturate(modt.g+modt.r); + blendfactor=smoothstep(minb,maxb,blendfactor); +#endif +#endif + baseColor.rgb = lerp( baseColor, baseColor2.rgb, blendfactor ); + blendedAlpha = lerp( baseColor.a, baseColor2.a, blendfactor ); + } + + HALF3 specularFactor = 1.0f; + float4 vNormalMask = float4(0, 0, 1, 1); + if( bBumpmap ) + { + if( bBaseTextureNoEnvmap ) + { + vNormal.a = 0.0f; + } + +#if ( BUMPMAP2 == 1 ) + { + #if ( BUMPMASK == 1 ) + HALF2 b2TexCoord = bumpmap2TexCoord; + #else + HALF2 b2TexCoord = bumpmapTexCoord; + #endif + + HALF4 vNormal2; + if ( BUMPMAP == 2 ) + vNormal2 = tex2D( BumpmapSampler2, b2TexCoord ); + else + vNormal2 = DecompressNormal( BumpmapSampler2, b2TexCoord, NORMAL_DECODE_MODE, AlphaMapSampler2 ); // Bump 2 coords + + if( bBaseTexture2NoEnvmap ) + { + vNormal2.a = 0.0f; + } + + #if ( BUMPMASK == 1 ) + float3 vNormal1 = DecompressNormal( BumpmapSampler, i.detailOrBumpAndEnvmapMaskTexCoord.xy, NORMALMASK_DECODE_MODE, AlphaMapSampler ); + + vNormal.xyz = normalize( vNormal1.xyz + vNormal2.xyz ); + + // Third normal map...same coords as base + vNormalMask = DecompressNormal( BumpMaskSampler, i.baseTexCoord.xy, NORMALMASK_DECODE_MODE, AlphaMaskSampler ); + + vNormal.xyz = lerp( vNormalMask.xyz, vNormal.xyz, vNormalMask.a ); // Mask out normals from vNormal + specularFactor = vNormalMask.a; + #else // BUMPMASK == 0 + if ( FANCY_BLENDING && bNormalMapAlphaEnvmapMask ) + { + vNormal = lerp( vNormal, vNormal2, blendfactor); + } + else + { + vNormal.xyz = lerp( vNormal.xyz, vNormal2.xyz, blendfactor); + } + + #endif + + } + +#endif // BUMPMAP2 == 1 + + if( bNormalMapAlphaEnvmapMask ) + { + specularFactor *= vNormal.a; + } + } + else if ( bNormalMapAlphaEnvmapMask ) + { + specularFactor *= vNormal.a; + } + +#if ( BUMPMAP2 == 0 ) + if( bEnvmapMask ) + { + specularFactor *= tex2D( EnvmapMaskSampler, envmapMaskTexCoord ).xyz; + } +#endif + + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - blendedAlpha; // Reversing alpha blows! + } + float4 albedo = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= baseColor; + if( !bBaseAlphaEnvmapMask && !bSelfIllum ) + { + alpha *= baseColor.a; + } + + if( bDetailTexture ) + { + albedo = TextureCombine( albedo, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); + } + + // The vertex color contains the modulation color + vertex color combined +#if ( SEAMLESS == 0 ) + albedo.xyz *= i.vertexColor; +#endif + alpha *= i.vertexColor.a * g_flAlpha2; // not sure about this one + + // Save this off for single-pass flashlight, since we'll still need the SSBump vector, not a real normal + float3 vSSBumpVector = vNormal.xyz; + + HALF3 diffuseLighting; + if( bBumpmap && bDiffuseBumpmap ) + { + +// ssbump +#if ( BUMPMAP == 2 ) + diffuseLighting = vNormal.x * lightmapColor1 + + vNormal.y * lightmapColor2 + + vNormal.z * lightmapColor3; + diffuseLighting *= g_TintValuesAndLightmapScale.rgb; + + // now, calculate vNormal for reflection purposes. if vNormal isn't needed, hopefully + // the compiler will eliminate these calculations + vNormal.xyz = normalize( bumpBasis[0]*vNormal.x + bumpBasis[1]*vNormal.y + bumpBasis[2]*vNormal.z); +#else + float3 dp; + dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); + dp *= dp; + +#if ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP ) + dp *= 2*detailColor; +#endif + diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= g_TintValuesAndLightmapScale.rgb / sum; +#endif + } + else + { + diffuseLighting = lightmapColor1 * g_TintValuesAndLightmapScale.rgb; + } + +#if WARPLIGHTING && ( SEAMLESS == 0 ) + float len=0.5*length(diffuseLighting); + // FIXME: 8-bit lookup textures like this need a "nice filtering" VTF option, which converts + // them to 16-bit on load or does filtering in the shader (since most hardware - 360 + // included - interpolates 8-bit textures at 8-bit precision, which causes banding) + diffuseLighting *= 2.0*tex2D(WarpLightingSampler,float2(len,0)); +#endif + +#if CUBEMAP || LIGHTING_PREVIEW || ( defined( _X360 ) && FLASHLIGHT ) + float3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); +#endif + + float3 diffuseComponent = albedo.xyz * diffuseLighting; + +#if defined( _X360 ) && FLASHLIGHT + + // ssbump doesn't pass a normal to the flashlight...it computes shadowing a different way +#if ( BUMPMAP == 2 ) + bool bHasNormal = false; + + float3 worldPosToLightVector = g_FlashlightPos - i.worldPos_projPosZ.xyz; + + float3 tangentPosToLightVector; + tangentPosToLightVector.x = dot( worldPosToLightVector, i.tangentSpaceTranspose[0] ); + tangentPosToLightVector.y = dot( worldPosToLightVector, i.tangentSpaceTranspose[1] ); + tangentPosToLightVector.z = dot( worldPosToLightVector, i.tangentSpaceTranspose[2] ); + + tangentPosToLightVector = normalize( tangentPosToLightVector ); + + float nDotL = saturate( vSSBumpVector.x*dot( tangentPosToLightVector, bumpBasis[0]) + + vSSBumpVector.y*dot( tangentPosToLightVector, bumpBasis[1]) + + vSSBumpVector.z*dot( tangentPosToLightVector, bumpBasis[2]) ); +#else + bool bHasNormal = true; + float nDotL = 1.0f; +#endif + + float fFlashlight = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, i.flashlightSpacePos, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, 0, true, false, i.vProjPos.xy / i.vProjPos.w, false, g_ShadowTweaks, bHasNormal ); + + diffuseComponent = albedo.xyz * ( diffuseLighting + ( fFlashlight * nDotL ) ); +#endif + + if( bSelfIllum ) + { + float3 selfIllumComponent = g_SelfIllumTint * albedo.xyz; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); +#if CUBEMAP + if( bCubemap ) + { + float3 worldVertToEyeVector = g_EyePos - i.worldPos_projPosZ.xyz; + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldVertToEyeVector ); + + // Calc Fresnel factor + half3 eyeVect = normalize(worldVertToEyeVector); + HALF fresnel = 1.0 - dot( worldSpaceNormal, eyeVect ); + fresnel = pow( fresnel, 5.0 ); + fresnel = fresnel * g_OneMinusFresnelReflection + g_FresnelReflection; + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + + specularLighting *= g_EnvmapTint; +#if FANCY_BLENDING == 0 + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); +#endif + specularLighting *= fresnel; + } +#endif + + HALF3 result = diffuseComponent + specularLighting; + +#if LIGHTING_PREVIEW + worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); +# if LIGHTING_PREVIEW == 1 + float dotprod = 0.7+0.25 * dot( worldSpaceNormal, normalize( float3( 1, 2, -.5 ) ) ); + return FinalOutput( HALF4( dotprod*albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +# else + LPREVIEW_PS_OUT ret; + ret.color = float4( albedo.xyz,alpha ); + ret.normal = float4( worldSpaceNormal,alpha ); + ret.position = float4( i.worldPos_projPosZ.xyz, alpha ); + ret.flags = float4( 1, 1, 1, alpha ); + + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +# endif +#else // == end LIGHTING_PREVIEW == + + bool bWriteDepthToAlpha = false; + + // ps_2_b and beyond +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) + bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w ); + +#endif +} + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc new file mode 100644 index 00000000..599d16a4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc @@ -0,0 +1,59 @@ +// STATIC: "MASKEDBLENDING" "0..1" +// STATIC: "BASETEXTURE2" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "BUMPMAP" "0..2" +// STATIC: "BUMPMAP2" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "BASETEXTURENOENVMAP" "0..1" +// STATIC: "BASETEXTURE2NOENVMAP" "0..1" +// STATIC: "WARPLIGHTING" "0..1" +// STATIC: "FANCY_BLENDING" "0..1" +// STATIC: "RELIEF_MAPPING" "0..0" [ps20b] +// STATIC: "SEAMLESS" "0..1" +// STATIC: "OUTLINE" "0..1" +// STATIC: "SOFTEDGES" "0..1" +// STATIC: "BUMPMASK" "0..1" +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] +// STATIC: "NORMALMASK_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMALMASK_DECODE_MODE" "0..0" [PC] +// STATIC: "DETAIL_BLEND_MODE" "0..11" +// STATIC: "FLASHLIGHT" "0..1" [ps20b] [XBOX] + +// DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1" +// DYNAMIC: "FASTPATH" "0..1" +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..2" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $SEAMLESS && $RELIEF_MAPPING [ps20b] + +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// SKIP: $SEAMLESS && ( $OUTLINE || $SOFTEDGES) +// SKIP: $BASETEXTURE2 && ( $OUTLINE || $SOFTEDGES) +// SKIP: $BUMPMAP2 && ( $OUTLINE || $SOFTEDGES) +// SKIP: $SELFILLUM && ( $OUTLINE || $SOFTEDGES) +// SKIP: $MASKEDBLENDING && ( $OUTLINE || $SOFTEDGES) +// SKIP: $FANCY_BLENDING && ( $OUTLINE || $SOFTEDGES) +// SKIP: $LIGHTING_PREVIEW && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($FASTPATH == 0) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($DETAILTEXTURE && $BUMPMAP) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($WARPLIGHTING) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($BUMPMAP) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($DETAIL_BLEND_MODE == 2 ) || ($DETAIL_BLEND_MODE == 3 ) || ($DETAIL_BLEND_MODE == 4 ) +// SKIP: ($DETAIL_BLEND_MODE == 5 ) || ($DETAIL_BLEND_MODE == 6 ) || ($DETAIL_BLEND_MODE == 7 ) +// SKIP: ($DETAIL_BLEND_MODE == 8 ) || ($DETAIL_BLEND_MODE == 9 ) +// SKIP ($DETAIL_BLEND_MODE == 10 ) && ($BUMPMAP == 0 ) +// SKIP ($DETAIL_BLEND_MODE == 11 ) && ($BUMPMAP != 0 ) + +#include "lightmappedgeneric_ps2_3_x.h" + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedenvmap.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedenvmap.psh new file mode 100644 index 00000000..84b56437 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedenvmap.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) + +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedmaskedenvmap.psh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedmaskedenvmap.psh new file mode 100644 index 00000000..b4893363 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedmaskedenvmap.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0.rgb, t0, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) + +mul r1, c1, t0.a ; Self illum alpha * tint +mad r1, t0, r1, t1 ; Self illum * tint + lightmap +mul r0.rgb, r1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_vs11.vsh b/mp/src/materialsystem/stdshaders/lightmappedgeneric_vs11.vsh new file mode 100644 index 00000000..cc1dd1f8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_vs11.vsh @@ -0,0 +1,20 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# STATIC: "DETAIL" "0..1" +# STATIC: "ENVMAP" "0..1" +# STATIC: "ENVMAPCAMERASPACE" "0..0" +# STATIC: "ENVMAPSPHERE" "0..1" +# STATIC: "VERTEXCOLOR" "0..1" + +# can't have envmapshere or envmapcameraspace without envmap +# SKIP: !$ENVMAP && ( $ENVMAPSPHERE || $ENVMAPCAMERASPACE ) + +# can't have both envmapsphere and envmapcameraspace +# SKIP: $ENVMAPSPHERE && $ENVMAPCAMERASPACE + +#include "LightmappedGeneric_inc.vsh" + +&LightmappedGeneric( $DETAIL, $ENVMAP, $ENVMAPCAMERASPACE, $ENVMAPSPHERE, + $VERTEXCOLOR ); + diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc b/mp/src/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc new file mode 100644 index 00000000..362eb668 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc @@ -0,0 +1,254 @@ +// STATIC: "ENVMAP_MASK" "0..1" +// STATIC: "TANGENTSPACE" "0..1" +// STATIC: "BUMPMAP" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "VERTEXALPHATEXBLENDFACTOR" "0..1" +// STATIC: "RELIEF_MAPPING" "0..0" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "BUMPMASK" "0..1" +// STATIC: "FLASHLIGHT" "0..1" [XBOX] + +// DYNAMIC: "FASTPATH" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] + +// This should not be a combo since I'm a moron with the tangent space and the flashlight. +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: $SEAMLESS && $RELIEF_MAPPING +// SKIP: $BUMPMASK && $RELIEF_MAPPING +// SKIP: $BUMPMASK && $SEAMLESS + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_UseSeparateEnvmapMask = ENVMAP_MASK; +static const bool g_bTangentSpace = TANGENTSPACE; +static const bool g_bBumpmap = BUMPMAP; +static const bool g_bBumpmapDiffuseLighting = DIFFUSEBUMPMAP; +static const bool g_bVertexColor = VERTEXCOLOR; +static const bool g_bVertexAlphaTexBlendFactor = VERTEXALPHATEXBLENDFACTOR; +static const bool g_BumpMask = BUMPMASK; + +#if SEAMLESS +const float4 SeamlessScale : register( SHADER_SPECIFIC_CONST_0 ); +#define SEAMLESS_SCALE (SeamlessScale.x) +#else +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailOrBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); +#endif +// This should be identity if we are bump mapping, otherwise we'll screw up the lightmapTexCoordOffset. +const float4 cEnvmapMaskTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cBlendMaskTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_10 ); // not contiguous with the rest! + +struct VS_INPUT +{ + float3 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD0; // x y z + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; // envmap mask +#else + float2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. +#if RELIEF_MAPPING + float3 TangentSpaceViewRay : TEXCOORD1; +#else + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; +#endif +#endif + float4 lightmapTexCoord1And2 : TEXCOORD2; + float4 lightmapTexCoord3 : TEXCOORD3; // and basetexcoord*mask_scale + float4 worldPos_projPosZ : TEXCOORD4; + +#if TANGENTSPACE || (LIGHTING_PREVIEW) || defined( _X360 ) + float3x3 tangentSpaceTranspose : TEXCOORD5; // and 6 and 7 +#endif + + float4 vertexColor : COLOR; // in seamless, r g b = blend weights + float4 vertexBlendX_fogFactorW : COLOR1; + + // Extra iterators on 360, used in flashlight combo +#if defined( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; + float4 vProjPos : TEXCOORD9; +#endif +#endif + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float3 worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + + float4 vProjPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( v.vPos, 1 ), cModelViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos, vProjPos.z ); + + float3 worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + +#if TANGENTSPACE || (LIGHTING_PREVIEW) || defined( _X360 ) + float3 worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + + #if SEAMLESS && BUMPMAP && defined( _X360 ) + float3 n = normalize( worldNormal ); + float3 n2 = n * n; // sums to 1. + + o.tangentSpaceTranspose[0] = normalize( float3( n2.y + n2.z, 0.0f, n2.x ) ); + o.tangentSpaceTranspose[1] = normalize( float3( 0.0f, n2.x + n2.z, n2.y ) ); + o.tangentSpaceTranspose[2] = worldNormal; + #else + o.tangentSpaceTranspose[0] = worldTangentS; + o.tangentSpaceTranspose[1] = worldTangentT; + o.tangentSpaceTranspose[2] = worldNormal; + #endif + +#endif + + float3 worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + +#if SEAMLESS + { + // we need to fill in the texture coordinate projections + o.SeamlessTexCoord = SEAMLESS_SCALE*worldPos; + } +#else + { + if (FASTPATH) + { + o.baseTexCoord.xy = v.vBaseTexCoord; + } + else + { + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + } +#if ( RELIEF_MAPPING == 0 ) + { + // calculate detailorbumptexcoord + if ( FASTPATH ) + o.detailOrBumpAndEnvmapMaskTexCoord.xy = v.vBaseTexCoord.xy; + else + { + o.detailOrBumpAndEnvmapMaskTexCoord.x = dot( v.vBaseTexCoord, cDetailOrBumpTexCoordTransform[0] ) + cDetailOrBumpTexCoordTransform[0].w; + o.detailOrBumpAndEnvmapMaskTexCoord.y = dot( v.vBaseTexCoord, cDetailOrBumpTexCoordTransform[1] ) + cDetailOrBumpTexCoordTransform[1].w; + } + } +#endif + } +#endif + if ( FASTPATH ) + { + o.lightmapTexCoord3.zw = v.vBaseTexCoord; + } + else + { + o.lightmapTexCoord3.z = dot( v.vBaseTexCoord, cBlendMaskTexCoordTransform[0] ) + cBlendMaskTexCoordTransform[0].w; + o.lightmapTexCoord3.w = dot( v.vBaseTexCoord, cBlendMaskTexCoordTransform[1] ) + cBlendMaskTexCoordTransform[1].w; + } + + // compute lightmap coordinates + if( g_bBumpmap && g_bBumpmapDiffuseLighting ) + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + } + else + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord; + } + +#if ( RELIEF_MAPPING == 0) + if( g_UseSeparateEnvmapMask || g_BumpMask ) + { + // reversed component order +# if FASTPATH + o.detailOrBumpAndEnvmapMaskTexCoord.wz = v.vBaseTexCoord.xy; +# else + o.detailOrBumpAndEnvmapMaskTexCoord.w = dot( v.vBaseTexCoord, cEnvmapMaskTexCoordTransform[0] ) + cEnvmapMaskTexCoordTransform[0].w; + o.detailOrBumpAndEnvmapMaskTexCoord.z = dot( v.vBaseTexCoord, cEnvmapMaskTexCoordTransform[1] ) + cEnvmapMaskTexCoordTransform[1].w; +# endif + } +#endif + + o.vertexBlendX_fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.vertexBlendX_fogFactorW; +#endif + + if (!g_bVertexColor) + { + o.vertexColor = float4( 1.0f, 1.0f, 1.0f, cModulationColor.a ); + } + else + { +#if FASTPATH + o.vertexColor = v.vColor; +#else + if ( g_bVertexAlphaTexBlendFactor ) + { + o.vertexColor.rgb = v.vColor.rgb; + o.vertexColor.a = cModulationColor.a; + } + else + { + o.vertexColor = v.vColor; + o.vertexColor.a *= cModulationColor.a; + } +#endif + } +#if SEAMLESS + // compute belnd weights in rgb + float3 vNormal=normalize( worldNormal ); + o.vertexColor.xyz = vNormal * vNormal; // sums to 1. +#endif + +// On 360, we have extra iterators and can fold the flashlight into this shader +#if defined( _X360 ) + #if FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.vProjPos = vProjPos; + #endif +#endif + + if ( g_bVertexAlphaTexBlendFactor ) + { + o.vertexBlendX_fogFactorW.r = v.vColor.a; + } + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/refract.cpp b/mp/src/materialsystem/stdshaders/refract.cpp new file mode 100644 index 00000000..852e93a5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/refract.cpp @@ -0,0 +1,111 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "refract_dx9_helper.h" + +DEFINE_FALLBACK_SHADER( Refract, Refract_DX90 ) + +BEGIN_VS_SHADER( Refract_DX90, "Help for Refract" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( NORMALMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $normalmap" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $normalmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$normalmap texcoord transform" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$normalmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0f", "" ) + SHADER_PARAM( BLURAMOUNT, SHADER_PARAM_TYPE_INTEGER, "1", "0, 1, or 2 for how much blur you want" ) + SHADER_PARAM( FADEOUTONSILHOUETTE, SHADER_PARAM_TYPE_BOOL, "1", "0 for no fade out on silhouette, 1 for fade out on sillhouette" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( REFRACTTINTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shield", "" ) + SHADER_PARAM( REFRACTTINTTEXTUREFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NOWRITEZ, SHADER_PARAM_TYPE_INTEGER, "0", "0 == write z, 1 = no write z" ) + SHADER_PARAM( MASKED, SHADER_PARAM_TYPE_BOOL, "0", "mask using dest alpha" ) + SHADER_PARAM( VERTEXCOLORMODULATE, SHADER_PARAM_TYPE_BOOL, "0","Use the vertex color to effect refract color. alpha will adjust refract amount" ) + SHADER_PARAM( FORCEALPHAWRITE, SHADER_PARAM_TYPE_BOOL, "0","Force the material to write alpha to the dest buffer" ) + END_SHADER_PARAMS +// FIXME: doesn't support Fresnel! + + void SetupVars( Refract_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nRefractTint = REFRACTTINT; + info.m_nNormalMap = NORMALMAP; + info.m_nNormalMap2 = NORMALMAP2; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBlurAmount = BLURAMOUNT; + info.m_nFadeOutOnSilhouette = FADEOUTONSILHOUETTE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nRefractTintTexture = REFRACTTINTTEXTURE; + info.m_nRefractTintTextureFrame = REFRACTTINTTEXTUREFRAME; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoWriteZ = NOWRITEZ; + info.m_nMasked = MASKED; + info.m_nVertexColorModulate = VERTEXCOLORMODULATE; + info.m_nForceAlphaWrite = FORCEALPHAWRITE; + } + + SHADER_INIT_PARAMS() + { + Refract_DX9_Vars_t info; + SetupVars( info ); + InitParamsRefract_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 82 ) + return "Refract_DX80"; + + return 0; + } + + SHADER_INIT + { + Refract_DX9_Vars_t info; + SetupVars( info ); + InitRefract_DX9( this, params, info ); + } + + SHADER_DRAW + { + Refract_DX9_Vars_t info; + SetupVars( info ); + + // If ( snapshotting ) or ( we need to draw this frame ) + bool bHasFlashlight = this->UsingFlashlight( params ); + if ( ( pShaderShadow != NULL ) || ( bHasFlashlight == false ) ) + { + DrawRefract_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + Draw( false ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/refract_dx60.cpp b/mp/src/materialsystem/stdshaders/refract_dx60.cpp new file mode 100644 index 00000000..2ca7a83c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/refract_dx60.cpp @@ -0,0 +1,16 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// FIXME: This is a placeholder. . need to do something for real here. +DEFINE_FALLBACK_SHADER( Refract, Refract_DX60 ) +DEFINE_FALLBACK_SHADER( Refract_DX60, UnlitGeneric ) + + diff --git a/mp/src/materialsystem/stdshaders/refract_dx80.cpp b/mp/src/materialsystem/stdshaders/refract_dx80.cpp new file mode 100644 index 00000000..b6e6e5a0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/refract_dx80.cpp @@ -0,0 +1,317 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + + +#include "BaseVSShader.h" + +#include "refract_model_vs11.inc" +#include "refract_world_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define MAXBLUR 1 + +DEFINE_FALLBACK_SHADER( Refract, Refract_DX80 ) + +BEGIN_VS_SHADER( Refract_DX80, + "Help for Refract_DX80" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( DUDVMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_dudv", "dudv bump map" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( DUDVFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $dudvmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0f", "" ) + SHADER_PARAM( BLURAMOUNT, SHADER_PARAM_TYPE_INTEGER, "1", "0, 1, or 2 for how much blur you want" ) + SHADER_PARAM( FADEOUTONSILHOUETTE, SHADER_PARAM_TYPE_BOOL, "1", "0 for no fade out on silhouette, 1 for fade out on sillhouette" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( REFRACTTINTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shield", "" ) + SHADER_PARAM( REFRACTTINTTEXTUREFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( FALLBACK, SHADER_PARAM_TYPE_STRING, "", "Name of the fallback shader" ) + SHADER_PARAM( FORCEREFRACT, SHADER_PARAM_TYPE_BOOL, "0", "Forces refraction on boards that have poor performance" ) + SHADER_PARAM( NOWRITEZ, SHADER_PARAM_TYPE_INTEGER, "0", "0 == write z, 1 = no write z" ) + SHADER_PARAM( MASKED, SHADER_PARAM_TYPE_BOOL, "0", "mask using dest alpha" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + if( !params[MASKED]->IsDefined() ) + { + params[MASKED]->SetIntValue( 0 ); + } + if( !params[BLURAMOUNT]->IsDefined() ) + { + params[BLURAMOUNT]->SetIntValue( 0 ); + } + if( !params[FADEOUTONSILHOUETTE]->IsDefined() ) + { + params[FADEOUTONSILHOUETTE]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + SHADER_FALLBACK + { + if ( IsPC() ) + { + const char *pFallback = (params && params[FALLBACK]->IsDefined()) ? params[FALLBACK]->GetStringValue() : ""; + if (!pFallback[0]) + { + pFallback = "Refract_DX60"; + } + + if( g_pHardwareConfig->GetDXSupportLevel() < 80 || !g_pHardwareConfig->HasProjectedBumpEnv() ) + return pFallback; + + if ( g_pHardwareConfig->PreferReducedFillrate() && (params && (params[FORCEREFRACT]->GetIntValue() == 0)) ) + return pFallback; + } + + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if (params[DUDVMAP]->IsDefined() ) + { + LoadTexture( DUDVMAP ); + } + if (params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + if( params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP ); + } + if( params[REFRACTTINTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTINTTEXTURE ); + } + } + + inline int ComputePixelShaderIndex( bool bRefractTintTexture, bool bNormalMapAlpha ) + { + // "REFRACTTINTTEXTURE" "0..1" + // "NORMALMAPALPHA" "0..1" + int pshIndex = 0; + if( bRefractTintTexture ) pshIndex |= 0x1; + if( bNormalMapAlpha ) pshIndex |= 0x2; + return pshIndex; + } + + SHADER_DRAW + { + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasEnvmap = params[ENVMAP]->IsTexture(); + int blurAmount = params[BLURAMOUNT]->GetIntValue(); + bool bRefractTintTexture = params[REFRACTTINTTEXTURE]->IsTexture(); + if( blurAmount < 0 ) + { + blurAmount = 0; + } + else if( blurAmount > MAXBLUR ) + { + blurAmount = MAXBLUR; + } + bool bMasked = (params[MASKED]->GetIntValue() != 0); + + SHADOW_STATE + { + if ( params[NOWRITEZ]->GetIntValue() != 0 ) + { + pShaderShadow->EnableDepthWrites( false ); + } + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // If envmap is not specified, the alpha channel is the translucency + // (If envmap *is* specified, alpha channel is the reflection amount) + bool bNormalMapAlpha = false; + if ( params[NORMALMAP]->IsTexture() && !bHasEnvmap ) + { + SetDefaultBlendingShadowState( NORMALMAP, false ); + if ( !bMasked && TextureIsTranslucent( NORMALMAP, false ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + bNormalMapAlpha = true; + } + } + + // dudv map + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // renderable texture for refraction + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + if( bRefractTintTexture ) + { + // refract tint texture + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + if( bIsModel ) + { + userDataSize = 4; + } + else + { + fmt |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, userDataSize ); + + if( bIsModel ) + { + refract_model_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Refract_model_vs11", vshIndex.GetIndex() ); + } + else + { + refract_world_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Refract_world_vs11", vshIndex.GetIndex() ); + } + + int pshIndex; + pshIndex = ComputePixelShaderIndex( bRefractTintTexture, bNormalMapAlpha ); + pShaderShadow->SetPixelShader( "Refract_ps11", pshIndex ); + + if( bMasked ) + { + EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + } + DefaultFog(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + + if ( params[DUDVFRAME]->GetIntValue() == 0 ) + { + BindTexture( SHADER_SAMPLER0, DUDVMAP, BUMPFRAME ); + } + else + { + BindTexture( SHADER_SAMPLER0, DUDVMAP, DUDVFRAME ); + } + + if ( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + } + + if( bRefractTintTexture ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTINTTEXTURE, REFRACTTINTTEXTUREFRAME ); + } + + if ( params[NORMALMAP]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER3, NORMALMAP, BUMPFRAME ); + } + + float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + // used to invert y + // xboxfixme - move this into defined constants + float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFRACTTINT ); + if( bIsModel ) + { + refract_model_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + refract_world_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + + Draw(); + + if( bHasEnvmap ) + { + bool bNoWriteZ = (params[NOWRITEZ]->GetIntValue() != 0); + const bool bBlendSpecular = true; + if( bIsModel ) + { + DrawModelBumpedSpecularLighting( NORMALMAP, BUMPFRAME, + ENVMAP, ENVMAPFRAME, + ENVMAPTINT, ALPHA, + ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, + bBlendSpecular, bNoWriteZ ); + } + else + { + DrawWorldBumpedSpecularLighting( NORMALMAP, ENVMAP, + BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, + ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + bBlendSpecular, bNoWriteZ ); + } + } + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/refract_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/refract_dx9_helper.cpp new file mode 100644 index 00000000..f436e62a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/refract_dx9_helper.cpp @@ -0,0 +1,342 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "refract_dx9_helper.h" +#include "convar.h" +#include "Refract_vs20.inc" +#include "Refract_ps20.inc" +#include "Refract_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +#define MAXBLUR 1 + +// FIXME: doesn't support fresnel! +void InitParamsRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Refract_DX9_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + if( !params[info.m_nEnvmapTint]->IsDefined() ) + { + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + if( !params[info.m_nEnvmapContrast]->IsDefined() ) + { + params[info.m_nEnvmapContrast]->SetFloatValue( 0.0f ); + } + if( !params[info.m_nEnvmapSaturation]->IsDefined() ) + { + params[info.m_nEnvmapSaturation]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nEnvmapFrame]->IsDefined() ) + { + params[info.m_nEnvmapFrame]->SetIntValue( 0 ); + } + if( !params[info.m_nFresnelReflection]->IsDefined() ) + { + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nMasked]->IsDefined() ) + { + params[info.m_nMasked]->SetIntValue( 0 ); + } + if( !params[info.m_nBlurAmount]->IsDefined() ) + { + params[info.m_nBlurAmount]->SetIntValue( 0 ); + } + if( !params[info.m_nFadeOutOnSilhouette]->IsDefined() ) + { + params[info.m_nFadeOutOnSilhouette]->SetIntValue( 0 ); + } + if( !params[info.m_nForceAlphaWrite]->IsDefined() ) + { + params[info.m_nForceAlphaWrite]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); +} + +void InitRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, Refract_DX9_Vars_t &info ) +{ + if (params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + } + if (params[info.m_nNormalMap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap ); + } + if (params[info.m_nNormalMap2]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap2 ); + } + if( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap, TEXTUREFLAGS_SRGB ); + } + if( params[info.m_nRefractTintTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nRefractTintTexture, TEXTUREFLAGS_SRGB ); + } +} + +void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasEnvmap = params[info.m_nEnvmap]->IsTexture(); + bool bRefractTintTexture = params[info.m_nRefractTintTexture]->IsTexture(); + bool bFadeOutOnSilhouette = params[info.m_nFadeOutOnSilhouette]->GetIntValue() != 0; + int blurAmount = params[info.m_nBlurAmount]->GetIntValue(); + bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0); + bool bSecondaryNormal = ( ( info.m_nNormalMap2 != -1 ) && ( params[info.m_nNormalMap2]->IsTexture() ) ); + bool bColorModulate = ( ( info.m_nVertexColorModulate != -1 ) && ( params[info.m_nVertexColorModulate]->GetIntValue() ) ); + bool bWriteZ = params[info.m_nNoWriteZ]->GetIntValue() == 0; + + if( blurAmount < 0 ) + { + blurAmount = 0; + } + else if( blurAmount > MAXBLUR ) + { + blurAmount = MAXBLUR; + } + + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + bFullyOpaque &= !bMasked; + + bool bTranslucentNormal = pShader->TextureIsTranslucent( info.m_nNormalMap, false ); + bFullyOpaque &= (! bTranslucentNormal ); + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( g_pHardwareConfig->SupportsNormalMapCompression() ) + { + ITexture *pBumpTex = params[info.m_nNormalMap]->GetTextureValue(); + if ( pBumpTex ) + { + nNormalDecodeMode = pBumpTex->GetNormalDecodeMode(); + + if ( bSecondaryNormal ) // Check encoding of secondary normal if there is one + { + ITexture *pBumpTex2 = params[info.m_nNormalMap2]->GetTextureValue(); + if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) ) + { + DevMsg("Refract: Primary and Secondary normal map compression formats don't match. This is unsupported!\n"); + Assert(0); + } + } + } + } + + SHADOW_STATE + { + pShader->SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( bWriteZ ); + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // If envmap is not specified, the alpha channel is the translucency + // (If envmap *is* specified, alpha channel is the reflection amount) + if ( params[info.m_nNormalMap]->IsTexture() && !bHasEnvmap ) + { + pShader->SetDefaultBlendingShadowState( info.m_nNormalMap, false ); + } + + // source render target that contains the image that we are warping. + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Normal map alpha, in the compressed normal case + } + + if ( bSecondaryNormal ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Secondary normal map alpha, in the compressed normal case + } + } + + if( bHasEnvmap ) + { + // envmap + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bRefractTintTexture ) + { + // refract tint texture + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + int nTexCoordCount = 1; + if( bIsModel ) + { + userDataSize = 4; + } + else + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + + if ( bColorModulate ) + { + flags |= VERTEX_COLOR; + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( refract_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_VERTEX_SHADER( refract_vs20 ); + + // We have to do this in the shader on R500 or Leopard + bool bShaderSRGBConvert = IsOSX() && ( g_pHardwareConfig->FakeSRGBWrite() || !g_pHardwareConfig->CanDoSRGBReadFromRTs() ); + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send OpenGL down the ps2b path + { + DECLARE_STATIC_PIXEL_SHADER( refract_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); + SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSRGBConvert ); + SET_STATIC_PIXEL_SHADER( refract_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( refract_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); + SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( refract_ps20 ); + } + pShader->DefaultFog(); + if( bMasked ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + } + + bool bAlphaWrites = bFullyOpaque || ( params[ info.m_nForceAlphaWrite ]->GetIntValue() != 0 ); + pShaderShadow->EnableAlphaWrites( bAlphaWrites ); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + if ( params[info.m_nBaseTexture]->IsTexture() ) + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture, info.m_nFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + } + + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShader->BindTexture( SHADER_SAMPLER3, SHADER_SAMPLER6, info.m_nNormalMap, info.m_nBumpFrame ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame ); + } + + if ( bSecondaryNormal ) + { + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShader->BindTexture( SHADER_SAMPLER1, SHADER_SAMPLER7, info.m_nNormalMap2, info.m_nBumpFrame2 ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nNormalMap2, info.m_nBumpFrame2 ); + } + } + + if( bHasEnvmap ) + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + if( bRefractTintTexture ) + { + pShader->BindTexture( SHADER_SAMPLER5, info.m_nRefractTintTexture, info.m_nRefractTintTextureFrame ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( refract_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send Posix down the ps2b path + { + DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( refract_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( refract_ps20 ); + } + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform ); // 1 & 2 + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nBumpTransform2 ); // 3 & 4 + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + pShader->SetPixelShaderConstantGammaToLinear( 0, info.m_nEnvmapTint ); + pShader->SetPixelShaderConstantGammaToLinear( 1, info.m_nRefractTint ); + pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation ); + float c5[4] = { params[info.m_nRefractAmount]->GetFloatValue(), + params[info.m_nRefractAmount]->GetFloatValue(), 0.0f, 0.0f }; + + // Time % 1000 + c5[3] = pShaderAPI->CurrentTime(); + c5[3] -= (float)( (int)( c5[3] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + + float cVs3[4] = { c5[3], 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, cVs3, 1 ); + } + pShader->Draw(); +} + diff --git a/mp/src/materialsystem/stdshaders/refract_dx9_helper.h b/mp/src/materialsystem/stdshaders/refract_dx9_helper.h new file mode 100644 index 00000000..69d6116f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/refract_dx9_helper.h @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef REFRACT_DX9_HELPER_H +#define REFRACT_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Refract_DX9_Vars_t +{ + Refract_DX9_Vars_t() { memset( this, 0xFF, sizeof( *this ) ); } + + int m_nBaseTexture; + int m_nFrame; + int m_nRefractAmount; + int m_nRefractTint; + int m_nNormalMap; + int m_nNormalMap2; + int m_nBumpFrame; + int m_nBumpFrame2; + int m_nBumpTransform; + int m_nBumpTransform2; + int m_nBlurAmount; + int m_nFadeOutOnSilhouette; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapTint; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nRefractTintTexture; + int m_nRefractTintTextureFrame; + int m_nFresnelReflection; + int m_nNoWriteZ; + int m_nMasked; + int m_nVertexColorModulate; + int m_nForceAlphaWrite; +}; + +void InitParamsRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Refract_DX9_Vars_t &info ); +void InitRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, Refract_DX9_Vars_t &info ); +void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // REFRACT_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/refract_ps2x.fxc b/mp/src/materialsystem/stdshaders/refract_ps2x.fxc new file mode 100644 index 00000000..2f974230 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/refract_ps2x.fxc @@ -0,0 +1,250 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======= +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "BLUR" "0..1" +// STATIC: "FADEOUTONSILHOUETTE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "REFRACTTINTTEXTURE" "0..1" +// STATIC: "MASKED" "0..1" +// STATIC: "COLORMODULATE" "0..1" +// STATIC: "SECONDARY_NORMAL" "0..1" +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] +// STATIC: "SHADER_SRGB_READ" "0..1" [ps20b] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $MASKED && $BLUR + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler NormalSampler2 : register( s1 ); +sampler RefractSampler : register( s2 ); +sampler NormalSampler : register( s3 ); +#if CUBEMAP +sampler EnvmapSampler : register( s4 ); +#endif +#if REFRACTTINTTEXTURE +sampler RefractTintSampler : register( s5 ); +#endif + +#if NORMAL_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMapSampler : register( s6 ); // alpha +sampler AlphaMapSampler2 : register( s7 ); +#else +#define AlphaMapSampler2 NormalSampler +#define AlphaMapSampler NormalSampler2 +#endif + +const float3 g_EnvmapTint : register( c0 ); +const float3 g_RefractTint : register( c1 ); +const float3 g_EnvmapContrast : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_c5 : register( c5 ); +#define g_RefractScale g_c5.x +#define g_flTime g_c5.w + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +static const int g_BlurCount = BLUR; +static const float g_BlurFraction = 1.0f / 512.0f; +static const float g_HalfBlurFraction = 0.5 * g_BlurFraction; +static const float4 g_BlurFractionVec = float4( g_BlurFraction, g_HalfBlurFraction, + -g_BlurFraction,-g_HalfBlurFraction ); + +struct PS_INPUT +{ + float4 vBumpTexCoord : TEXCOORD0; // NormalMap1 in xy, NormalMap2 in wz + float3 vTangentVertToEyeVector : TEXCOORD1; + float3 vWorldNormal : TEXCOORD2; + float3 vWorldTangent : TEXCOORD3; + float3 vWorldBinormal : TEXCOORD4; + float3 vRefractXYW : TEXCOORD5; + float3 vWorldViewVector : TEXCOORD6; +#if COLORMODULATE + float4 ColorModulate : COLOR0; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 result; + + float pixelFogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + +#if FADEOUTONSILHOUETTE + //float blend = -i.projNormal.z; + float blend = saturate( dot( -i.vWorldViewVector.xyz, i.vWorldNormal.xyz ) ); + blend = blend * blend * blend; +#else + float blend = 1.0f; +#endif + + // Decompress normal + float4 vNormal = DecompressNormal( NormalSampler, i.vBumpTexCoord.xy, NORMAL_DECODE_MODE, AlphaMapSampler ); + +#if SECONDARY_NORMAL + float3 vNormal2 = DecompressNormal( NormalSampler2, i.vBumpTexCoord.wz, NORMAL_DECODE_MODE, AlphaMapSampler2 ); + vNormal.xyz = normalize( vNormal.xyz + vNormal2.xyz ); +#endif + +#if REFRACTTINTTEXTURE + float3 refractTintColor = 2.0 * g_RefractTint * tex2D( RefractTintSampler, i.vBumpTexCoord.xy ); +#else + float3 refractTintColor = g_RefractTint; +#endif + +#if COLORMODULATE + refractTintColor *= i.ColorModulate.rgb; +#endif + + // Perform division by W only once + float ooW = 1.0f / i.vRefractXYW.z; + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.vRefractXYW.xy * ooW; + float2 vRefractTexCoord = vNormal.xy; + float scale = vNormal.a * g_RefractScale; +#if COLORMODULATE + scale *= i.ColorModulate.a; +#endif + vRefractTexCoord *= scale; + vRefractTexCoord += vRefractTexCoordNoWarp; + +#if (BLUR==1) // use polyphase magic to convert 9 lookups into 4 + + // basic principle behind this transformation: + // [ A B C ] + // [ D E F ] + // [ G H I ] + // use bilinear filtering hardware to weight upper 2x2 samples evenly (0.25* [A + B + D + E]). + // scale the upper 2x2 by 4/9 (total area of kernel occupied) + // use bilinear filtering hardware to weight right 1x2 samples evenly (0.5*[C + F]) + // scale right 1x2 by 2/9 + // use bilinear filtering hardware to weight lower 2x1 samples evenly (0.5*[G + H]) + // scale bottom 2x1 by 2/9 + // fetch last sample (I) and scale by 1/9. + + float2 upper_2x2_loc = vRefractTexCoord.xy - float2(g_HalfBlurFraction, g_HalfBlurFraction); + float2 right_1x2_loc = vRefractTexCoord.xy + float2(g_BlurFraction, -g_HalfBlurFraction); + float2 lower_2x1_loc = vRefractTexCoord.xy + float2(-g_HalfBlurFraction, g_BlurFraction); + float2 singleton_loc = vRefractTexCoord.xy + float2(g_BlurFraction, g_BlurFraction); + result = tex2D(RefractSampler, upper_2x2_loc) * 0.4444444; + result += tex2D(RefractSampler, right_1x2_loc) * 0.2222222; + result += tex2D(RefractSampler, lower_2x1_loc) * 0.2222222; + result += tex2D(RefractSampler, singleton_loc) * 0.1111111; + + #if ( SHADER_SRGB_READ == 1 ) + { + // Just do this once rather than after every blur step, which is wrong, but much more efficient + result = GammaToLinear( result ); + } + #endif + + float3 unblurredColor = tex2D(RefractSampler, vRefractTexCoordNoWarp.xy); + #if ( SHADER_SRGB_READ == 1 ) + { + unblurredColor = GammaToLinear( unblurredColor ); + } + #endif + + result = lerp(unblurredColor, result * refractTintColor, blend); + +#elif (BLUR>0) // iteratively step through render target + int x, y; + + result = float3( 0.0f, 0.0f, 0.0f ); + for( x = -g_BlurCount; x <= g_BlurCount; x++ ) + { + for( y = -g_BlurCount; y <= g_BlurCount; y++ ) + { + result += tex2D( RefractSampler, vRefractTexCoord.xy + float2( g_BlurFraction * x, g_BlurFraction * y ) ); + } + } + + int width = g_BlurCount * 2 + 1; + result *= 1.0f / ( width * width ); + + #if ( SHADER_SRGB_READ == 1 ) + { + // Just do this once rather than after every blur step, which is wrong, but much more efficient + result = GammaToLinear( result ); + } + #endif + + // result is the blurred one now. . .now lerp. + float3 unblurredColor = tex2D( RefractSampler, vRefractTexCoordNoWarp.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + unblurredColor = GammaToLinear( unblurredColor ); + } + #endif + + result = lerp( unblurredColor, result * refractTintColor, blend ); +#else +# if MASKED + float4 fMaskedResult = tex2D( RefractSampler, vRefractTexCoord.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + fMaskedResult = GammaToLinear( fMaskedResult ); + } + #endif + + return FinalOutput( fMaskedResult, pixelFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); +# else + float3 colorWarp = tex2D( RefractSampler, vRefractTexCoord.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + colorWarp = GammaToLinear( colorWarp ); + } + #endif + float3 colorNoWarp = tex2D( RefractSampler, vRefractTexCoordNoWarp.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + colorNoWarp = GammaToLinear( colorNoWarp ); + } + #endif + + colorWarp *= refractTintColor; + result = lerp( colorNoWarp, colorWarp, blend ); +# endif +#endif + +#if CUBEMAP + float specularFactor = vNormal.a; + + float3 worldSpaceNormal = Vec3TangentToWorld( vNormal.xyz, i.vWorldNormal, i.vWorldTangent, i.vWorldBinormal ); + + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.vTangentVertToEyeVector ); + float3 specularLighting = texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + result += specularLighting; +#endif + +#if COLORMODULATE + float resultAlpha = i.ColorModulate.a * vNormal.a; +#else + float resultAlpha = vNormal.a; +#endif + + return FinalOutput( float4( result, resultAlpha ), pixelFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/mp/src/materialsystem/stdshaders/shadowmodel_dx8.cpp b/mp/src/materialsystem/stdshaders/shadowmodel_dx8.cpp new file mode 100644 index 00000000..e7d7228a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/shadowmodel_dx8.cpp @@ -0,0 +1,97 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "shadowmodel.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( ShadowModel, ShadowModel_DX8 ) + +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX8, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) + SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) + SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) + SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) + SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + if (!params[BASETEXTURESCALE]->IsDefined()) + { + Vector2D scale(1, 1); + params[BASETEXTURESCALE]->SetVecValue( scale.Base(), 2 ); + } + + if (!params[FALLOFFDISTANCE]->IsDefined()) + params[FALLOFFDISTANCE]->SetFloatValue( 100.0f ); + + if (!params[FALLOFFAMOUNT]->IsDefined()) + params[FALLOFFAMOUNT]->SetFloatValue( 0.9f ); + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Base texture on stage 0 + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Multiplicative blending state... + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_ZERO ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + shadowmodel_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "ShadowModel", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "ShadowModel" ); + + // We need to fog to *white* regardless of overbrighting... + FogToWhite(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderMatrix3x4( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTUREOFFSET ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURESCALE ); + + Vector4D shadow; + shadow[0] = params[FALLOFFOFFSET]->GetFloatValue(); + shadow[1] = params[FALLOFFDISTANCE]->GetFloatValue() + shadow[0]; + if (shadow[1] != 0.0f) + shadow[1] = 1.0f / shadow[1]; + shadow[2] = params[FALLOFFAMOUNT]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, shadow.Base(), 1 ); + + // The constant color is the shadow color... + SetModulationVertexShaderDynamicState(); + + shadowmodel_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw( ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/shadowmodel_dx9.cpp b/mp/src/materialsystem/stdshaders/shadowmodel_dx9.cpp new file mode 100644 index 00000000..0198e86f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/shadowmodel_dx9.cpp @@ -0,0 +1,154 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +//Note: Not upgraded to vs/ps 2.0 fxc's because this shader is unused and there are no test cases to verify against. +#include "BaseVSShader.h" + +#if !defined( _X360 ) +#include "shadowmodel_ps20.inc" +#include "shadowmodel_vs20.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( ShadowModel, ShadowModel_DX9 ) + + +#if !defined( _X360 ) //not used for anything at time of 360 ship, and we want to avoid storing/loading assembly shaders + +//PC version +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX9, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + +BEGIN_SHADER_PARAMS +SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) +SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) +SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) +SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) +SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ + if (!params[BASETEXTURESCALE]->IsDefined()) + { + Vector2D scale(1, 1); + params[BASETEXTURESCALE]->SetVecValue( scale.Base(), 2 ); + } + + if (!params[FALLOFFDISTANCE]->IsDefined()) + params[FALLOFFDISTANCE]->SetFloatValue( 100.0f ); + + if (!params[FALLOFFAMOUNT]->IsDefined()) + params[FALLOFFAMOUNT]->SetFloatValue( 0.9f ); +} + +SHADER_FALLBACK +{ + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "ShadowModel_DX8"; + + return 0; +} + +SHADER_INIT +{ + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + } +} + +SHADER_DRAW +{ + SHADOW_STATE + { + // Base texture on stage 0 + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Multiplicative blending state... + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_ZERO ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( shadowmodel_vs20 ); + SET_STATIC_VERTEX_SHADER( shadowmodel_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( shadowmodel_ps20 ); + SET_STATIC_PIXEL_SHADER( shadowmodel_ps20 ); + + // We need to fog to *white* regardless of overbrighting... + FogToWhite(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderMatrix3x4( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTUREOFFSET ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURESCALE ); + + Vector4D shadow; + shadow[0] = params[FALLOFFOFFSET]->GetFloatValue(); + shadow[1] = params[FALLOFFDISTANCE]->GetFloatValue() + shadow[0]; + if (shadow[1] != 0.0f) + shadow[1] = 1.0f / shadow[1]; + shadow[2] = params[FALLOFFAMOUNT]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, shadow.Base(), 1 ); + + // The constant color is the shadow color... + SetModulationVertexShaderDynamicState(); + + DECLARE_DYNAMIC_VERTEX_SHADER( shadowmodel_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( shadowmodel_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( shadowmodel_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( shadowmodel_ps20 ); + } + Draw( ); +} +END_SHADER + + +#else + +//360 version + +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX9, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + +BEGIN_SHADER_PARAMS +SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) +SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) +SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) +SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) +SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ +} + +SHADER_FALLBACK +{ + return 0; +} + +SHADER_INIT +{ +} + +SHADER_DRAW +{ + Draw( false ); +} +END_SHADER + +#endif \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/shadowmodel_ps20.fxc b/mp/src/materialsystem/stdshaders/shadowmodel_ps20.fxc new file mode 100644 index 00000000..d0aedda9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/shadowmodel_ps20.fxc @@ -0,0 +1,20 @@ + +struct PS_INPUT +{ + float4 T0 : TEXCOORD0; + float3 T1 : TEXCOORD1; + float3 T2 : TEXCOORD2; + float T3 : TEXCOORD3; + float3 vColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + // Kill pixel against various fields computed in vertex shader + clip ( i.T1 ); + clip ( i.T2 ); + clip ( i.T3 ); // Backface cull + + // i.T0.a is uninitialized by the vs, but this is how the original asm shader was written???? + return float4( lerp( float3(1,1,1), i.vColor.xyz, i.T0.a ), 1 ); +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/shadowmodel_vs20.fxc b/mp/src/materialsystem/stdshaders/shadowmodel_vs20.fxc new file mode 100644 index 00000000..9d1ff02c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/shadowmodel_vs20.fxc @@ -0,0 +1,81 @@ +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cShadowTextureMatrix[3] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cTexOrigin : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cTexScale : register( SHADER_SPECIFIC_CONST_4 ); + +// { Shadow falloff offset, 1/Shadow distance, Shadow scale, 0 } +const float3 cShadowConstants : register( SHADER_SPECIFIC_CONST_5 ); +#define flShadowFalloffOffset cShadowConstants.x +#define flOneOverShadowDist cShadowConstants.y +#define flShadowScale cShadowConstants.z + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float3 vNormal : NORMAL; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position + float3 T0 : TEXCOORD0; // PS wants this to be 4D but VS doesn't? (see original asm sources) + float3 T1 : TEXCOORD1; + float3 T2 : TEXCOORD2; + float T3 : TEXCOORD3; + float4 vColor : COLOR0; + float fog : FOG; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( g_bSkinning, v.vPos, v.vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + + // Compute fog + o.fog = CalcFog( worldPos, o.projPos, g_FogType ); + + // Transform position into texture space (from 0 to 1) + float3 vTexturePos; + vTexturePos.x = dot( worldPos.xyz, cShadowTextureMatrix[0].xyz ); + vTexturePos.y = dot( worldPos.xyz, cShadowTextureMatrix[1].xyz ); + vTexturePos.z = dot( worldPos.xyz, cShadowTextureMatrix[2].xyz ); + + // Figure out the shadow fade amount + float flShadowFade = ( vTexturePos.z - flShadowFalloffOffset ) * flOneOverShadowDist; + + // Offset it into the texture + o.T0 = vTexturePos * cTexScale + cTexOrigin; + + // We're doing clipping by using texkill + o.T1.xyz = vTexturePos.xyz; // Also clips when shadow z < 0 ! + o.T2.xyz = float3( 1.0f, 1.0f, 1.0f ) - vTexturePos.xyz; + o.T2.z = 1.0f - flShadowFade; // Clips when shadow z > shadow distance + + // We're doing backface culling by using texkill also (wow yucky) + // -------------------------------------------------------------- + // Transform z component of normal in texture space + // If it's negative, then don't draw the pixel + o.T3 = dot( worldNormal, -cShadowTextureMatrix[2] ); + + // Shadow color, falloff + o.vColor.xyz = cModulationColor.xyz; + o.vColor.w = flShadowFade * flShadowScale; + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp new file mode 100644 index 00000000..1e2d30f3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp @@ -0,0 +1,977 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "BaseVSShader.h" +#include "skin_dx9_helper.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "skin_vs20.inc" +#include "skin_ps20b.inc" +#include "commandbuilder.h" + +#ifndef _X360 +#include "skin_vs30.inc" +#include "skin_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); + +// Textures may be bound to the following samplers: +// SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha +// SHADER_SAMPLER1 Specular warp (including iridescence) +// SHADER_SAMPLER2 Diffuse Lighting warp texture +// SHADER_SAMPLER3 Normal Map +// SHADER_SAMPLER4 Flashlight Shadow Depth Map +// SHADER_SAMPLER5 Normalization cube map +// SHADER_SAMPLER6 Flashlight Cookie +// SHADER_SAMPLER7 Specular exponent +// SHADER_SAMPLER8 Cubic environment map +// SHADER_SAMPLER9 Compressed wrinklemap +// SHADER_SAMPLER10 Stretched wrinklemap +// SHADER_SAMPLER11 Compressed wrinkle normal map +// SHADER_SAMPLER12 Stretched wrinkle normal map +// SHADER_SAMPLER13 Detail texture + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info ) +{ + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping. + if( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // No texture means no env mask in base alpha + if ( !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // Lots of reasons to want tangent space, since we bind a flat normal map in many cases where we don't have a bump map + bool bBump = (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined(); + bool bEnvMap = (info.m_nEnvmap != -1) && params[info.m_nEnvmap]->IsDefined(); + bool bDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined(); + bool bPhong = (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined(); + if( bBump || bEnvMap || bDiffuseWarp || bPhong ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } + + if ( ( info.m_nSelfIllumFresnel != -1 ) && ( !params[info.m_nSelfIllumFresnel]->IsDefined() ) ) + { + params[info.m_nSelfIllumFresnel]->SetIntValue( 0 ); + } + + if ( ( info.m_nSelfIllumFresnelMinMaxExp != -1 ) && ( !params[info.m_nSelfIllumFresnelMinMaxExp]->IsDefined() ) ) + { + params[info.m_nSelfIllumFresnelMinMaxExp]->SetVecValue( 0.0f, 1.0f, 1.0f ); + } + + if ( ( info.m_nBaseMapAlphaPhongMask != -1 ) && ( !params[info.m_nBaseMapAlphaPhongMask]->IsDefined() ) ) + { + params[info.m_nBaseMapAlphaPhongMask]->SetIntValue( 0 ); + } + + if ( ( info.m_nEnvmapFresnel != -1 ) && ( !params[info.m_nEnvmapFresnel]->IsDefined() ) ) + { + params[info.m_nEnvmapFresnel]->SetFloatValue( 0 ); + } +} + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- +void InitSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, VertexLitGeneric_DX9_Vars_t &info ) +{ + Assert( info.m_nFlashlightTexture >= 0 ); + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + + bool bIsBaseTextureTranslucent = false; + if ( params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + + if ( ( info.m_nWrinkle != -1 ) && ( info.m_nStretch != -1 ) && + params[info.m_nWrinkle]->IsDefined() && params[info.m_nStretch]->IsDefined() ) + { + pShader->LoadTexture( info.m_nWrinkle, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nStretch, TEXTUREFLAGS_SRGB ); + } + } + + bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsDefined(); + + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + // Can still be self illum with no base alpha if using one of these alternate modes + if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nPhongExponentTexture ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + if ( (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nPhongWarpTexture ); + } + + if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() ) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + if ( nDetailBlendMode == 0 ) // Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail, TEXTUREFLAGS_SRGB ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + + if ( ( info.m_nNormalWrinkle != -1 ) && ( info.m_nNormalStretch != -1 ) && + params[info.m_nNormalWrinkle]->IsDefined() && params[info.m_nNormalStretch]->IsDefined() ) + { + pShader->LoadTexture( info.m_nNormalWrinkle ); + pShader->LoadTexture( info.m_nNormalStretch ); + } + } + } + + if ( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + + if ( bHasSelfIllumMask ) + { + pShader->LoadTexture( info.m_nSelfIllumMask ); + } +} + +class CSkin_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; + bool m_bFastPath; + +}; + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bHasFlashlight, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ + bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture(); + bool bHasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture(); + + bool bHasBaseTextureWrinkle = bHasBaseTexture && + (info.m_nWrinkle != -1) && params[info.m_nWrinkle]->IsTexture() && + (info.m_nStretch != -1) && params[info.m_nStretch]->IsTexture(); + + bool bHasBumpWrinkle = bHasBump && + (info.m_nNormalWrinkle != -1) && params[info.m_nNormalWrinkle]->IsTexture() && + (info.m_nNormalStretch != -1) && params[info.m_nNormalStretch]->IsTexture(); + + bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bHasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) != 0; + bool bHasSelfIllumFresnel = ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + bool bHasSelfIllumMask = ( bHasSelfIllum ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsTexture(); + + // Tie these to specular + bool bHasPhong = (info.m_nPhong != -1) && ( params[info.m_nPhong]->GetIntValue() != 0 ); + bool bHasSpecularExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture(); + bool bHasPhongTintMap = bHasSpecularExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 ); + bool bHasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + bool bHasPhongWarp = (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsTexture(); + bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + +#if !defined( _X360 ) + bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); +#endif + + // Rimlight must be set to non-zero to trigger rim light combo (also requires Phong) + bool bHasRimLight = r_rimlight.GetBool() && bHasPhong && (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 ); + bool bHasRimMaskMap = bHasSpecularExponentTexture && bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 ); + + float fBlendFactor=( info.m_nDetailTextureBlendFactor == -1 )? 1 : params[info.m_nDetailTextureBlendFactor]->GetFloatValue(); + bool hasDetailTexture = ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsTexture(); + int nDetailBlendMode = ( hasDetailTexture && info.m_nDetailTextureCombineMode != -1 ) ? params[info.m_nDetailTextureCombineMode]->GetIntValue() : 0; + + bool bBlendTintByBaseAlpha = IsBoolSet( info.m_nBlendTintByBaseAlpha, params ) && !bHasSelfIllum; // Pixel shader can't do both BLENDTINTBYBASEALPHA and SELFILLUM, so let selfillum win + + float flTintReplacementAmount = GetFloatParam( info.m_nTintReplacesBaseColor, params ); + + BlendType_t nBlendType= pShader->EvaluateBlendRequirements( bBlendTintByBaseAlpha ? -1 : info.m_nBaseTexture, true ); + + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlight; //dest alpha is free for special use + + CSkin_DX9_Context *pContextData = reinterpret_cast< CSkin_DX9_Context *> ( *pContextDataPtr ); + if ( ! pContextData ) + { + pContextData = new CSkin_DX9_Context; + *pContextDataPtr = pContextData; + } + + if( pShader->IsSnapshotting() ) + { + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + bool bHasEnvmap = !bHasFlashlight && params[info.m_nEnvmap]->IsTexture(); + bool bHasNormal = params[info.m_nBumpmap]->IsTexture(); + bool bCanUseBaseAlphaPhongMaskFastPath = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 ); + + if ( ! ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) ) + bCanUseBaseAlphaPhongMaskFastPath = true; + + pContextData->m_bFastPath = + (! bHasBump ) && + (! bHasSpecularExponentTexture ) && + (! bHasPhongTintMap ) && + (! bHasPhongWarp ) && + (! bHasRimLight ) && + (! hasDetailTexture ) && + bCanUseBaseAlphaPhongMaskFastPath && + (! bHasSelfIllum ) && + (! bBlendTintByBaseAlpha ); + + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if( bHasFlashlight ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + else // not flashlight pass + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + + if ( bHasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Cubic environment map + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); + } + } + } + + unsigned int flags = VERTEX_POSITION; + if( bHasNormal ) + { + flags |= VERTEX_NORMAL; + } + + int userDataSize = 0; + + // Always enable...will bind white if nothing specified... + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if ( bHasBaseTextureWrinkle || bHasBumpWrinkle ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Base (albedo) compression map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // Base (albedo) expansion map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true ); + } + + if( bHasDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Diffuse warp texture + } + + if( bHasPhongWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Specular warp texture + } + + // Specular exponent map or dummy + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Specular exponent map + + if( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true ); + userDataSize = 4; // tangent S + } + + // Always enable, since flat normal will be bound + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Normal map + userDataSize = 4; // tangent S + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Normalizing cube map + + if ( bHasBaseTextureWrinkle || bHasBumpWrinkle ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // Normal compression map + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); // Normal expansion map + } + + if ( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER13, true ); + } + + if ( bHasSelfIllum ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + } + + if( bHasVertexColor || bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + + pShaderShadow->EnableSRGBWrite( true ); + + // texcoord0 : base texcoord, texcoord2 : decal hw morph delta + int pTexCoordDim[3] = { 2, 0, 3 }; + int nTexCoordCount = 1; + +#ifndef _X360 + // Special morphed decal information + if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( skin_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( skin_vs20 ); + + // Assume we're only going to get in here if we support 2b + DECLARE_STATIC_PIXEL_SHADER( skin_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, bHasPhongWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, bHasBaseTextureWrinkle || bHasBumpWrinkle ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bHasRimLight ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FASTPATH_NOBUMP, pContextData->m_bFastPath ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( skin_ps20b ); + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( skin_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER( skin_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( skin_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, bHasPhongWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, bHasBaseTextureWrinkle || bHasBumpWrinkle ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bHasRimLight ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FASTPATH_NOBUMP, pContextData->m_bFastPath ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( skin_ps30 ); + } +#endif + + if( bHasFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + else // not snapshotting -- begin dynamic state + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + bool bHasEnvmap = !bHasFlashlight && params[info.m_nEnvmap]->IsTexture(); + + if( bHasBaseTexture ) + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + if ( bHasBaseTextureWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER9, info.m_nWrinkle, info.m_nBaseTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER10, info.m_nStretch, info.m_nBaseTextureFrame ); + } + else if ( bHasBumpWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER9, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER10, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + + if( bHasDiffuseWarp && bHasPhong ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nDiffuseWarpTexture ); + } + } + + if( bHasPhongWarp ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nPhongWarpTexture ); + } + + if( bHasSpecularExponentTexture && bHasPhong ) + { + pShader->BindTexture( SHADER_SAMPLER7, info.m_nPhongExponentTexture ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE ); + } + + if( !g_pConfig->m_bFastNoBump ) + { + if( bHasBump ) + pShader->BindTexture( SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + else + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + + if ( bHasBumpWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER11, info.m_nNormalWrinkle, info.m_nBumpFrame ); + pShader->BindTexture( SHADER_SAMPLER12, info.m_nNormalStretch, info.m_nBumpFrame ); + } + else if ( bHasBaseTextureWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER11, info.m_nBumpmap, info.m_nBumpFrame ); + pShader->BindTexture( SHADER_SAMPLER12, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else + { + if( bHasBump ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + if ( bHasBaseTextureWrinkle || bHasBumpWrinkle ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER11, TEXTURE_NORMALMAP_FLAT ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER12, TEXTURE_NORMALMAP_FLAT ); + } + } + + if ( hasDetailTexture ) + { + pShader->BindTexture( SHADER_SAMPLER13, info.m_nDetail, info.m_nDetailFrame ); + } + + if ( bHasSelfIllum ) + { + if ( bHasSelfIllumMask ) // Separate texture for self illum? + { + pShader->BindTexture( SHADER_SAMPLER14, info.m_nSelfIllumMask ); // Bind it + } + else // else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER14, TEXTURE_BLACK ); // Bind dummy + } + } + + LightState_t lightState = { 0, false, false }; + bool bFlashlightShadows = false; + if( bHasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame ); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + } + else // no flashlight + { + if ( bHasEnvmap ) + { + pShader->BindTexture( SHADER_SAMPLER8, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + int numBones = pShaderAPI->GetCurrentNumBones(); + + // don't have an easy way to get this through to GLM, so just print it old school + //printf("\n-D- DrawSkin_DX9_Internal numBones is %d", numBones ); + + bool bWriteDepthToAlpha = false; + bool bWriteWaterFogToAlpha = false; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( skin_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( skin_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( skin_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( skin_ps20b ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( skin_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( skin_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( skin_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( skin_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + + if( bHasBump ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + + if ( hasDetailTexture ) + { + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, + info.m_nDetailTextureTransform, + info.m_nDetailScale ); + else + pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, + info.m_nBaseTextureTransform, + info.m_nDetailScale ); + } + + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + pShader->SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, fBlendFactor ); + bool bInvertPhongMask = ( info.m_nInvertPhongMask != -1 ) && ( params[info.m_nInvertPhongMask]->GetIntValue() != 0 ); + float fInvertPhongMask = bInvertPhongMask ? 1 : 0; + + bool bHasBaseAlphaPhongMask = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 ); + float fHasBaseAlphaPhongMask = bHasBaseAlphaPhongMask ? 1 : 0; + // Controls for lerp-style paths through shader code + float vShaderControls[4] = { fHasBaseAlphaPhongMask, 0.0f/*unused*/, flTintReplacementAmount, fInvertPhongMask }; + pShaderAPI->SetPixelShaderConstant( PSREG_CONSTANT_27, vShaderControls, 1 ); + + if ( hasDetailTexture ) + { +#if 0 // needs constant change + if ( info.m_nDetailTint != -1 ) + pShader->SetPixelShaderConstantGammaToLinear( 10, info.m_nDetailTint ); + else + { + float boring_tint[4]={1,1,1,1}; + pShaderAPI->SetPixelShaderConstant( 10, boring_tint, 1 ); + } +#endif + } + + if ( bHasSelfIllumFresnel && !bHasFlashlight ) + { + float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f; + float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f; + float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f; + + vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias + vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale + vConstScaleBiasExp[2] = flExp; // Exp + vConstScaleBiasExp[3] = flMax; // Brightness + + pShaderAPI->SetPixelShaderConstant( PSREG_SELFILLUM_SCALE_BIAS_EXP, vConstScaleBiasExp, 1 ); + } + + pShader->SetAmbientCubeDynamicStateVertexShader(); + + if( !bHasFlashlight ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // Setting .x to 1 means to apply Fresnel to env map. Setting w to 1 means use separate selfillummask + float vEnvMapFresnel_SelfIllumMask[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + vEnvMapFresnel_SelfIllumMask[3] = bHasSelfIllumMask ? 1.0f : 0.0f; + + if( bHasEnvmap ) + { + float vEnvMapTint_MaskControl[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + + // If we have a tint, grab it + if ( (info.m_nEnvmapTint != -1) && params[info.m_nEnvmapTint]->IsDefined() ) + params[info.m_nEnvmapTint]->GetVecValue(vEnvMapTint_MaskControl, 3); + + // Set control for source of env map mask (normal alpha or base alpha) + vEnvMapTint_MaskControl[3] = bHasNormalMapAlphaEnvmapMask ? 1.0f : 0.0f; + + if ( (info.m_nEnvmapFresnel != -1) && params[info.m_nEnvmapFresnel]->IsDefined() ) + vEnvMapFresnel_SelfIllumMask[0] = params[info.m_nEnvmapFresnel]->GetFloatValue(); + + // Handle mat_fullbright 2 (diffuse lighting only with 50% gamma space basetexture) + if( bLightingOnly ) + { + vEnvMapTint_MaskControl[0] = vEnvMapTint_MaskControl[1] = vEnvMapTint_MaskControl[2] = 0.0f; + } + + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, vEnvMapTint_MaskControl, 1 ); + } + + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_FRESNEL__SELFILLUMMASK, vEnvMapFresnel_SelfIllumMask, 1 ); + } + + pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight ); // Force to black if not bAmbientLight + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + + // Pack Phong exponent in with the eye position + float vEyePos_SpecExponent[4], vFresnelRanges_SpecBoost[4] = {1, 0.5, 1, 1}, vRimBoost[4] = {1, 1, 1, 1}; + float vSpecularTint[4] = {1, 1, 1, 4}; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + + // Use the alpha channel of the normal map for the exponent by default + vEyePos_SpecExponent[3] = -1.f; + if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) + { + float fValue = params[info.m_nPhongExponent]->GetFloatValue(); + if ( fValue > 0.f ) + { + // Nonzero value in material overrides map channel + vEyePos_SpecExponent[3] = fValue; + } + } + + // Get the tint parameter + if ( (info.m_nPhongTint != -1) && params[info.m_nPhongTint]->IsDefined() ) + { + params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 3); + } + + // Get the rim light power (goes in w of Phong tint) + if ( bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() ) + { + vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue(); + vSpecularTint[3] = max(vSpecularTint[3], 1.0f); // Make sure this is at least 1 + } + + // Get the rim boost (goes in w of flashlight position) + if ( bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() ) + { + vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue(); + } + + if ( !bHasFlashlight ) + { + float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code + vRimMaskControl[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f; + + // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 ); + } + + // If it's all zeros, there was no constant tint in the vmt + if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) ) + { + if ( bHasPhongTintMap ) // If we have a map to use, tell the shader + { + vSpecularTint[0] = -1; + } + else // Otherwise, just tint with white + { + vSpecularTint[0] = 1.0f; + vSpecularTint[1] = 1.0f; + vSpecularTint[2] = 1.0f; + } + } + + // handle mat_fullbright 2 (diffuse lighting only) + if( bLightingOnly ) + { + // BASETEXTURE + if( bHasSelfIllum && !bHasFlashlight ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + // DETAILTEXTURE + if ( hasDetailTexture ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER13, TEXTURE_GREY ); + } + + // turn off specularity + vSpecularTint[0] = vSpecularTint[1] = vSpecularTint[2] = 0.0f; + } + + if ( (info.m_nPhongFresnelRanges != -1) && params[info.m_nPhongFresnelRanges]->IsDefined() ) + { + params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 ); // Grab optional Fresnel range parameters + // Change fresnel range encoding from (min, mid, max) to ((mid-min)*2, mid, (max-mid)*2) + vFresnelRanges_SpecBoost[0] = (vFresnelRanges_SpecBoost[1] - vFresnelRanges_SpecBoost[0]) * 2; + vFresnelRanges_SpecBoost[2] = (vFresnelRanges_SpecBoost[2] - vFresnelRanges_SpecBoost[1]) * 2; + } + + if ( (info.m_nPhongBoost != -1 ) && params[info.m_nPhongBoost]->IsDefined()) // Grab optional Phong boost param + vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue(); + else + vFresnelRanges_SpecBoost[3] = 1.0f; + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 ); // Rim boost in w on non-flashlight pass + + pShaderAPI->SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 ); + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + // flashlightfixme: put this in common code. + if( bHasFlashlight ) + { + VMatrix worldToTexture; + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } + } + } + pShader->Draw(); +} + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +extern ConVar r_flashlight_version2; +void DrawSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) + +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawSkin_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, false, info, vertexCompression, pContextDataPtr++ ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawSkin_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bHasFlashlight, info, vertexCompression, pContextDataPtr ); +} diff --git a/mp/src/materialsystem/stdshaders/skin_dx9_helper.h b/mp/src/materialsystem/stdshaders/skin_dx9_helper.h new file mode 100644 index 00000000..414e8dd2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/skin_dx9_helper.h @@ -0,0 +1,35 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef SKIN_DX9_HELPER_H +#define SKIN_DX9_HELPER_H + +#include + +#include "vertexlitgeneric_dx9_helper.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +void InitParamsSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, + const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info ); +void InitSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, + VertexLitGeneric_DX9_Vars_t &info ); + +void DrawSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + + + +#endif // SKIN_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/skin_ps20b.fxc b/mp/src/materialsystem/stdshaders/skin_ps20b.fxc new file mode 100644 index 00000000..20c3eef9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/skin_ps20b.fxc @@ -0,0 +1,371 @@ +//======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== +// STATIC: "CONVERT_TO_SRGB" "0..0" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "SELFILLUMFRESNEL" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "PHONGWARPTEXTURE" "0..1" +// STATIC: "WRINKLEMAP" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..6" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "RIMLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "FASTPATH_NOBUMP" "0..1" +// STATIC: "BLENDTINTBYBASEALPHA" "0..1" + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + + +// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) + +// blend mode doesn't matter if we only have one texture +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30] + +// Only need self illum fresnel when self illum enabled +// SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUM == 1 ) + +// BlendTintByBaseAlpha and self illum and are opposing meanings for alpha channel +// SKIP: ( $BLENDTINTBYBASEALPHA ) && ( $SELFILLUM ) + +// fastpath means: +// no bumpmap +// basealphaenvmapmask (not inverted) +// no spec expmap +// no spectint +// no specwarp +// no rimlight +// no selfillum +// no detail +// no BlendTintByBaseAlpha + +// SKIP: $FASTPATH_NOBUMP && ( $RIMLIGHT || $DETAILTEXTURE || $PHONGWARPTEXTURE || $SELFILLUM || $BLENDTINTBYBASEALPHA ) + + + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +const float4 g_SelfIllumTint_and_DetailBlendFactor : register( PSREG_SELFILLUMTINT ); +#if ( SELFILLUMFRESNEL == 1 ) +const float4 g_SelfIllumScaleBiasExpBrightness : register( PSREG_SELFILLUM_SCALE_BIAS_EXP ); +#endif +const float4 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION ); +const float4 g_EnvmapTint_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); // w controls spec mask +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EnvMapFresnel : register( PSREG_ENVMAP_FRESNEL__SELFILLUMMASK ); // x is envmap fresnel ... w is selfillummask control +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control +const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost +const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total (4th light spread across w's) + +// TODO: give this a better name. For now, I don't want to touch shader_constant_register_map.h since I don't want to trigger a recompile of everything... +const float4 g_ShaderControls : register( PSREG_CONSTANT_27 ); // x is basemap alpgha phong mask, y is 1 - blendtintbybasealpha, z is tint overlay amount, w controls "INVERTPHONGMASK" +#define g_FlashlightPos g_FlashlightPos_RimBoost.xyz +#define g_fRimBoost g_FlashlightPos_RimBoost.w +#define g_FresnelRanges g_FresnelSpecParams.xyz +#define g_SpecularBoost g_FresnelSpecParams.w +#define g_SpecularTint g_SpecularRimParams.xyz +#define g_RimExponent g_SpecularRimParams.w +#define g_FlashlightAttenuationFactors g_FlashlightAttenuationFactors_RimMask +#define g_RimMaskControl g_FlashlightAttenuationFactors_RimMask.x +#define g_SelfIllumMaskControl g_EnvMapFresnel.w +#define g_fBaseMapAlphaPhongMask g_ShaderControls.x +#define g_fTintReplacementControl g_ShaderControls.z +#define g_fInvertPhongMask g_ShaderControls.w + +sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha +sampler SpecularWarpSampler : register( s1 ); // Specular warp sampler (for iridescence etc) +sampler DiffuseWarpSampler : register( s2 ); // Lighting warp sampler (1D texture for diffuse lighting modification) +sampler NormalMapSampler : register( s3 ); // Normal map, specular mask in alpha +sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler +sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers +sampler FlashlightSampler : register( s6 ); // Flashlight cookie +sampler SpecExponentSampler : register( s7 ); // Specular exponent map +sampler EnvmapSampler : register( s8 ); // Cubic environment map + +#if WRINKLEMAP +sampler WrinkleSampler : register( s9 ); // Compression base +sampler StretchSampler : register( s10 ); // Expansion base +sampler NormalWrinkleSampler : register( s11 ); // Compression base +sampler NormalStretchSampler : register( s12 ); // Expansion base +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s13 ); // detail texture +#endif + +sampler SelfIllumMaskSampler : register( s14 ); // selfillummask + + +struct PS_INPUT +{ + float4 baseTexCoordDetailTexCoord : TEXCOORD0; // xy=base zw=detail + float3 lightAtten : TEXCOORD1; // Scalar light attenuation factors for FOUR lights + float3 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3x3 tangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float4 worldPos_atten3 : TEXCOORD6; + float4 projPos_fWrinkleWeight : TEXCOORD7; +}; + + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bWrinkleMap = WRINKLEMAP ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + bool bDoSpecularWarp = PHONGWARPTEXTURE ? true : false; + bool bDoAmbientOcclusion = false; + bool bFlashlight = (FLASHLIGHT!=0) ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bDoRimLighting = RIMLIGHT ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + int nNumLights = NUM_LIGHTS; + + // Unpacking for convenience + float fWrinkleWeight = i.projPos_fWrinkleWeight.w; + float3 vProjPos = i.projPos_fWrinkleWeight.xyz; + float3 vWorldPos = i.worldPos_atten3.xyz; + float atten3 = i.worldPos_atten3.w; + + float4 vLightAtten = float4( i.lightAtten, atten3 ); + +#if WRINKLEMAP + float flWrinkleAmount = saturate( -fWrinkleWeight ); // One of these two is zero + float flStretchAmount = saturate( fWrinkleWeight ); // while the other is in the 0..1 range + + float flTextureAmount = 1.0f - flWrinkleAmount - flStretchAmount; // These should sum to one +#endif + + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoordDetailTexCoord.xy ); +#if WRINKLEMAP + float4 wrinkleColor = tex2D( WrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); + float4 stretchColor = tex2D( StretchSampler, i.baseTexCoordDetailTexCoord.xy ); + + // Apply wrinkle blend to only RGB. Alpha comes from the base texture + baseColor.rgb = flTextureAmount * baseColor + flWrinkleAmount * wrinkleColor + flStretchAmount * stretchColor; +#endif + +#if DETAILTEXTURE + float4 detailColor = tex2D( DetailSampler, i.baseTexCoordDetailTexCoord.zw ); + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactor.w ); +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, vWorldPos.z, vProjPos.z ); + + float3 vEyeDir = normalize(i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz); + float3 vRimAmbientCubeColor = PixelShaderAmbientLight(vEyeDir, cAmbientCube); + + float3 worldSpaceNormal, tangentSpaceNormal; + float fSpecMask = 1.0f; + float4 normalTexel = tex2D( NormalMapSampler, i.baseTexCoordDetailTexCoord.xy ); + +#if WRINKLEMAP + float4 wrinkleNormal = tex2D( NormalWrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); + float4 stretchNormal = tex2D( NormalStretchSampler, i.baseTexCoordDetailTexCoord.xy ); + normalTexel = flTextureAmount * normalTexel + flWrinkleAmount * wrinkleNormal + flStretchAmount * stretchNormal; +#endif + +#if (FASTPATH_NOBUMP == 0 ) + tangentSpaceNormal = lerp( 2.0f * normalTexel.xyz - 1.0f, float3(0, 0, 1), g_fBaseMapAlphaPhongMask ); + fSpecMask = lerp( normalTexel.a, baseColor.a, g_fBaseMapAlphaPhongMask ); +#else + tangentSpaceNormal = float3(0, 0, 1); + fSpecMask = baseColor.a; +#endif + + // We need a normal if we're doing any lighting + worldSpaceNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + + float fFresnelRanges = Fresnel( worldSpaceNormal, vEyeDir, g_FresnelRanges ); + float fRimFresnel = Fresnel4( worldSpaceNormal, vEyeDir ); + + // Break down reflect so that we can share dot(worldSpaceNormal,vEyeDir) with fresnel terms + float3 vReflect = 2 * worldSpaceNormal * dot(worldSpaceNormal, vEyeDir) - vEyeDir; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + float3 envMapColor = float3( 0.0f, 0.0f, 0.0f ); + if( !bFlashlight ) + { + // Summation of diffuse illumination from all local lights + diffuseLighting = PixelShaderDoLighting( vWorldPos, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, true, vLightAtten, + cAmbientCube, NormalizeRandRotSampler, nNumLights, cLightInfo, true, + + // These parameters aren't passed by generic shaders: + false, 1.0f, + bDoDiffuseWarp, DiffuseWarpSampler ); + + if( bCubemap ) + { + // Mask is either normal map alpha or base map alpha +#if ( SELFILLUMFRESNEL == 1 ) // This is to match the 2.0 version of vertexlitgeneric + float fEnvMapMask = lerp( baseColor.a, g_fInvertPhongMask, g_EnvmapTint_ShadowTweaks.w ); +#else + float fEnvMapMask = lerp( baseColor.a, fSpecMask, g_EnvmapTint_ShadowTweaks.w ); +#endif + + envMapColor = (ENV_MAP_SCALE * + lerp(1, fFresnelRanges, g_EnvMapFresnel.x) * + lerp(fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask)) * + texCUBE( EnvmapSampler, vReflect ) * + g_EnvmapTint_ShadowTweaks.xyz; + } + } + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 rimLighting = float3( 0.0f, 0.0f, 0.0f ); + + float3 vSpecularTint = 1; + float fRimMask = 0; + float fSpecExp = 1; + +#if ( FASTPATH_NOBUMP == 0 ) + float4 vSpecExpMap = tex2D( SpecExponentSampler, i.baseTexCoordDetailTexCoord.xy ); + + if ( !bFlashlight ) + { + fRimMask = lerp( 1.0f, vSpecExpMap.a, g_RimMaskControl ); // Select rim mask + } + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent +#if defined( _X360 ) + [flatten] +#endif + + fSpecExp = (g_EyePos_SpecExponent.w >= 0.0) ? g_EyePos_SpecExponent.w : (1.0f + 149.0f * vSpecExpMap.r); + + // If constant tint is negative, tint with albedo, based upon scalar tint map +#if defined( _X360 ) + [flatten] +#endif + vSpecularTint = lerp( float3(1.0f, 1.0f, 1.0f), baseColor.rgb, vSpecExpMap.g ); + vSpecularTint = (g_SpecularTint.r >= 0.0) ? g_SpecularTint.rgb : vSpecularTint; + +#else + fSpecExp = max(g_EyePos_SpecExponent.w, 0); +#endif + + float3 albedo = baseColor.rgb; + + if ( !bFlashlight ) + { + // Summation of specular from all local lights besides the flashlight + PixelShaderDoSpecularLighting( vWorldPos, worldSpaceNormal, + fSpecExp, vEyeDir, vLightAtten, + nNumLights, cLightInfo, false, 1.0f, bDoSpecularWarp, + SpecularWarpSampler, fFresnelRanges, bDoRimLighting, g_RimExponent, + + // Outputs + specularLighting, rimLighting ); + } + else + { + float4 flashlightSpacePosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); + + DoSpecularFlashlight( g_FlashlightPos, vWorldPos, flashlightSpacePosition, worldSpaceNormal, + g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, + FlashlightSampler, ShadowDepthSampler, NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, vProjPos.xy / vProjPos.z, + fSpecExp, vEyeDir, bDoSpecularWarp, SpecularWarpSampler, fFresnelRanges, g_EnvmapTint_ShadowTweaks, + + // These two values are output + diffuseLighting, specularLighting ); + } + + // If we didn't already apply Fresnel to specular warp, modulate the specular + if ( !bDoSpecularWarp ) + fSpecMask *= fFresnelRanges; + + // Modulate with spec mask, boost and tint + specularLighting *= fSpecMask * g_SpecularBoost; + + if (bBlendTintByBaseAlpha) + { + float3 tintedColor = albedo * g_DiffuseModulation.rgb; + tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_fTintReplacementControl); + albedo = lerp(albedo, tintedColor, baseColor.a); + } + else + { + albedo = albedo * g_DiffuseModulation.rgb; + } + + + float3 diffuseComponent = albedo * diffuseLighting; + if ( bSelfIllum && !bFlashlight ) + { +#if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file + // This will apply a Fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look + float3 vVertexNormal = normalize( float3( i.tangentSpaceTranspose[0].z, i.tangentSpaceTranspose[1].z, i.tangentSpaceTranspose[2].z ) ); + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, vEyeDir.xyz ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo * g_SelfIllumScaleBiasExpBrightness.w, baseColor.a * saturate( flSelfIllumFresnel ) ); +#else + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoordDetailTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo, vSelfIllumMask ); +#endif + + diffuseComponent = max( 0.0f, diffuseComponent ); + } + +#if DETAILTEXTURE + diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, + DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactor.w ); +#endif + + if ( bDoRimLighting && !bFlashlight ) + { + float fRimMultiply = fRimMask * fRimFresnel; // both unit range: [0, 1] + + // Add in rim light modulated with tint, mask and traditional Fresnel (not using Fresnel ranges) + rimLighting *= fRimMultiply; + + // Fold rim lighting into specular term by using the max so that we don't really add light twice... + specularLighting = max( specularLighting, rimLighting ); + + // Add in view-ray lookup from ambient cube + specularLighting += (vRimAmbientCubeColor * g_fRimBoost) * saturate(fRimMultiply * worldSpaceNormal.z); + } + + float3 result = specularLighting*vSpecularTint + envMapColor + diffuseComponent; + +#if WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + float alpha = fogFactor; +#else + float alpha = g_DiffuseModulation.a; + if ( !bSelfIllum && !bBlendTintByBaseAlpha ) + { + alpha = lerp( baseColor.a * alpha, alpha, g_fBaseMapAlphaPhongMask ); + } +#endif + + bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); + + //FIXME: need to take dowaterfog into consideration + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, vProjPos.z ); +} diff --git a/mp/src/materialsystem/stdshaders/skin_vs20.fxc b/mp/src/materialsystem/stdshaders/skin_vs20.fxc new file mode 100644 index 00000000..9b04b7aa --- /dev/null +++ b/mp/src/materialsystem/stdshaders/skin_vs20.fxc @@ -0,0 +1,173 @@ +//======= Copyright (c) 1996-2007, Valve Corporation, All rights reserved. ====== + +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float4 vPosFlex : POSITION1; + float4 vNormalFlex : NORMAL1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + // Stuff that is seen by the pixel shader + float4 baseTexCoord : TEXCOORD0; // includes detail tex coord + float3 lightAtten : TEXCOORD1; + float3 worldVertToEyeVector : TEXCOORD2; + float3x3 tangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float4 worldPos_atten3 : TEXCOORD6; + float4 projPos_fWrinkleWeight : TEXCOORD7; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, + vPosition.xyz, vNormal, vTangent.xyz, o.projPos_fWrinkleWeight.w ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, v.vTexCoord2, + vPosition.xyz, vNormal, vTangent.xyz, o.projPos_fWrinkleWeight.w ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.projPos_fWrinkleWeight.xyz = vProjPos.xyz; + +#if !defined( _X360 ) + o.fog = CalcFog( worldPos, vProjPos.xyz, g_FogType ); +#endif + // Needed for water fog alpha and diffuse lighting + // FIXME: we shouldn't have to compute this all the time. + o.worldPos_atten3.xyz = worldPos; + + // Needed for specular + o.worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + + // Compute bumped lighting + // FIXME: We shouldn't have to compute this for unlit materials +#if defined ( SHADER_MODEL_VS_2_0 ) && ( !USE_STATIC_CONTROL_FLOW ) + o.lightAtten.xyz = float3(0,0,0); + o.worldPos_atten3.w = 0.0f; + #if ( NUM_LIGHTS > 0 ) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.worldPos_atten3.w = GetVertexAttenForLight( worldPos, 3, false ); + #endif +#else + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, true ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, true ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, true ); + o.worldPos_atten3.w = GetVertexAttenForLight( worldPos, 3, true ); +#endif + + // Base texture coordinate transform + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + o.baseTexCoord.z = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.baseTexCoord.w = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/sky_dx6.cpp b/mp/src/materialsystem/stdshaders/sky_dx6.cpp new file mode 100644 index 00000000..15bdc553 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_dx6.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Teeth renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Sky, UnlitGeneric ) +DEFINE_FALLBACK_SHADER( Sky_dx6, UnlitGeneric ) + diff --git a/mp/src/materialsystem/stdshaders/sky_dx9.cpp b/mp/src/materialsystem/stdshaders/sky_dx9.cpp new file mode 100644 index 00000000..93eb6115 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_dx9.cpp @@ -0,0 +1,126 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// +#include "BaseVSShader.h" +#include "sky_vs20.inc" +#include "sky_ps20.inc" +#include "sky_ps20b.inc" + +#include "convar.h" + +BEGIN_VS_SHADER( Sky_DX9, "Help for Sky_DX9 shader" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_VEC3, "[ 1 1 1]", "color multiplier", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "sky_dx6"; + } + return 0; + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NOFOG ); + SET_FLAGS( MATERIAL_VAR_IGNOREZ ); + } + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + ImageFormat fmt = params[BASETEXTURE]->GetTextureValue()->GetImageFormat(); + LoadTexture( BASETEXTURE, (fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616) ? 0 : TEXTUREFLAGS_SRGB ); + } + } + SHADER_DRAW + { + SHADOW_STATE + { + SetInitialShadowState(); + +// pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + ITexture *txtr=params[BASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ((fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616)) + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + else + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,true); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, NULL, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sky_vs20 ); + SET_STATIC_VERTEX_SHADER( sky_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_ps20 ); + } + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + float c1[4]={0,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + float c0[4]={1,1,1,1}; + if (params[COLOR]->IsDefined()) + { + memcpy(c0,params[COLOR]->GetVecValue(),3*sizeof(float)); + } + ITexture *txtr=params[BASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( + (fmt==IMAGE_FORMAT_RGBA16161616) || + ( (fmt==IMAGE_FORMAT_RGBA16161616F) && + (g_pHardwareConfig->GetHDRType()==HDR_TYPE_INTEGER)) + ) + { + c0[0]*=16.0; + c0[1]*=16.0; + c0[2]*=16.0; + } + pShaderAPI->SetPixelShaderConstant(0,c0,1); + DECLARE_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + + // Texture coord transform + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BASETEXTURETRANSFORM ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + } + } + Draw( ); + } + +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc b/mp/src/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc new file mode 100644 index 00000000..8e54d21f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc @@ -0,0 +1,29 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler ExposureTextureSampler0 : register( s0 ); +sampler ExposureTextureSampler1 : register( s1 ); +sampler ExposureTextureSampler2 : register( s2 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF3 color0 = 0.25*tex2D( ExposureTextureSampler0, i.baseTexCoord ); + HALF3 color1 = 2.0*tex2D( ExposureTextureSampler1, i.baseTexCoord ); + HALF3 color2 = 16.0*tex2D( ExposureTextureSampler2, i.baseTexCoord ); + + // This is never fogged. +// return FinalOutput( float4( max(max(color0,color1),color2), 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate + return FinalOutput( float4(1,0,0,1 ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/mp/src/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc b/mp/src/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc new file mode 100644 index 00000000..4871da56 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc @@ -0,0 +1,81 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler RGBSTextureSampler : register( s0 ); +HALF4 InputScale : register( c0 ); + +float2 texWidthHeight : register( c1 ); + +float4 texOffsets : register( c2 ); + +struct PS_INPUT +{ +//#if defined( _X360 ) +// float2 baseTexCoord : TEXCOORD0; +//#else + float2 baseTexCoord00 : TEXCOORD0; + float2 baseTexCoord01 : TEXCOORD1; + float2 baseTexCoord10 : TEXCOORD2; + float2 baseTexCoord11 : TEXCOORD3; + float2 baseTexCoord_In_Pixels: TEXCOORD4; +//#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 result; + +//#if defined( _X360 ) //360 has a cheaper way to handle RGBscale +// float4 Weights; +// float4 samples_0; //no arrays allowed in inline assembly +// float4 samples_1; +// float4 samples_2; +// float4 samples_3; +// float2 vTexCoord = i.baseTexCoord; +// +// asm { +// tfetch2D samples_0, vTexCoord.xy, RGBSTextureSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_1, vTexCoord.xy, RGBSTextureSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_2, vTexCoord.xy, RGBSTextureSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_3, vTexCoord.xy, RGBSTextureSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// +// getWeights2D Weights, vTexCoord.xy, RGBSTextureSampler +// }; +// +// Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); +// +// result.rgb = samples_0.rgb * (samples_0.a * Weights.x); +// result.rgb += samples_1.rgb * (samples_1.a * Weights.y); +// result.rgb += samples_2.rgb * (samples_2.a * Weights.z); +// result.rgb += samples_3.rgb * (samples_3.a * Weights.w); +// +//#else + float4 s00 = tex2D(RGBSTextureSampler, i.baseTexCoord00); + float4 s10 = tex2D(RGBSTextureSampler, i.baseTexCoord10); + float4 s01 = tex2D(RGBSTextureSampler, i.baseTexCoord01); + float4 s11 = tex2D(RGBSTextureSampler, i.baseTexCoord11); + + float2 fracCoord = frac(i.baseTexCoord_In_Pixels); + + s00.rgb*=s00.a; + s10.rgb*=s10.a; + + s00.xyz = lerp(s00, s10, fracCoord.x); + + s01.rgb*=s01.a; + s11.rgb*=s11.a; + s01.xyz = lerp(s01, s11, fracCoord.x); + + result = lerp(s00, s01, fracCoord.y); +//#endif + + // This is never fogged. + return FinalOutput( float4( InputScale*result, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/mp/src/materialsystem/stdshaders/sky_hdr_dx9.cpp b/mp/src/materialsystem/stdshaders/sky_hdr_dx9.cpp new file mode 100644 index 00000000..285879c0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_hdr_dx9.cpp @@ -0,0 +1,297 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// +#include "BaseVSShader.h" +#include "sky_vs20.inc" +#include "sky_ps20.inc" +#include "sky_ps20b.inc" +#include "sky_hdr_compressed_ps20.inc" +#include "sky_hdr_compressed_ps20b.inc" +#include "sky_hdr_compressed_rgbs_ps20.inc" +#include "sky_hdr_compressed_rgbs_ps20b.inc" + +#include "convar.h" + +static ConVar mat_use_compressed_hdr_textures( "mat_use_compressed_hdr_textures", "1" ); + +DEFINE_FALLBACK_SHADER( Sky, Sky_HDR_DX9 ) + +BEGIN_VS_SHADER( Sky_HDR_DX9, "Help for Sky_HDR_DX9 shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( HDRBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "base texture when running with HDR enabled" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "base texture (compressed) for hdr compression method A" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE0, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture0 for hdr compression method B" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE1, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture1 for hdr compression method B" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture2 for hdr compression method B" ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_VEC3, "[ 1 1 1]", "color multiplier", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 || g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "Sky_DX9"; + } + return 0; + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NOFOG ); + SET_FLAGS( MATERIAL_VAR_IGNOREZ ); + } + SHADER_INIT + { + // First figure out if sampler zero wants to be sRGB + int nSamplerZeroFlags = 0; + if ( (params[HDRCOMPRESSEDTEXTURE]->IsDefined()) && mat_use_compressed_hdr_textures.GetBool() ) + { + nSamplerZeroFlags = 0; + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + nSamplerZeroFlags = 0; + } + else + { + nSamplerZeroFlags = TEXTUREFLAGS_SRGB; + + if ( params[HDRBASETEXTURE]->IsDefined() && params[HDRBASETEXTURE]->IsTexture() ) + { + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( ( fmt == IMAGE_FORMAT_RGBA16161616F ) || ( fmt == IMAGE_FORMAT_RGBA16161616 ) ) + { + nSamplerZeroFlags = 0; + } + } + } + } + + // Next, figure out which texture will be on sampler zero + int nSampler0 = HDRCOMPRESSEDTEXTURE; + if ( params[HDRCOMPRESSEDTEXTURE]->IsDefined() && mat_use_compressed_hdr_textures.GetBool() ) + { + nSampler0 = HDRCOMPRESSEDTEXTURE; + } + else + { + if ( params[HDRCOMPRESSEDTEXTURE0]->IsDefined() ) + { + nSampler0 = HDRCOMPRESSEDTEXTURE0; + } + else + { + nSampler0 = HDRBASETEXTURE; + } + } + + // Load the appropriate textures, making sure that the texture set on sampler 0 is sRGB if necessary + if ( params[HDRCOMPRESSEDTEXTURE]->IsDefined() && (mat_use_compressed_hdr_textures.GetBool() ) ) + { + LoadTexture( HDRCOMPRESSEDTEXTURE, HDRCOMPRESSEDTEXTURE == nSampler0 ? nSamplerZeroFlags : 0 ); + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE0, HDRCOMPRESSEDTEXTURE0 == nSampler0 ? nSamplerZeroFlags : 0 ); + if ( params[HDRCOMPRESSEDTEXTURE1]->IsDefined() ) + { + LoadTexture( HDRCOMPRESSEDTEXTURE1, HDRCOMPRESSEDTEXTURE1 == nSampler0 ? nSamplerZeroFlags : 0 ); + } + if ( params[HDRCOMPRESSEDTEXTURE2]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE2, HDRCOMPRESSEDTEXTURE2 == nSampler0 ? nSamplerZeroFlags : 0 ); + } + } + else + { + if ( params[HDRBASETEXTURE]->IsDefined() ) + { + LoadTexture( HDRBASETEXTURE, HDRBASETEXTURE == nSampler0 ? nSamplerZeroFlags : 0 ); + } + } + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + SetInitialShadowState(); + +// pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, NULL, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sky_vs20 ); + SET_STATIC_VERTEX_SHADER( sky_vs20 ); + + if ( (params[HDRCOMPRESSEDTEXTURE]->IsDefined()) && + mat_use_compressed_hdr_textures.GetBool() ) + { + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + } + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER1,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER2,false); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + } + } + else + { + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ((fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616)) + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + else + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,true); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_ps20 ); + } + } + } + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + + // Texture coord transform + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BASETEXTURETRANSFORM ); + + float c0[4]={1,1,1,1}; + if (params[COLOR]->IsDefined()) + { + memcpy(c0,params[COLOR]->GetVecValue(),3*sizeof(float)); + } + if ( + params[HDRCOMPRESSEDTEXTURE]->IsDefined() && + mat_use_compressed_hdr_textures.GetBool() + ) + { + // set up data needs for pixel shader interpolation + ITexture *txtr=params[HDRCOMPRESSEDTEXTURE]->GetTextureValue(); + float w=txtr->GetActualWidth(); + float h=txtr->GetActualHeight(); + float FUDGE=0.01/max(w,h); // per ATI + float c1[4]={0.5/w-FUDGE, 0.5/h-FUDGE, w, h }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + BindTexture( SHADER_SAMPLER0, HDRCOMPRESSEDTEXTURE, FRAME ); + c0[0]*=8.0; + c0[1]*=8.0; + c0[2]*=8.0; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + } + } + else + { + float c1[4]={0,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined() ) + { + BindTexture( SHADER_SAMPLER0, HDRCOMPRESSEDTEXTURE0, FRAME ); + BindTexture( SHADER_SAMPLER1, HDRCOMPRESSEDTEXTURE1, FRAME ); + BindTexture( SHADER_SAMPLER2, HDRCOMPRESSEDTEXTURE2, FRAME ); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + } + + } + else + { + BindTexture( SHADER_SAMPLER0, HDRBASETEXTURE, FRAME ); + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( + (fmt==IMAGE_FORMAT_RGBA16161616) || + ( (fmt==IMAGE_FORMAT_RGBA16161616F) && + (g_pHardwareConfig->GetHDRType()==HDR_TYPE_INTEGER)) + ) + { + c0[0]*=16.0; + c0[1]*=16.0; + c0[2]*=16.0; + } + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + } + } + } + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + } + Draw( ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/sky_ps2x.fxc b/mp/src/materialsystem/stdshaders/sky_ps2x.fxc new file mode 100644 index 00000000..563fddbb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_ps2x.fxc @@ -0,0 +1,27 @@ +// HDRFIXME: Make this work with nonHDR +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler BaseTextureSampler : register( s0 ); +HALF4 InputScale : register( c0 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF4 color = tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + color.rgb *= InputScale.rgb; + + // This is never fogged. + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/mp/src/materialsystem/stdshaders/sky_vs20.fxc b/mp/src/materialsystem/stdshaders/sky_vs20.fxc new file mode 100644 index 00000000..1bc2a3e6 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sky_vs20.fxc @@ -0,0 +1,64 @@ +#include "common_vs_fxc.h" + +const float4 g_vTextureSizeInfo : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_mBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + //SHADER_SPECIFIC_CONST_2 + +#define TEXEL_XINCR (g_vTextureSizeInfo.x) +#define TEXEL_YINCR (g_vTextureSizeInfo.y) +#define U_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.z) +#define V_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.w) + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + +//#if defined( _X360 ) +// float2 baseTexCoord : TEXCOORD0; +//#else + float2 baseTexCoord00 : TEXCOORD0; + float2 baseTexCoord01 : TEXCOORD1; + float2 baseTexCoord10 : TEXCOORD2; + float2 baseTexCoord11 : TEXCOORD3; + float2 baseTexCoord_In_Pixels: TEXCOORD4; +//#endif +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = mul( v.vPos, cModelViewProj ); + + float4 vTexCoordInput = { v.vTexCoord0.x, v.vTexCoord0.y, 0.0f, 1.0f }; + float2 vTexCoord; + vTexCoord.x = dot( vTexCoordInput.xyzw, g_mBaseTexCoordTransform[0] ); + vTexCoord.y = dot( vTexCoordInput.xyzw, g_mBaseTexCoordTransform[1] ); + +//#if defined( _X360 ) +// o.baseTexCoord.xy = vTexCoord.xy; +//#else + // Compute quantities needed for pixel shader texture lerping + o.baseTexCoord00.x = vTexCoord.x - TEXEL_XINCR; + o.baseTexCoord00.y = vTexCoord.y - TEXEL_YINCR; + o.baseTexCoord10.x = vTexCoord.x + TEXEL_XINCR; + o.baseTexCoord10.y = vTexCoord.y - TEXEL_YINCR; + + o.baseTexCoord01.x = vTexCoord.x - TEXEL_XINCR; + o.baseTexCoord01.y = vTexCoord.y + TEXEL_YINCR; + o.baseTexCoord11.x = vTexCoord.x + TEXEL_XINCR; + o.baseTexCoord11.y = vTexCoord.y + TEXEL_YINCR; + + o.baseTexCoord_In_Pixels.xy = o.baseTexCoord00.xy; + o.baseTexCoord_In_Pixels.x *= U_TO_PIXEL_COORD_SCALE; + o.baseTexCoord_In_Pixels.y *= V_TO_PIXEL_COORD_SCALE; +//#endif + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/sprite.cpp b/mp/src/materialsystem/stdshaders/sprite.cpp new file mode 100644 index 00000000..77934f57 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite.cpp @@ -0,0 +1,379 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +// Implementation of the sprite shader +//=============================================================================// + +#include "BaseVSShader.h" +#include +#include "const.h" +#include "sprite_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX8 ) + +BEGIN_VS_SHADER( Sprite_DX8, + "Help for Sprite_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "Sprite_DX6"; + return 0; + } + + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + // FIXME: Not sure if this is the best solution, but it's a very] + // easy one. When graphics aren't enabled, we oftentimes need to get + // at the parameters of a shader. Therefore, we must set the default + // values in a separate phase from when we load resources. + + if (!params[ALPHA]->IsDefined()) + params[ ALPHA ]->SetFloatValue( 1.0f ); + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + +#define SHADER_USE_VERTEX_COLOR 1 +#define SHADER_USE_CONSTANT_COLOR 2 + + void SetSpriteCommonShadowState( unsigned int shaderFlags ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + unsigned int flags = VERTEX_POSITION; + if( shaderFlags & SHADER_USE_VERTEX_COLOR ) + { + flags |= VERTEX_COLOR; + } + s_pShaderShadow->VertexShaderVertexFormat( flags, 1, 0, 0 ); + + sprite_vs11_Static_Index vshIndex; + bool vertexColor = ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false; + vshIndex.SetVERTEXCOLOR( vertexColor ); + s_pShaderShadow->SetVertexShader( "sprite_vs11", vshIndex.GetIndex() ); + + // "VERTEXCOLOR" "0..1" + // "CONSTANTCOLOR" "0..1" + int pshIndex = 0; + if ( shaderFlags & SHADER_USE_VERTEX_COLOR ) pshIndex |= 0x1; + if ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) pshIndex |= 0x2; + s_pShaderShadow->SetPixelShader( "sprite_ps11", pshIndex ); + } + + void SetSpriteCommonDynamicState( unsigned int shaderFlags ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + sprite_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( 0 ); + vshIndex.SetDOWATERFOG( fogIndex ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + s_pShaderAPI->SetPixelShaderIndex( 0 ); + if ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) + { + SetPixelShaderConstant( 0, COLOR, ALPHA ); + } + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + // identity base texture transorm + float ident[2][4] = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f } + }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &ident[0][0], 2 ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + FogToFogColor(); + SetSpriteCommonShadowState( 0 ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( 0 ); + } + Draw(); + break; + case kRenderTransColor: + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlpha: + // untested cut and past from kRenderTransAlphaAdd . . same as first pass of that. + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + + SHADOW_STATE + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + + case kRenderTransAdd: + { + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( flags ); + } + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + sprite_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( 0 ); + vshIndex.SetDOWATERFOG( fogIndex ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + + + // identity base texture transorm + float ident[2][4] = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f } + }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &ident[0][0], 2 ); + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + sprite_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( 0 ); + vshIndex.SetDOWATERFOG( fogIndex ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + + // identity base texture transorm + float ident[2][4] = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f } + }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &ident[0][0], 2 ); + } + Draw(); + } + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/sprite_dx6.cpp b/mp/src/materialsystem/stdshaders/sprite_dx6.cpp new file mode 100644 index 00000000..15ba22a6 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite_dx6.cpp @@ -0,0 +1,289 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +// Implementation of the sprite shader +//=============================================================================// + +#include "shaderlib/cshader.h" +#include +#include "const.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX6 ) + +BEGIN_SHADER( Sprite_DX6, + "Help for Sprite_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + // FIXME: Not sure if this is the best solution, but it's a very] + // easy one. When graphics aren't enabled, we oftentimes need to get + // at the parameters of a shader. Therefore, we must set the default + // values in a separate phase from when we load resources. + + if (!params[ALPHA]->IsDefined()) + params[ ALPHA ]->SetFloatValue( 1.0f ); + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransColor: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransAlpha: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + + case kRenderTransAdd: + SHADOW_STATE + { + if( params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + } + else + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + } + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + FogToBlack(); + } + DYNAMIC_STATE + { + SetColorState( COLOR, ALPHA ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + SHADOW_STATE + { + if( params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + } + else + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + } + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + FogToBlack(); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + pShaderAPI->Color3f( flFade * frameBlendAlpha, flFade * frameBlendAlpha, flFade * frameBlendAlpha ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + pShaderAPI->Color3f( flFade * frameBlendAlpha, flFade * frameBlendAlpha, flFade * frameBlendAlpha ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + } + Draw(); + } + + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/sprite_dx9.cpp b/mp/src/materialsystem/stdshaders/sprite_dx9.cpp new file mode 100644 index 00000000..0a0bb9f4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite_dx9.cpp @@ -0,0 +1,490 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "BaseVSShader.h" +#include +#include "const.h" + +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#include "sprite_vs20.inc" +#include "sprite_ps20.inc" +#include "sprite_ps20b.inc" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX9 ) + +BEGIN_VS_SHADER( Sprite_DX9, + "Help for Sprite_DX9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + SHADER_PARAM( NOSRGB, SHADER_PARAM_TYPE_BOOL, "0", "do not operate in srgb space" ) + SHADER_PARAM( HDRCOLORSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "hdr color scale" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 90) + return "Sprite_DX8"; + return 0; + } + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + if (!params[ALPHA]->IsDefined()) + { + params[ALPHA]->SetFloatValue( 1.0f ); + } + + if (!params[HDRCOLORSCALE]->IsDefined()) + { + params[HDRCOLORSCALE]->SetFloatValue( 1.0f ); + } + + if ( !params[NOSRGB]->IsDefined() ) + { + // Disable sRGB reads and writes by default + params[NOSRGB]->SetIntValue( 1 ); + } + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + LoadTexture( BASETEXTURE, bSRGB ? TEXTUREFLAGS_SRGB : 0 ); + } + +#define SHADER_USE_VERTEX_COLOR 1 +#define SHADER_USE_CONSTANT_COLOR 2 + + void SetSpriteCommonShadowState( unsigned int shaderFlags ) + { + IShaderShadow *pShaderShadow = s_pShaderShadow; + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bSRGB ); + + // Only enabling this on OSX() - it causes GL mode's light glow sprites to be much darker vs. D3D9 under Linux/Win GL. + bool bSRGBOutputAdapter = ( IsOSX() && !g_pHardwareConfig->FakeSRGBWrite() ) && !bSRGB; + + unsigned int flags = VERTEX_POSITION; + if( shaderFlags & SHADER_USE_VERTEX_COLOR ) + { + flags |= VERTEX_COLOR; + } + int numTexCoords = 1; + s_pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sprite_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_VERTEX_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_STATIC_PIXEL_SHADER( sprite_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTCOLOR, ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB_OUTPUT_ADAPTER, bSRGBOutputAdapter ); + SET_STATIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sprite_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTCOLOR, ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_PIXEL_SHADER( sprite_ps20 ); + } + + // OSX always has to sRGB write (don't do this on Linux/Win GL - it causes glow sprites to be way too dark) + s_pShaderShadow->EnableSRGBWrite( bSRGB || ( IsOSX() && !g_pHardwareConfig->FakeSRGBWrite() ) ); + } + + void SetSpriteCommonDynamicState( unsigned int shaderFlags ) + { + IShaderDynamicAPI *pShaderAPI = s_pShaderAPI; + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if( shaderFlags & SHADER_USE_CONSTANT_COLOR ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 0, COLOR, ALPHA ); + else + SetPixelShaderConstant( 0, COLOR, ALPHA ); + } + + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + + SHADER_DRAW + { + bool bSRGB = params[NOSRGB]->GetIntValue() == 0; + + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + FogToFogColor(); + + SetSpriteCommonShadowState( 0 ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( 0 ); + } + Draw(); + break; + case kRenderTransColor: + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlpha: + // untested cut and past from kRenderTransAlphaAdd . . same as first pass of that. + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + + SHADOW_STATE + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + + case kRenderTransAdd: + { + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( flags ); + } + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + float color[4]; + if ( bSRGB ) + color[0] = color[1] = color[2] = GammaToLinear( flFade * frameBlendAlpha ); + else + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + float color[4]; + if ( bSRGB ) + color[0] = color[1] = color[2] = GammaToLinear( flFade * frameBlendAlpha ); + else + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + Draw(); + } + + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/sprite_ps11.psh b/mp/src/materialsystem/stdshaders/sprite_ps11.psh new file mode 100644 index 00000000..5f5def5b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite_ps11.psh @@ -0,0 +1,15 @@ +; STATIC: "VERTEXCOLOR" "0..1" +; STATIC: "CONSTANTCOLOR" "0..1" + +ps.1.1 + +tex t0 +mov r0, t0 + +#if VERTEXCOLOR +mul r0, r0, v0 +#endif + +#if CONSTANTCOLOR +mul r0, r0, c0 +#endif \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/sprite_ps2x.fxc b/mp/src/materialsystem/stdshaders/sprite_ps2x.fxc new file mode 100644 index 00000000..83a7ab08 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite_ps2x.fxc @@ -0,0 +1,61 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "CONSTANTCOLOR" "0..1" +// STATIC: "HDRTYPE" "0..2" +// STATIC: "SRGB" "0..1" +// STATIC: "SRGB_OUTPUT_ADAPTER" "0..1" [ps20b] + +// DYNAMIC: "HDRENABLED" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +const HALF4 g_Color : register( c0 ); +const float g_HDRColorScale : register( c1 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result, sample = tex2D( TexSampler, i.baseTexCoord ); + +#if VERTEXCOLOR + sample *= i.color; +#endif + +#if CONSTANTCOLOR + sample *= g_Color; +#endif + +#if HDRTYPE && HDRENABLED + sample.xyz *= g_HDRColorScale; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); +#if SRGB + result = FinalOutput( sample, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +#else + result = FinalOutput( sample, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_GAMMA ); +#endif + + // On Posix, we're being forced through a linear-to-gamma curve but don't want it, so we do the opposite here first +#if SRGB_OUTPUT_ADAPTER + result = GammaToLinear( result ); +#endif + + return result; +} + diff --git a/mp/src/materialsystem/stdshaders/sprite_vs11.vsh b/mp/src/materialsystem/stdshaders/sprite_vs11.vsh new file mode 100644 index 00000000..5ffa45f1 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite_vs11.vsh @@ -0,0 +1,9 @@ +vs.1.1 + +# STATIC: "VERTEXCOLOR" "0..1" +# DYNAMIC: "SKINNING" "0..0" +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "UnlitGeneric_inc.vsh" + +&UnlitGeneric( 0, 0, 0, 0, $VERTEXCOLOR ); diff --git a/mp/src/materialsystem/stdshaders/sprite_vs20.fxc b/mp/src/materialsystem/stdshaders/sprite_vs20.fxc new file mode 100644 index 00000000..5e427c19 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/sprite_vs20.fxc @@ -0,0 +1,65 @@ +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "SRGB" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; +#endif + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + projPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, projPos.z ); + +#if !defined( _X360 ) + o.fog = CalcFog( worldPos, projPos, g_FogType ); +#endif + if ( g_bVertexColor ) + { + // Assume that this is unlitgeneric if you are using vertex color. +#if SRGB + o.color.rgba = GammaToLinear( v.vColor.rgba ); +#else + o.color.rgba = v.vColor.rgba; +#endif + } + + // Base texture coordinates + o.baseTexCoord.xy = v.vTexCoord0.xy; + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/spritecard.cpp b/mp/src/materialsystem/stdshaders/spritecard.cpp new file mode 100644 index 00000000..850c357a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/spritecard.cpp @@ -0,0 +1,484 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: shader for drawing sprites as cards, with animation frame lerping +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +// STDSHADER_DX9_DLL_EXPORT +#include "spritecard_ps20.inc" +#include "spritecard_ps20b.inc" +#include "spritecard_vs20.inc" +#include "splinecard_vs20.inc" + +#if SUPPORT_DX8 +// STDSHADER_DX8_DLL_EXPORT +#include "spritecard_vs11.inc" +#include "spritecard_ps11.inc" +#include "splinecard_vs11.inc" +#endif + +#include "tier0/icommandline.h" //command line + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define DEFAULT_PARTICLE_FEATHERING_ENABLED 1 + +#ifdef STDSHADER_DX8_DLL_EXPORT +DEFINE_FALLBACK_SHADER( Spritecard, Spritecard_DX8 ) +#endif + +int GetDefaultDepthFeatheringValue( void ) //Allow the command-line to go against the default soft-particle value +{ + static int iRetVal = -1; + + if( iRetVal == -1 ) + { +# if( DEFAULT_PARTICLE_FEATHERING_ENABLED == 1 ) + { + if( CommandLine()->CheckParm( "-softparticlesdefaultoff" ) ) + iRetVal = 0; + else + iRetVal = 1; + } +# else + { + if( CommandLine()->CheckParm( "-softparticlesdefaulton" ) ) + iRetVal = 1; + else + iRetVal = 0; + } +# endif + } + + // On low end parts on the Mac, we reduce particles and shut off depth blending here + static ConVarRef mat_reduceparticles( "mat_reduceparticles" ); + if ( mat_reduceparticles.GetBool() ) + { + iRetVal = 0; + } + + return iRetVal; +} + + +#ifdef STDSHADER_DX9_DLL_EXPORT +BEGIN_VS_SHADER_FLAGS( Spritecard, "Help for Spritecard", SHADER_NOT_EDITABLE ) +#else +BEGIN_VS_SHADER_FLAGS( Spritecard_DX8, "Help for Spritecard_DX8", SHADER_NOT_EDITABLE ) +#endif + +BEGIN_SHADER_PARAMS +SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries" ) +SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) +SHADER_PARAM( ORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "0 = always face camera, 1 = rotate around z, 2= parallel to ground" ) +SHADER_PARAM( ADDBASETEXTURE2, SHADER_PARAM_TYPE_FLOAT, "0.0", "amount to blend second texture into frame by" ) +SHADER_PARAM( OVERBRIGHTFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "overbright factor for texture. For HDR effects.") +SHADER_PARAM( DUALSEQUENCE, SHADER_PARAM_TYPE_INTEGER, "0", "blend two separate animated sequences.") +SHADER_PARAM( SEQUENCE_BLEND_MODE, SHADER_PARAM_TYPE_INTEGER, "0", "defines the blend mode between the images un dual sequence particles. 0 = avg, 1=alpha from first, rgb from 2nd, 2= first over second" ) +SHADER_PARAM( MAXLUMFRAMEBLEND1, SHADER_PARAM_TYPE_INTEGER, "0", "instead of blending between animation frames for the first sequence, select pixels based upon max luminance" ) +SHADER_PARAM( MAXLUMFRAMEBLEND2, SHADER_PARAM_TYPE_INTEGER, "0", "instead of blending between animation frames for the 2nd sequence, select pixels based upon max luminance" ) +SHADER_PARAM( RAMPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "if specified, then the red value of the image is used to index this ramp to produce the output color" ) +SHADER_PARAM( ZOOMANIMATESEQ2, SHADER_PARAM_TYPE_FLOAT, "1.0", "amount to gradually zoom between frames on the second sequence. 2.0 will double the size of a frame over its lifetime.") +SHADER_PARAM( EXTRACTGREENALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "grayscale data sitting in green/alpha channels") +SHADER_PARAM( ADDOVERBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "use ONE:INVSRCALPHA blending") +SHADER_PARAM( ADDSELF, SHADER_PARAM_TYPE_FLOAT, "0.0", "amount of base texture to additively blend in" ) +SHADER_PARAM( BLENDFRAMES, SHADER_PARAM_TYPE_BOOL, "1", "whether or not to smoothly blend between animated frames" ) +SHADER_PARAM( MINSIZE, SHADER_PARAM_TYPE_FLOAT, "0.0", "minimum screen fractional size of particle") +SHADER_PARAM( STARTFADESIZE, SHADER_PARAM_TYPE_FLOAT, "10.0", "screen fractional size to start fading particle out") +SHADER_PARAM( ENDFADESIZE, SHADER_PARAM_TYPE_FLOAT, "20.0", "screen fractional size to finish fading particle out") +SHADER_PARAM( MAXSIZE, SHADER_PARAM_TYPE_FLOAT, "20.0", "maximum screen fractional size of particle") +SHADER_PARAM( USEINSTANCING, SHADER_PARAM_TYPE_BOOL, "1", "whether to use GPU vertex instancing (submit 1 vert per particle quad)") +SHADER_PARAM( SPLINETYPE, SHADER_PARAM_TYPE_INTEGER, "0", "spline type 0 = none, 1=ctamull rom") +SHADER_PARAM( MAXDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100000.0", "maximum distance to draw particles at") +SHADER_PARAM( FARFADEINTERVAL, SHADER_PARAM_TYPE_FLOAT, "400.0", "interval over which to fade out far away particles") +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ + INIT_FLOAT_PARM( MAXDISTANCE, 100000.0); + INIT_FLOAT_PARM( FARFADEINTERVAL, 400.0); + INIT_FLOAT_PARM( MAXSIZE, 20.0 ); + INIT_FLOAT_PARM( ENDFADESIZE, 20.0 ); + INIT_FLOAT_PARM( STARTFADESIZE, 10.0 ); + INIT_FLOAT_PARM( DEPTHBLENDSCALE, 50.0 ); + INIT_FLOAT_PARM( OVERBRIGHTFACTOR, 1.0 ); + INIT_FLOAT_PARM( ADDBASETEXTURE2, 0.0 ); + INIT_FLOAT_PARM( ADDSELF, 0.0 ); + INIT_FLOAT_PARM( ZOOMANIMATESEQ2, 0.0 ); + + if ( !params[DEPTHBLEND]->IsDefined() ) + { + params[ DEPTHBLEND ]->SetIntValue( GetDefaultDepthFeatheringValue() ); + } + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + params[ DEPTHBLEND ]->SetIntValue( 0 ); + } + if ( !params[DUALSEQUENCE]->IsDefined() ) + { + params[DUALSEQUENCE]->SetIntValue( 0 ); + } + if ( !params[MAXLUMFRAMEBLEND1]->IsDefined() ) + { + params[MAXLUMFRAMEBLEND1]->SetIntValue( 0 ); + } + if ( !params[MAXLUMFRAMEBLEND2]->IsDefined() ) + { + params[MAXLUMFRAMEBLEND2]->SetIntValue( 0 ); + } + if ( !params[EXTRACTGREENALPHA]->IsDefined() ) + { + params[EXTRACTGREENALPHA]->SetIntValue( 0 ); + } + if ( !params[ADDOVERBLEND]->IsDefined() ) + { + params[ADDOVERBLEND]->SetIntValue( 0 ); + } + if ( !params[BLENDFRAMES]->IsDefined() ) + { + params[ BLENDFRAMES ]->SetIntValue( 1 ); + } + if ( !params[USEINSTANCING]->IsDefined() ) + { + params[ USEINSTANCING ]->SetIntValue( IsX360() ? 1 : 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_IS_SPRITECARD ); +} + +SHADER_FALLBACK +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "SpriteCard_DX8"; +#endif +#ifdef STDSHADER_DX8_DLL_EXPORT + // STDSHADER_DX8_DLL_EXPORT + if ( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "Wireframe"; +#endif + return 0; +} + +SHADER_INIT +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + const bool bDX8 = false; +#endif +#ifdef STDSHADER_DX8_DLL_EXPORT + const bool bDX8 = true; +#endif + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + if ( params[BASETEXTURE]->IsDefined() ) + { + bool bExtractGreenAlpha = false; + if ( params[EXTRACTGREENALPHA]->IsDefined() ) + { + bExtractGreenAlpha = params[EXTRACTGREENALPHA]->GetIntValue() != 0; + } + + LoadTexture( BASETEXTURE, !bExtractGreenAlpha && !bDX8 ? TEXTUREFLAGS_SRGB : 0 ); + } + if ( params[RAMPTEXTURE]->IsDefined() ) + { + LoadTexture( RAMPTEXTURE, TEXTUREFLAGS_SRGB ); + } +} + +SHADER_DRAW +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + const bool bDX8 = false; +#endif +#ifdef STDSHADER_DX8_DLL_EXPORT + const bool bDX8 = true; +#endif + bool bUseRampTexture = (! bDX8 ) && ( params[RAMPTEXTURE]->IsDefined() ); + bool bZoomSeq2 = (! bDX8 ) && ( ( params[ZOOMANIMATESEQ2]->GetFloatValue()) > 1.0 ); + bool bDepthBlend = (! bDX8 ) && ( params[DEPTHBLEND]->GetIntValue() != 0 ); + bool bAdditive2ndTexture = params[ADDBASETEXTURE2]->GetFloatValue() != 0.0; + int nSplineType = params[SPLINETYPE]->GetIntValue(); + + SHADOW_STATE + { + bool bSecondSequence = params[DUALSEQUENCE]->GetIntValue() != 0; + bool bAddOverBlend = params[ADDOVERBLEND]->GetIntValue() != 0; + bool bExtractGreenAlpha = (! bDX8 ) && ( params[EXTRACTGREENALPHA]->GetIntValue() != 0 ); + bool bBlendFrames = (! bDX8 ) && ( params[BLENDFRAMES]->GetIntValue() != 0 ); + if ( nSplineType ) + { + bBlendFrames = false; + } + bool bAddSelf = params[ADDSELF]->GetFloatValue() != 0.0; + bool bUseInstancing = IsX360() ? ( params[ USEINSTANCING ]->GetIntValue() != 0 ) : false; + if ( nSplineType ) + bUseInstancing = false; + + // draw back-facing because of yaw spin + pShaderShadow->EnableCulling( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + if ( bDX8 ) + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + if ( bAdditive2ndTexture && bDX8 ) + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + if ( bUseRampTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + if ( bDepthBlend ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + if ( bAdditive2ndTexture || bAddSelf ) + pShaderShadow->EnableAlphaTest( false ); + else + pShaderShadow->EnableAlphaTest( true ); + + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.01f ); + + if ( bAdditive2ndTexture || bAddOverBlend || bAddSelf ) + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + } + + unsigned int flags = VERTEX_POSITION | VERTEX_COLOR; + static int s_TexCoordSize[8]={4, // 0 = sheet bounding uvs, frame0 + 4, // 1 = sheet bounding uvs, frame 1 + 4, // 2 = frame blend, rot, radius, ??? + 2, // 3 = corner identifier ( 0/0,1/0,1/1, 1/0 ) + 4, // 4 = texture 2 bounding uvs + 4, // 5 = second sequence bounding uvs, frame0 + 4, // 6 = second sequence bounding uvs, frame1 + 4, // 7 = second sequence frame blend, ?,?,? + }; + static int s_TexCoordSizeSpline[]={4, // 0 = sheet bounding uvs, frame0 + 4, // 1 = sheet bounding uvs, frame 1 + 4, // 2 = frame blend, rot, radius, ??? + 4, // 3 = corner identifier ( 0/0,1/0,1/1, 1/0 ) + 4, // 4 = texture 2 bounding uvs + 4, // 5 = second sequence bounding uvs, frame0 + 4, // 6 = second sequence bounding uvs, frame1 + 4, // 7 = second sequence frame blend, ?,?,? + }; + + int numTexCoords = 4; + if ( true /* bAdditive2ndTexture */ ) // there is no branch for 2nd texture in the VS! -henryg + { + numTexCoords = 5; + } + if ( bSecondSequence ) + { + // the whole shebang - 2 sequences, with a possible multi-image sequence first + numTexCoords = 8; + } + pShaderShadow->VertexShaderVertexFormat( flags, + numTexCoords, + nSplineType? s_TexCoordSizeSpline : s_TexCoordSize, 0 ); + + if ( bDX8 ) + { +#if SUPPORT_DX8 + if ( nSplineType ) + { + DECLARE_STATIC_VERTEX_SHADER( splinecard_vs11 ); + SET_STATIC_VERTEX_SHADER( splinecard_vs11 ); + } + else + { + DECLARE_STATIC_VERTEX_SHADER( spritecard_vs11 ); + if ( bSecondSequence ) + bAdditive2ndTexture = false; + SET_STATIC_VERTEX_SHADER_COMBO( DUALSEQUENCE, false ); + SET_STATIC_VERTEX_SHADER_COMBO( ZOOM_ANIMATE_SEQ2, false ); + SET_STATIC_VERTEX_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_VERTEX_SHADER( spritecard_vs11 ); + } + + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps11 ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( USEALPHAASRGB, bSecondSequence ); + SET_STATIC_PIXEL_SHADER( spritecard_ps11 ); +#endif + } + else + { + if ( nSplineType ) + { + DECLARE_STATIC_VERTEX_SHADER( splinecard_vs20 ); + SET_STATIC_VERTEX_SHADER( splinecard_vs20 ); + } + else + { + DECLARE_STATIC_VERTEX_SHADER( spritecard_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_VERTEX_SHADER_COMBO( ZOOM_ANIMATE_SEQ2, bZoomSeq2 ); + SET_STATIC_VERTEX_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_INSTANCING, bUseInstancing ); + SET_STATIC_VERTEX_SHADER( spritecard_vs20 ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( ANIMBLEND, bBlendFrames ); + SET_STATIC_PIXEL_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_PIXEL_SHADER_COMBO( SEQUENCE_BLEND_MODE, bSecondSequence ? params[SEQUENCE_BLEND_MODE]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND1, params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND2, bSecondSequence? params[MAXLUMFRAMEBLEND1]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORRAMP, bUseRampTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDepthBlend ); + SET_STATIC_PIXEL_SHADER( spritecard_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( ANIMBLEND, bBlendFrames ); + SET_STATIC_PIXEL_SHADER_COMBO( SEQUENCE_BLEND_MODE, bSecondSequence ? params[SEQUENCE_BLEND_MODE]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND1, params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND2, bSecondSequence? params[MAXLUMFRAMEBLEND1]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORRAMP, bUseRampTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_PIXEL_SHADER( spritecard_ps20 ); + } + + if ( !bDX8 ) + pShaderShadow->EnableSRGBWrite( true ); + + if( !bExtractGreenAlpha && !bDX8 ) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + if ( bDX8 ) // bind on 2nd sampelr so we can lerp + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + + if ( bDX8 && bAdditive2ndTexture ) + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + if ( bUseRampTexture && ( !bDX8 ) ) + { + BindTexture( SHADER_SAMPLER1, RAMPTEXTURE, FRAME ); + } + + if ( bDepthBlend ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + + LoadViewportTransformScaledIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10 ); + + int nOrientation = params[ORIENTATION]->GetIntValue(); + nOrientation = clamp( nOrientation, 0, 2 ); + + // We need these only when screen-orienting + if ( nOrientation == 0 ) + { + LoadModelViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 ); + LoadProjectionMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 ); + } + + if ( bZoomSeq2 ) + { + float flZScale=1.0/(params[ZOOMANIMATESEQ2]->GetFloatValue()); + float C0[4]={ 0.5*(1.0+flZScale), flZScale, 0, 0 }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, C0, + ARRAYSIZE(C0)/4 ); + } + + // set fade constants in vsconsts 8 and 9 + float flMaxDistance = params[MAXDISTANCE]->GetFloatValue(); + float flStartFade = max( 1.0, flMaxDistance - params[FARFADEINTERVAL]->GetFloatValue() ); + + float VC0[8]={ params[MINSIZE]->GetFloatValue(), params[MAXSIZE]->GetFloatValue(), + params[STARTFADESIZE]->GetFloatValue(), params[ENDFADESIZE]->GetFloatValue(), + flStartFade, 1.0/(flMaxDistance-flStartFade), + 0,0 }; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, VC0, ARRAYSIZE(VC0)/4 ); + + pShaderAPI->SetDepthFeatheringPixelShaderConstant( 2, params[DEPTHBLENDSCALE]->GetFloatValue() ); + + float C0[4]={ params[ADDBASETEXTURE2]->GetFloatValue(), + params[OVERBRIGHTFACTOR]->GetFloatValue(), + params[ADDSELF]->GetFloatValue(), + 0.0f }; + + if ( bDX8 && ( !bAdditive2ndTexture ) ) // deal with 0..1 limit for pix shader constants + { + C0[2] *= 0.25; + C0[1] *= 0.25; + } + + pShaderAPI->SetPixelShaderConstant( 0, C0, ARRAYSIZE(C0)/4 ); + + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { +#if SUPPORT_DX8 + if ( nSplineType ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( splinecard_vs11 ); + SET_DYNAMIC_VERTEX_SHADER( splinecard_vs11 ); + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( spritecard_vs11 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( ORIENTATION, nOrientation ); + SET_DYNAMIC_VERTEX_SHADER( spritecard_vs11 ); + } +#endif + } + else + { + if ( nSplineType ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( splinecard_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( splinecard_vs20 ); + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( spritecard_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( ORIENTATION, nOrientation ); + SET_DYNAMIC_VERTEX_SHADER( spritecard_vs20 ); + } + } + } + Draw( ); +} +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/spritecard_ps11.fxc b/mp/src/materialsystem/stdshaders/spritecard_ps11.fxc new file mode 100644 index 00000000..624362cb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/spritecard_ps11.fxc @@ -0,0 +1,72 @@ +// STATIC: "ADDBASETEXTURE2" "0..1" +// STATIC: "ADDSELF" "0..1" +// STATIC: "USEALPHAASRGB" "0..1" +// SKIP: $USEALPHAASRGB && $ADDSELF +// SKIP: $USEALPHAASRGB && $ADDBASETEXTURE2 + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD1; + float4 argbcolor : COLOR; + float4 blendfactor0 : TEXCOORD2; +#if ADDBASETEXTURE2 + float2 texCoord2 : TEXCOORD3; +#endif + float4 vScreenPos : TEXCOORD7; +}; + +sampler BaseTextureSampler : register( s0 ); + +#if ADDBASETEXTURE2 +sampler BaseTextureSampler2 : register( s3 ); +#endif + +sampler BaseTextureSampler1 : register( s1 ); +const float4 g_Parameters : register( c0 ); +const float4 g_ColorPowers : register( c1 ); + +#define fAdditiveBlendWeight g_Parameters.x +#define fOverbrightFactor g_Parameters.y +#define fAdditiveSelfBlendWeight g_Parameters.z +#define fSoftParticleBlendScale g_Parameters.w + +#pragma warning( disable : 4707 4704 ) +float4 main( PS_INPUT i ) : COLOR +{ + // Sample frames from texture 0 +#if ( ! ADDSELF ) && ( ! ADDBASETEXTURE2 ) + float4 baseTex0 = tex2D( BaseTextureSampler, i.texCoord0 ); + float4 baseTex1 = tex2D( BaseTextureSampler1, i.texCoord1 ); + float4 blended_rgb = lerp( baseTex0, baseTex1, i.blendfactor0.x ); +#else + float4 blended_rgb = tex2D( BaseTextureSampler, i.texCoord0 ); +#endif +#if USEALPHAASRGB + blended_rgb.rgb = blended_rgb.a; +#endif + +#if ADDBASETEXTURE2 + blended_rgb.a *= i.argbcolor.a; + + // In this case, we don't really want to pre-multiply by alpha + float4 color2 = tex2D( BaseTextureSampler2, i.texCoord2 ); + blended_rgb.rgb *= blended_rgb.a; + blended_rgb.rgb += fOverbrightFactor * fAdditiveBlendWeight * i.argbcolor.a * color2; + blended_rgb.rgb *= 2 * i.argbcolor.rgb; +#else +#if ADDSELF + blended_rgb.a *= i.argbcolor.a; + blended_rgb.rgb *= blended_rgb.a; + blended_rgb.rgb += fOverbrightFactor * 8 * fAdditiveSelfBlendWeight * blended_rgb; + blended_rgb.rgb *= 2 * i.argbcolor.rgb; +#else + blended_rgb *= i.argbcolor; +#endif +#endif + return blended_rgb; +} + diff --git a/mp/src/materialsystem/stdshaders/spritecard_ps2x.fxc b/mp/src/materialsystem/stdshaders/spritecard_ps2x.fxc new file mode 100644 index 00000000..1281d33a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/spritecard_ps2x.fxc @@ -0,0 +1,194 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "DUALSEQUENCE" "0..1" +// STATIC: "SEQUENCE_BLEND_MODE" "0..2" +// STATIC: "ADDBASETEXTURE2" "0..1" +// STATIC: "MAXLUMFRAMEBLEND1" "0..1" +// STATIC: "MAXLUMFRAMEBLEND2" "0..1" +// STATIC: "EXTRACTGREENALPHA" "0..1" +// STATIC: "COLORRAMP" "0..1" +// STATIC: "ANIMBLEND" "0..1" +// STATIC: "ADDSELF" "0..1" +// STATIC: "DEPTHBLEND" "0..1" [ps20b] + +#define COMBINE_MODE_AVERAGE 0 +#define COMBINE_MODE_USE_FIRST_AS_ALPHA_MASK_ON_SECOND 1 +#define COMBINE_MODE_USE_FIRST_OVER_SECOND 2 + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +const float4 g_Parameters : register( c0 ); +const float4 g_DepthFeatheringConstants : register( c2 ); + +#define fAdditiveBlendWeight g_Parameters.x +#define fOverbrightFactor g_Parameters.y +#define fAdditiveSelfBlendWeight g_Parameters.z + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD1; + float4 argbcolor : COLOR; + float4 blendfactor0 : TEXCOORD2; +#if ADDBASETEXTURE2 + float2 texCoord2 : TEXCOORD3; +#endif +#if EXTRACTGREENALPHA + float4 blendfactor1 : TEXCOORD4; +#endif + +#if DUALSEQUENCE + float2 vSeq2TexCoord0 : TEXCOORD5; + float2 vSeq2TexCoord1 : TEXCOORD6; +#endif + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD7; +#else + float4 vScreenPos : TEXCOORD7; +#endif +}; + +sampler BaseTextureSampler : register( s0 ); +sampler ColorRampSampler : register( s1 ); +sampler DepthSampler : register( s2 ); + +float4 main( PS_INPUT i ) : COLOR +{ + bool bMaxLumFrameBlend1 = MAXLUMFRAMEBLEND1 ? true : false; + bool bMaxLumFrameBlend2 = MAXLUMFRAMEBLEND2 ? true : false; + bool bExtractGreenAlpha = EXTRACTGREENALPHA ? true : false; + bool bAddBaseTexture2 = ADDBASETEXTURE2 ? true : false; + bool bDualSequence = DUALSEQUENCE ? true : false; + bool bColorRamp = COLORRAMP ? true : false; +#ifdef DEPTHBLEND + bool bDepthBlend = DEPTHBLEND ? true : false; +#endif + int nSequenceBlendMode = SEQUENCE_BLEND_MODE; + + // Sample frames from texture 0 + float4 baseTex0 = tex2D( BaseTextureSampler, i.texCoord0 ); + + float4 baseTex1 = tex2D( BaseTextureSampler, i.texCoord1 ); + + // Blend by default (may override with bMaxLumFrameBlend1 or bExtractGreenAlpha) +#if ANIMBLEND + float4 blended_rgb = lerp( baseTex0, baseTex1, i.blendfactor0.x ); +#else + float4 blended_rgb = baseTex0; +#endif + + if ( bMaxLumFrameBlend1 ) + { + // Blend between animation frames based upon max luminance + float lum0 = dot( float3(.3, .59, .11), baseTex0.rgb * (1-i.blendfactor0.x)); + float lum1 = dot( float3(.3, .59, .11), baseTex1.rgb * i.blendfactor0.x); + + if ( lum0 > lum1 ) + blended_rgb = baseTex0; + else + blended_rgb = baseTex1; + } + else if( bExtractGreenAlpha ) + { +#if EXTRACTGREENALPHA + // Weight Green/Alphas from the two frames for a scalar result + blended_rgb = dot( baseTex0, i.blendfactor0 ) + dot( baseTex1, i.blendfactor1 ); +#endif + } + +#if DUALSEQUENCE + if ( bDualSequence ) + { + baseTex0 = tex2D( BaseTextureSampler, i.vSeq2TexCoord0 ); + baseTex1 = tex2D( BaseTextureSampler, i.vSeq2TexCoord1 ); + + // Blend by default (may override with bMaxLumFrameBlend2) + float4 rgb2 = lerp( baseTex0, baseTex1, i.blendfactor0.z ); + + if ( bMaxLumFrameBlend2 ) + { + // blend between animation frames based upon max luminance + float tlum0 = dot( float3(.3, .59, .11), baseTex0.rgb * (1-i.blendfactor0.x)); + float tlum1 = dot( float3(.3, .59, .11), baseTex1.rgb * i.blendfactor0.x); + + if ( tlum0 > tlum1 ) + rgb2 = baseTex0; + else + rgb2 = baseTex1; + } + + if ( nSequenceBlendMode == COMBINE_MODE_AVERAGE ) + { + blended_rgb = 0.5 * ( blended_rgb + rgb2 ); + } + else if ( nSequenceBlendMode == COMBINE_MODE_USE_FIRST_AS_ALPHA_MASK_ON_SECOND ) + { + blended_rgb.rgb = rgb2.rgb; + } + else if ( nSequenceBlendMode == COMBINE_MODE_USE_FIRST_OVER_SECOND ) + { + blended_rgb.rgb = lerp( blended_rgb.rgb, rgb2.rgb, rgb2.a ); + } + } // bDualSequence +#endif + + // Optional color ramp + if ( bColorRamp ) + { + blended_rgb.rgb = tex2D( ColorRampSampler, float2( blended_rgb.r, blended_rgb.g ) ); + } + + // Overbright + blended_rgb.rgb *= fOverbrightFactor; + + //Soft Particles FTW +# if (DEPTHBLEND == 1) +# if defined( _X360 ) + float fDepthBlend = DepthFeathering( DepthSampler, i.vScreenPos_ReverseZ.xy / i.vScreenPos_ReverseZ.w, i.vScreenPos_ReverseZ.z, i.vScreenPos_ReverseZ.w, g_DepthFeatheringConstants ); +# else + float fDepthBlend = DepthFeathering( DepthSampler, i.vScreenPos.xy / i.vScreenPos.w, i.vScreenPos.z, i.vScreenPos.w, g_DepthFeatheringConstants ); +# endif + i.argbcolor.a *= fDepthBlend; +# endif + + // Premultiply the alpha for a ONE:INVALPHA blend +#if ADDBASETEXTURE2 + if ( bAddBaseTexture2 ) + { + blended_rgb.a *= i.argbcolor.a; + + // In this case, we don't really want to pre-multiply by alpha + if ( !bColorRamp ) + { + blended_rgb.rgb *= blended_rgb.a; + } + + if ( bExtractGreenAlpha ) + { + blended_rgb.rgb += fAdditiveBlendWeight * i.argbcolor.a * blended_rgb.rgb; + } + else + { + blended_rgb.rgb += fOverbrightFactor * fAdditiveBlendWeight * i.argbcolor.a * tex2D( BaseTextureSampler, i.texCoord2 ); + } + + blended_rgb.rgb *= i.argbcolor.rgb; + } + else +#endif + { +#if ADDSELF + blended_rgb.a *= i.argbcolor.a; + blended_rgb.rgb *= blended_rgb.a; + blended_rgb.rgb += fOverbrightFactor * fAdditiveSelfBlendWeight * i.argbcolor.a * blended_rgb; + blended_rgb.rgb *= i.argbcolor.rgb; +#else + blended_rgb *= i.argbcolor; +#endif + } + + return FinalOutput( blended_rgb, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/mp/src/materialsystem/stdshaders/spritecard_vsxx.fxc b/mp/src/materialsystem/stdshaders/spritecard_vsxx.fxc new file mode 100644 index 00000000..6f670101 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/spritecard_vsxx.fxc @@ -0,0 +1,347 @@ +// STATIC: "ZOOM_ANIMATE_SEQ2" "0..1" [vs20] +// STATIC: "DUALSEQUENCE" "0..1" [vs20] +// STATIC: "EXTRACTGREENALPHA" "0..1" [vs20] + +// STATIC: "ZOOM_ANIMATE_SEQ2" "0..0" [vs11] +// STATIC: "DUALSEQUENCE" "0..0" [vs11] +// STATIC: "EXTRACTGREENALPHA" "0..0" [vs11] + +// STATIC: "USE_INSTANCING" "0..1" [vs20] +// DYNAMIC: "ORIENTATION" "0..2" + + +#include "common_vs_fxc.h" + +const float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0); +const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3); + +#if ZOOM_ANIMATE_SEQ2 +const float4 ScaleParms : register(SHADER_SPECIFIC_CONST_7); +#define OLDFRM_SCALE_START (ScaleParms.x) +#define OLDFRM_SCALE_END (ScaleParms.y) +#endif + +const float4 SizeParms : register(SHADER_SPECIFIC_CONST_8); +const float4 SizeParms2 : register(SHADER_SPECIFIC_CONST_9); +const float4 ViewportTransformScaled : register(SHADER_SPECIFIC_CONST_10); + +#define MINIMUM_SIZE_FACTOR (SizeParms.x) +#define MAXIMUM_SIZE_FACTOR (SizeParms.y) + +#define START_FADE_SIZE_FACTOR (SizeParms.z) +#define END_FADE_SIZE_FACTOR (SizeParms.w) + +// alpha fade w/ distance +#define START_FAR_FADE ( SizeParms2.x ) +#define FAR_FADE_FACTOR ( SizeParms2.y ) // alpha = 1-min(1,max(0, (dist-start_fade)*factor)) + +// Define stuff for instancing on 360 +#if ( defined( _X360 ) && defined( SHADER_MODEL_VS_2_0 ) ) +#define CONST_PC +#define VERTEX_INDEX_PARAM_360 ,int Index:INDEX +#define DO_INSTANCING 1 +#else +#define CONST_PC const +#define VERTEX_INDEX_PARAM_360 +#endif + + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vTint : COLOR; + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vParms : TEXCOORD2; // frame blend, rot, radius, yaw + // FIXME: remove this vertex element for (USE_INSTANCING == 1), need to shuffle the following elements down + float2 vCornerID : TEXCOORD3; // 0,0 1,0 1,1 0,1 + float4 vTexCoord2 : TEXCOORD4; +#if DUALSEQUENCE + float4 vSeq2TexCoord0 : TEXCOORD5; + float4 vSeq2TexCoord1 : TEXCOORD6; + float4 vParms1 : TEXCOORD7; // second frame blend, ?,?,? +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD1; + float4 argbcolor : COLOR; + float4 blendfactor0 : TEXCOORD2; + float2 texCoord2 : TEXCOORD3; +#if !defined( SHADER_MODEL_VS_1_1 ) + float4 blendfactor1 : TEXCOORD4; // for extracting green/alpha +#endif +#if DUALSEQUENCE + float2 vSeq2TexCoord0 : TEXCOORD5; + float2 vSeq2TexCoord1 : TEXCOORD6; +#endif + +#if defined( _X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD7; +#else + float4 vScreenPos : TEXCOORD7; +#endif +}; + +#define BLENDFACTOR v.vParms.x +#define ROTATION v.vParms.y +#define RADIUS v.vParms.z +#define YAW (v.vParms.w) + +#if ( ZOOM_ANIMATE_SEQ2 ) +float getlerpscaled( float l_in, float s0, float s1, float ts ) +{ + l_in = 2.0*(l_in-.5); + l_in *= lerp(s0,s1,ts); + return 0.5+0.5*l_in; +} + +float getlerpscale_for_old_frame( float l_in, float ts ) +{ + return getlerpscaled( l_in, OLDFRM_SCALE_START, OLDFRM_SCALE_END, ts); +} + +float getlerpscale_for_new_frame( float l_in, float ts ) +{ + return getlerpscaled( l_in, 1.0, OLDFRM_SCALE_START, ts ); +} +#endif // ZOOM_ANIMATE_SEQ2 + +#ifdef DO_INSTANCING +void InstancedVertexRead( inout VS_INPUT v, int index ) +{ + // Duplicate each VB vertex 4 times (and generate vCornerID - the only thing that varies per-corner) + float4 vTint; + float4 vPos; + float4 vTexCoord0; + float4 vTexCoord1; + float4 vParms; + float4 vTexCoord2; + float4 vSeq_TexCoord0; // NOTE: April XDK compiler barfs on var names which have a number in the middle! (i.e. vSeq2TexCoord0) + float4 vSeq_TexCoord1; + float4 vParms1; + + int spriteIndex = index / 4; + int cornerIndex = index - 4*spriteIndex; + asm + { + vfetch vTint, spriteIndex, color0; + vfetch vPos, spriteIndex, position0; + vfetch vTexCoord0, spriteIndex, texcoord0; + vfetch vTexCoord1, spriteIndex, texcoord1; + vfetch vParms, spriteIndex, texcoord2; + vfetch vTexCoord2, spriteIndex, texcoord4; +#if DUALSEQUENCE + vfetch vSeq_TexCoord0, spriteIndex, texcoord5; + vfetch vSeq_TexCoord1, spriteIndex, texcoord6; + vfetch vParms1, spriteIndex, texcoord7; +#endif + }; + + v.vTint = vTint; + v.vPos = vPos; + v.vTexCoord0 = vTexCoord0; + v.vTexCoord1 = vTexCoord1; + v.vParms = vParms; + v.vTexCoord2 = vTexCoord2; +#if DUALSEQUENCE + v.vSeq2TexCoord0 = vSeq_TexCoord0; + v.vSeq2TexCoord1 = vSeq_TexCoord1; + v.vParms1 = vParms1; +#endif + + // Compute vCornerID - order is: (0,0) (1,0) (1,1) (0,1) + // float2 IDs[4] = { {0,0}, {1,0}, {1,1}, {0,1} }; + // v.vCornerID.xy = IDs[ cornerIndex ]; + // This compiles to 2 ops on 360 (MADDs with abs/sat register read/write modifiers): + v.vCornerID.xy = float2( 1.5f, 0.0f ) + cornerIndex*float2( -1.0f, 1.0f ); + v.vCornerID.xy = saturate( float2(1.5f, -3.0f) + float2( -1.0f, 2.0f )*abs( v.vCornerID.xy ) ); +} +#endif + +VS_OUTPUT main( CONST_PC VS_INPUT v + VERTEX_INDEX_PARAM_360 ) +{ + VS_OUTPUT o; + +#ifdef DO_INSTANCING + if ( USE_INSTANCING ) + { + InstancedVertexRead( v, Index ); + } +#endif + +#if SHADER_MODEL_VS_1_1 + float4 tint = v.vTint; +#else + float4 tint = GammaToLinear( v.vTint ); +#endif + + float2 sc_yaw; + sincos( YAW, sc_yaw.y, sc_yaw.x ); + + float2 sc; + sincos( ROTATION, sc.y, sc.x ); + + float2 ix=2*v.vCornerID.xy-1; + float x1=dot(ix,sc); + float y1=sc.x*ix.y-sc.y*ix.x; + + float4 projPos; + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + float rad = RADIUS; + float3 v2p = ( worldPos - cEyePos ); + float l = length(v2p); + rad=max(rad, MINIMUM_SIZE_FACTOR * l); + // now, perform fade out +#ifndef SHADER_MODEL_VS_1_1 + if ( rad > START_FADE_SIZE_FACTOR * l ) + { + if ( rad > END_FADE_SIZE_FACTOR *l ) + { + tint = 0; + rad = 0; // cull so we emit 0-sized sprite + } + else + { + tint *= 1-(rad-START_FADE_SIZE_FACTOR*l)/(END_FADE_SIZE_FACTOR*l-START_FADE_SIZE_FACTOR*l); + } + } +#endif + + +#ifndef SHADER_MODEL_VS_1_1 + // perform far fade + float tscale = 1-min(1, max(0, (l-START_FAR_FADE)*FAR_FADE_FACTOR) ); + tint *= tscale; + + if ( tscale <= 0) + rad = 0; // cull so we emit 0-sized sprite +#endif + + rad=min(rad, MAXIMUM_SIZE_FACTOR * l); + +#if ORIENTATION == 0 + // Screen-aligned case + float3 viewPos; + viewPos = mul4x3( v.vPos, cModelView ); + + float3 disp=float3( -x1,y1,0); + float tmpx=disp.x*sc_yaw.x+disp.z*sc_yaw.y; + disp.z = disp.z*sc_yaw.x-disp.x*sc_yaw.y; + disp.x=tmpx; + + viewPos.xyz += disp * rad; + + projPos = mul( float4(viewPos, 1.0f), cProj ); +#endif + +#if ORIENTATION == 1 + // Z-aligned case + if (l > rad/2) + { + float3 up = float3(0,0,1); + float3 right = normalize(cross(up, v2p)); + float tmpx=right.x*sc_yaw.x+right.y*sc_yaw.y; + right.y = right.y*sc_yaw.x-right.x*sc_yaw.y; + right.x=tmpx; + + worldPos += (x1*rad)*right; + worldPos.z += (y1*rad)*up.z; + +#ifndef SHADER_MODEL_VS_1_1 + if (l < rad*2 ) + { + tint *= smoothstep(rad/2,rad,l); + } +#endif + + } + projPos = mul( float4(worldPos, 1.0f), cViewProj ); +#endif + +#if ORIENTATION == 2 + // aligned with z plane case - easy + float3 wpos=v.vPos+RADIUS*float3( y1,x1,0); + projPos = mul( float4(wpos, 1.0f), cModelViewProj ); +#endif + + o.blendfactor0 = float4( v.vParms.x, 0, 0, 0 ); + o.projPos = projPos; + o.texCoord0.x = lerp( v.vTexCoord0.z, v.vTexCoord0.x, v.vCornerID.x ); + o.texCoord0.y = lerp( v.vTexCoord0.w, v.vTexCoord0.y, v.vCornerID.y ); + o.texCoord1.x = lerp( v.vTexCoord1.z, v.vTexCoord1.x, v.vCornerID.x ); + o.texCoord1.y = lerp( v.vTexCoord1.w, v.vTexCoord1.y, v.vCornerID.y ); + o.texCoord2.x = lerp( v.vTexCoord2.z, v.vTexCoord2.x, v.vCornerID.x ); + o.texCoord2.y = lerp( v.vTexCoord2.w, v.vTexCoord2.y, v.vCornerID.y ); + +#if ( DUALSEQUENCE ) + float2 lerpold = v.vCornerID.xy; + float2 lerpnew = v.vCornerID.xy; + +#if ( ZOOM_ANIMATE_SEQ2 ) + lerpold.x = getlerpscale_for_old_frame( v.vCornerID.x, v.vParms1.x ); + lerpold.y = getlerpscale_for_old_frame( v.vCornerID.y, v.vParms1.x ); + lerpnew.x = getlerpscale_for_new_frame( v.vCornerID.x, v.vParms1.x ); + lerpnew.y = getlerpscale_for_new_frame( v.vCornerID.y, v.vParms1.x ); +#endif + + o.vSeq2TexCoord0.xy = lerp( v.vSeq2TexCoord0.zw, v.vSeq2TexCoord0.xy, lerpold.xy ); + o.vSeq2TexCoord1.xy = lerp( v.vSeq2TexCoord1.zw, v.vSeq2TexCoord1.xy, lerpnew.xy ); + + o.blendfactor0.z = v.vParms1.x; +#endif + + +#if !defined( SHADER_MODEL_VS_1_1 ) + + o.blendfactor1 = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + +#if ( EXTRACTGREENALPHA ) + // Input range Output range + if ( v.vParms.x < 0.25f ) // 0.0 .. 0.25 + { + o.blendfactor0.a = v.vParms.x * 2 + 0.5f; // 0.5 .. 1.0 + o.blendfactor0.g = 1 - o.blendfactor0.a; // 0.5 .. 0.0 + } + else if ( v.vParms.x < 0.75f ) // 0.25 .. 0.75 + { + o.blendfactor1.g = v.vParms.x * 2 - 0.5f; // 0.0 .. 1.0 + o.blendfactor0.a = 1 - o.blendfactor1.g; // 1.0 .. 0.0 + } + else // 0.75 .. 1.0 + { + o.blendfactor1.a = v.vParms.x * 2 - 1.5f; // 0.0 .. 0.5 + o.blendfactor1.g = 1 - o.blendfactor1.a; // 1.0 .. 0.5 + } +#endif + +#endif + + // Map projected position to the refraction texture + float2 vScreenPos; + vScreenPos.x = projPos.x; + vScreenPos.y = -projPos.y; // invert Y + vScreenPos = (vScreenPos + projPos.w) * 0.5f; + + // Need to also account for the viewport transform, which matters when rendering with mat_viewportscale != 1.0 + vScreenPos = (vScreenPos * ViewportTransformScaled.xy) + (projPos.w * ViewportTransformScaled.zw); + +#if defined( _X360 ) + o.vScreenPos_ReverseZ = float4(vScreenPos.x, vScreenPos.y, projPos.w - projPos.z, projPos.w ); +#else + o.vScreenPos = float4(vScreenPos.x, vScreenPos.y, projPos.z, projPos.w ); +#endif + + o.argbcolor = tint; + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/teeth.cpp b/mp/src/materialsystem/stdshaders/teeth.cpp new file mode 100644 index 00000000..a3168822 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth.cpp @@ -0,0 +1,578 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +#include "teeth_vs20.inc" +#include "teeth_flashlight_vs20.inc" +#include "teeth_bump_vs20.inc" +#include "teeth_ps20.inc" +#include "teeth_ps20b.inc" +#include "teeth_flashlight_ps20.inc" +#include "teeth_flashlight_ps20b.inc" +#include "teeth_bump_ps20.inc" +#include "teeth_bump_ps20b.inc" + +#ifndef _X360 +#include "teeth_vs30.inc" +#include "teeth_ps30.inc" +#include "teeth_bump_vs30.inc" +#include "teeth_bump_ps30.inc" +#include "teeth_flashlight_vs30.inc" +#include "teeth_flashlight_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX9 ) + +extern ConVar r_flashlight_version2; +BEGIN_VS_SHADER( Teeth_DX9, "Help for Teeth_DX9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "100", "phong exponent" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is teeth in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[INTRO]->IsDefined() ) + { + params[INTRO]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 || g_pConfig->bSoftwareLighting ) + { + return "Teeth_dx8"; + } + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + + if( params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + } + + void DrawUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression ) + { + bool hasBump = params[BUMPMAP]->IsTexture(); + + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base map + + int flags = VERTEX_POSITION | VERTEX_NORMAL; + int nTexCoordCount = 1; + int userDataSize = 0; + + if ( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Normalization sampler for per-pixel lighting + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false ); + userDataSize = 4; // tangent S + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( hasBump ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( teeth_bump_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( teeth_bump_vs20 ); + + // ps_2_b version which does phong + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps20b ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_bump_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_bump_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps30 ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps30 ); + } +#endif + } + else + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( teeth_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( teeth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_ps20b ); + SET_STATIC_PIXEL_SHADER( teeth_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_ps30 ); + SET_STATIC_PIXEL_SHADER( teeth_ps30 ); + } +#endif + } + + // On DX9, do sRGB + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + if ( hasBump ) + { + BindTexture( SHADER_SAMPLER1, BUMPMAP ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE ); + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if ( hasBump ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_bump_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( teeth_bump_vs20 ); + + // ps_2_b version which does Phong + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + Vector4D vSpecExponent; + vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue(); + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_bump_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_bump_vs30 ); + + Vector4D vSpecExponent; + vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps30 ); + } +#endif + } + else + { + // For non-bumped case, ambient cube is computed in the vertex shader + SetAmbientCubeDynamicStateVertexShader(); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( teeth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps30 ); + } +#endif + } + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, timeVec, 1 ); + } + } + Draw(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression ) + { + SHADOW_STATE + { + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Flashlight spot + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + + // Additive blend the teeth, lit by the flashlight + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + s_pShaderShadow->EnableBlending( true ); + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + int nShadowFilterMode = 0; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER2 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // shadow noise + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + } +#endif + // On DX9, do sRGB + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // State for spotlight projection, attenuation etc + SetFlashlightVertexShaderConstants( false, -1, false, -1, true ); + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + bool bFlashlightShadows = g_pHardwareConfig->SupportsPixelShaders_2_b() ? state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) : false; + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + BindTexture( SHADER_SAMPLER2, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_SHADOW_NOISE_2D ); + } + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, lighting.Base() ); + + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + BindTexture( SHADER_SAMPLER1, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + float vFlashlightPos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vFlashlightPos ); + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vFlashlightPos, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + } +#endif + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, timeVec, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + if ( !hasFlashlight || ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawUsingVertexShader( params, pShaderAPI, pShaderShadow, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState(); + } + } + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow, vertexCompression ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/teeth_bump_ps2x.fxc b/mp/src/materialsystem/stdshaders/teeth_bump_ps2x.fxc new file mode 100644 index 00000000..72e43a10 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_bump_ps2x.fxc @@ -0,0 +1,101 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "shader_constant_register_map.h" + +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +sampler BaseTextureSampler : register( s0 ); +sampler BumpTextureSampler : register( s1 ); +sampler NormalizeSampler : register( s2 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 worldVertToEyeVector_Darkening : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + + + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + +#define worldVertToEyeVector i.worldVertToEyeVector_Darkening.xyz +#define fDarkening i.worldVertToEyeVector_Darkening.w + +#endif + + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vLightAtten = float4( i.lightAtten01, i.lightAtten23 ); + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float3 worldSpaceNormal, tangentSpaceNormal = float3(0, 0, 1); + float fSpecExp = g_EyePos_SpecExponent.w; + + float4 normalTexel = tex2D( BumpTextureSampler, i.baseTexCoord ); + tangentSpaceNormal = 2.0f * normalTexel.xyz - 1.0f; + worldSpaceNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent + if ( fSpecExp == 0 ) + fSpecExp = 1.0f * ( 1.0f - normalTexel.w ) + 150.0f * normalTexel.w; + + // Summation of diffuse illumination from all local lights + float3 diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, + bAmbientLight, vLightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, true, + false, 0, false, NormalizeSampler ); + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + + float3 vDummy, specularLighting; + + // Summation of specular from all local lights + PixelShaderDoSpecularLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, fSpecExp, normalize(worldVertToEyeVector), + vLightAtten, nNumLights, cLightInfo, + false, 1.0f, false, NormalizeSampler, 1.0f, false, 1.0f, + + // Outputs + specularLighting, vDummy ); + + // Specular plus diffuse, all darkened as a function of mouth openness + float3 result = (specularLighting * baseSample.a + baseSample.rgb * diffuseLighting) * fDarkening; + +#else + float3 result = baseSample.rgb * diffuseLighting * i.worldVertToEyeVector_Darkening.w; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( float4(result, 1.0f), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/mp/src/materialsystem/stdshaders/teeth_bump_vs20.fxc b/mp/src/materialsystem/stdshaders/teeth_bump_vs20.fxc new file mode 100644 index 00000000..1dd834b5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_bump_vs20.fxc @@ -0,0 +1,152 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== + +// STATIC: "INTRO" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_0 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_1 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + float4 vUserData : TANGENT; // Sign for cross product in w + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float4 worldVertToEyeVector_Darkening : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), + vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + +#if INTRO + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, worldTangentS, worldTangentT ); +#endif + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos, vProjPos.z ); +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, vProjPos, g_FogType ); +#endif + // Needed for specular + o.worldVertToEyeVector_Darkening.xyz = cEyePos - worldPos; + + // Special darkening of lights for mouth open/close + o.worldVertToEyeVector_Darkening.w = cTeethLighting.w * saturate( dot( worldNormal, cTeethLighting.xyz ) );; + + // Scalar light attenuation (mouth darkening applied in pixel shader) +#if defined( SHADER_MODEL_VS_2_0 ) && ( !USE_STATIC_CONTROL_FLOW ) + o.lightAtten01.xy = float2(0,0); + o.lightAtten23.xy = float2(0,0); + #if ( NUM_LIGHTS > 0 ) + o.lightAtten01.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten01.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten23.x = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.lightAtten23.y = GetVertexAttenForLight( worldPos, 3, false ); + #endif +#else + o.lightAtten01.x = GetVertexAttenForLight( worldPos, 0, true ); + o.lightAtten01.y = GetVertexAttenForLight( worldPos, 1, true ); + o.lightAtten23.x = GetVertexAttenForLight( worldPos, 2, true ); + o.lightAtten23.y = GetVertexAttenForLight( worldPos, 3, true ); +#endif + + o.baseTexCoord = v.vTexCoord0; + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/teeth_dx6.cpp b/mp/src/materialsystem/stdshaders/teeth_dx6.cpp new file mode 100644 index 00000000..8c097f6a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_dx6.cpp @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX6 ) + +BEGIN_VS_SHADER( Teeth_DX6, + "Help for Teeth_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + } + + void DrawUsingSoftwareLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + } + else + { + DrawUsingSoftwareLighting( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/teeth_dx8.cpp b/mp/src/materialsystem/stdshaders/teeth_dx8.cpp new file mode 100644 index 00000000..d91626d8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_dx8.cpp @@ -0,0 +1,116 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" + +#include "teeth.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX8 ) + +BEGIN_VS_SHADER( Teeth_DX8, "Help for Teeth_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is teeth in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[INTRO]->IsDefined() ) + { + params[INTRO]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + if ( IsPC() && ( g_pHardwareConfig->GetDXSupportLevel() < 80 || g_pConfig->bSoftwareLighting ) ) + { + return "Teeth_dx6"; + } + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + } + + void DrawUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL, 1, 0, 0 ); + teeth_Static_Index vshIndex; + vshIndex.SetHALF_LAMBERT( IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + vshIndex.SetINTRO( params[INTRO]->GetIntValue() != 0 ); + pShaderShadow->SetVertexShader( "Teeth", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "VertexLitTexture_Overbright2" ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetAmbientCubeDynamicStateVertexShader(); + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + + teeth_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetLIGHT_COMBO( pShaderAPI->GetCurrentLightCombo() ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, timeVec, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, false, false, 0, -1, -1, + // Optional parameters, specific to teeth: + true, FORWARD, ILLUMFACTOR ); + } + else + { + DrawUsingVertexShader( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc b/mp/src/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc new file mode 100644 index 00000000..7ef61872 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc @@ -0,0 +1,66 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler SpotSampler : register( s1 ); +sampler FlashlightDepthSampler : register( s2 ); +sampler RandomRotationSampler : register( s3 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float3 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float3 g_FlashlightPos : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4 g_FlashlightAtten : register( PSREG_FLASHLIGHT_ATTENUATION ); +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +const float4 g_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; // Base texture coordinates + float4 spotTexCoord : TEXCOORD1; // Spotlight texture coordinates + float3 vertAtten : TEXCOORD2; // Distance/spot attenuation + float4 projPos : TEXCOORD3; // Projective space position + float3 worldPos : TEXCOORD4; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if defined( SHADER_MODEL_PS_2_0 ) + float3 result = tex2Dproj( SpotSampler, i.spotTexCoord.xyzw ); +#else + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + float3 result = tex2D( SpotSampler, vProjCoords ); +#endif + + result *= cFlashlightColor.rgb; + +#if FLASHLIGHTSHADOWS && ( defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) + result *= DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos.xy / i.projPos.z, FLASHLIGHTDEPTHFILTERMODE, g_ShadowTweaks, true ); +#endif + result *= 0.35f; // Without this, unshadowed teeth always seem to glow + + result *= i.vertAtten; // Distance atten, NdotL and forward vector + + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + result *= baseSample.rgb; // Multiply by base map and diffuse + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z ); + return FinalOutput( float4( result, baseSample.a ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/mp/src/materialsystem/stdshaders/teeth_flashlight_vs20.fxc b/mp/src/materialsystem/stdshaders/teeth_flashlight_vs20.fxc new file mode 100644 index 00000000..8c5ce4c5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_flashlight_vs20.fxc @@ -0,0 +1,149 @@ +//======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== + +// STATIC: "INTRO" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cFlashlightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cSpotlightProj1 : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cSpotlightProj2 : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cSpotlightProj3 : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cSpotlightProj4 : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cFlashlighAtten : register( SHADER_SPECIFIC_CONST_5 ); // const, linear, quadratic & farZ + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_8 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_9 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; // Base texture coordinates + float4 spotTexCoord : TEXCOORD1; // Spotlight texture coordinates + float3 vertAtten : TEXCOORD2; // Distance/spot attenuation + float4 vProjPos : TEXCOORD3; // Projective space position + float3 worldPos : TEXCOORD4; // Necessary for pixel fog +}; + + +float RemapValClamped_01( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Normalize the flexed normal + vNormal.xyz = normalize( vNormal.xyz ); + + // Transform the position + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, dummy, dummy ); +#endif + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos = worldPos.xyz; + o.vProjPos = o.projPos; +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, o.projPos, g_FogType ); +#endif + // Spotlight texture coordinates + o.spotTexCoord.x = dot( cSpotlightProj1, float4(worldPos, 1) ); + o.spotTexCoord.y = dot( cSpotlightProj2, float4(worldPos, 1) ); + o.spotTexCoord.z = dot( cSpotlightProj3, float4(worldPos, 1) ); + o.spotTexCoord.w = dot( cSpotlightProj4, float4(worldPos, 1) ); + + // Compute vector to light + float3 vWorldPosToLightVector = cFlashlightPosition.xyz - worldPos; + + float3 vDistAtten = float3(1, 1, 1); + vDistAtten.z = dot( vWorldPosToLightVector, vWorldPosToLightVector ); + vDistAtten.y = rsqrt( vDistAtten.z ); + + float flDist = vDistAtten.z * vDistAtten.y; // Distance to light + vDistAtten.z = 1.0f / vDistAtten.z; // 1 / distsquared + + float fFarZ = cFlashlighAtten.w; + + float NdotL = saturate( dot( worldNormal, normalize( vWorldPosToLightVector ) ) ); + + float endFalloffFactor = RemapValClamped_01( flDist, fFarZ, 0.6 * fFarZ ); + o.vertAtten.xyz = endFalloffFactor * dot( vDistAtten, cFlashlighAtten.xyz ); + + // Final attenuation from flashlight only... + float linearAtten = NdotL * dot( vDistAtten, cFlashlighAtten.xyz ) * endFalloffFactor; + + // Forward vector + float3 vForward = cTeethLighting.xyz; + float fIllumFactor = cTeethLighting.w; + + // Modulate flashlight by mouth darkening + o.vertAtten = linearAtten * fIllumFactor * saturate( dot( worldNormal, vForward ) ); + + o.baseTexCoord = v.vTexCoord0; + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/teeth_ps2x.fxc b/mp/src/materialsystem/stdshaders/teeth_ps2x.fxc new file mode 100644 index 00000000..4893f9aa --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_ps2x.fxc @@ -0,0 +1,48 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] + + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float3 vertAtten : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float4 result; + result.xyz = baseSample.xyz * i.vertAtten; + result.a = baseSample.a; + + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/mp/src/materialsystem/stdshaders/teeth_vs20.fxc b/mp/src/materialsystem/stdshaders/teeth_vs20.fxc new file mode 100644 index 00000000..9a9ab045 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/teeth_vs20.fxc @@ -0,0 +1,127 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== + +// STATIC: "INTRO" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_0 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_1 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float3 vertAtten : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Normalize the flexed normal + vNormal.xyz = normalize( vNormal.xyz ); + + // Transform the position + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, dummy, dummy ); +#endif + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, vProjPos, g_FogType ); +#endif + + // Compute lighting +#if ( USE_STATIC_CONTROL_FLOW ) || defined ( SHADER_MODEL_VS_3_0 ) + float3 linearColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, false ); +#else + float3 linearColor = DoLightingUnrolled( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, false, NUM_LIGHTS ); +#endif + + // Forward vector + float3 vForward = cTeethLighting.xyz; + float fIllumFactor = cTeethLighting.w; + + // Darken by forward dot normal and illumination factor + linearColor *= fIllumFactor * saturate( dot( worldNormal, vForward ) ); + + o.vertAtten = linearColor; + o.baseTexCoord = v.vTexCoord0; + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_basetimesdetail.psh b/mp/src/materialsystem/stdshaders/unlitgeneric_basetimesdetail.psh new file mode 100644 index 00000000..8f9139df --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_basetimesdetail.psh @@ -0,0 +1,24 @@ +ps.1.1 +def c0,0,0,0,.1 +def c1,0,0,0,.1 +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; tc3 - detail texcoords +; +; c3 = outline color +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t3 ; detail mask + +mul r1,t0,t3 ; multiply + +mov r0.rgb, c3 ; color = outline color +;add r0.a, r1.a, c0.a +;cnd r0.rgb, r0.a, r0, r1 ; if ( alpha+c0 > 0.5 ) color = outline, else color = base +sub r0.a, r1.a, c1.a +cnd r0.rgb, r0.a, r1, r0 ; if ( alpha -c1 > 0.5) color=base diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_dx6.cpp b/mp/src/materialsystem/stdshaders/unlitgeneric_dx6.cpp new file mode 100644 index 00000000..fc8bdf47 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_dx6.cpp @@ -0,0 +1,310 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( UnlitGeneric, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( MonitorScreen, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( ParticleSphere, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( Predator, Predator_DX60 ) +DEFINE_FALLBACK_SHADER( Predator_DX60, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( WindowImposter, WindowImposter_DX60 ) +DEFINE_FALLBACK_SHADER( WindowImposter_DX60, UnlitGeneric_DX6 ) + +BEGIN_SHADER( UnlitGeneric_DX6, + "Help for UnlitGeneric_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No texture means no env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // the second texture (if there is one) + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + SET_FLAGS(MATERIAL_VAR_ENVMAPSPHERE); + + if (params[ENVMAPMASK]->IsDefined()) + { + LoadTexture( ENVMAPMASK ); + } + } + } + + int GetDrawFlagsPass1(IMaterialVar** params, bool doDetail) + { + int flags = SHADER_DRAW_POSITION; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + if (params[BASETEXTURE]->IsTexture()) + flags |= SHADER_DRAW_TEXCOORD0; + if (doDetail) + flags |= SHADER_DRAW_TEXCOORD1; + return flags; + } + + void SetDetailShadowState(IShaderShadow* pShaderShadow) + { + // Specifically choose overbright2, will cause mod2x here + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 2.0f ); + } + + void SetDetailDymamicState(IShaderShadow* pShaderShadow) + { + BindTexture( SHADER_SAMPLER1, DETAIL, FRAME ); + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE1, BASETEXTURETRANSFORM, DETAILSCALE ); + } + + void DrawAdditiveNonTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + SetModulationShadowState(); + SetAdditiveBlendingShadowState( ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToBlack(); + } + DYNAMIC_STATE + { + SetModulationDynamicState(); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + } + Draw( ); + } + + void DrawAdditiveTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + SetModulationShadowState(); + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + SetModulationDynamicState(); + } + Draw( ); + } + + void DrawNonTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + SetModulationShadowState(); + SetNormalBlendingShadowState( ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToFogColor(); + } + DYNAMIC_STATE + { + SetModulationDynamicState(); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + } + Draw( ); + } + + void DrawTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + SetModulationShadowState(); + SetNormalBlendingShadowState( BASETEXTURE, true ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + SetModulationDynamicState(); + } + Draw( ); + } + + SHADER_DRAW + { + bool isTextureDefined = params[BASETEXTURE]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + bool doFirstPass = isTextureDefined || hasVertexColor || (!params[ENVMAP]->IsTexture()); + + if (doFirstPass) + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + if( params[ALPHATESTREFERENCE]->IsDefined() && params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + } + + if (IS_FLAG_SET(MATERIAL_VAR_ADDITIVE)) + { + if (!isTextureDefined) + { + bool hasDetailTexture = params[DETAIL]->IsTexture(); + DrawAdditiveNonTextured( params, pShaderAPI, pShaderShadow, hasDetailTexture ); + } + else + { + // We can't do detail in a single pass if we're also + // colormodulating and have vertex color + bool hasDetailTexture = params[DETAIL]->IsTexture(); + bool isModulating = IsColorModulating() || IsAlphaModulating(); + bool onePassDetail = hasDetailTexture && (!hasVertexColor || !isModulating); + DrawAdditiveTextured( params, pShaderAPI, pShaderShadow, onePassDetail ); + if (hasDetailTexture && !onePassDetail) + { + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + } + } + else + { + if (!isTextureDefined) + { + bool hasDetailTexture = params[DETAIL]->IsTexture(); + DrawNonTextured( params, pShaderAPI, pShaderShadow, hasDetailTexture ); + } + else + { + // We can't do detail in a single pass if we're also + // colormodulating and have vertex color + bool hasDetailTexture = params[DETAIL]->IsTexture(); + bool isModulating = IsColorModulating() || IsAlphaModulating(); + bool onePassDetail = hasDetailTexture && (!hasVertexColor || !isModulating); + DrawTextured( params, pShaderAPI, pShaderShadow, onePassDetail ); + if (hasDetailTexture && !onePassDetail) + { + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + } + } + } + + SHADOW_STATE + { + // Disable mod2x used by detail + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + } + + // Second pass... + if (params[ENVMAP]->IsTexture() && + (!doFirstPass || IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) ) + { + if (doFirstPass || IS_FLAG_SET(MATERIAL_VAR_ADDITIVE)) + { + FixedFunctionAdditiveMaskedEnvmapPass( ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + else + { + FixedFunctionMaskedEnvmapPass( ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_dx8.cpp b/mp/src/materialsystem/stdshaders/unlitgeneric_dx8.cpp new file mode 100644 index 00000000..19d0e169 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_dx8.cpp @@ -0,0 +1,72 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( UnlitGeneric, UnlitGeneric_DX8 ) + +BEGIN_VS_SHADER( UnlitGeneric_DX8, + "Help for UnlitGeneric_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && !g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + return "UnlitGeneric_DX6"; + } + return 0; + } + + SHADER_INIT_PARAMS() + { + InitParamsUnlitGeneric_DX8( + BASETEXTURE, DETAILSCALE, ENVMAPOPTIONAL, + ENVMAP, ENVMAPTINT, ENVMAPMASKSCALE, + DETAILBLENDMODE ); + } + + SHADER_INIT + { + InitUnlitGeneric_DX8( BASETEXTURE, DETAIL, ENVMAP, ENVMAPMASK ); + } + + SHADER_DRAW + { + VertexShaderUnlitGenericPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, + DETAIL, DETAILSCALE, true, ENVMAP, ENVMAPFRAME, ENVMAPMASK, + ENVMAPMASKFRAME, ENVMAPMASKSCALE, ENVMAPTINT, ALPHATESTREFERENCE, + DETAILBLENDMODE, + OUTLINE, OUTLINECOLOR, OUTLINESTART0, OUTLINEEND1, SEPARATEDETAILUVS ); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_dx9.cpp b/mp/src/materialsystem/stdshaders/unlitgeneric_dx9.cpp new file mode 100644 index 00000000..b57474a8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_dx9.cpp @@ -0,0 +1,200 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" + +extern ConVar r_flashlight_version2; + +BEGIN_VS_SHADER( UnlitGeneric, "Help for UnlitGeneric" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + SHADER_PARAM( VERTEXALPHATEST, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( HDRCOLORSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "hdr color scale" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "2D map for warping specular" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + + SHADER_PARAM( SELFILLUMMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "If we bind a texture here, it overrides base alpha (if any) for self illum" ) + + SHADER_PARAM( DISTANCEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use distance-coded alpha generated from hi-res texture by vtex.") + SHADER_PARAM( DISTANCEALPHAFROMDETAIL, SHADER_PARAM_TYPE_BOOL, "0", "Take the distance-coded alpha mask from the detail texture.") + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( SCALEEDGESOFTNESSBASEDONSCREENRES, SHADER_PARAM_TYPE_BOOL, "0", "Scale the size of the soft edges based upon resolution. 1024x768 = nominal.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( GLOW, SHADER_PARAM_TYPE_BOOL, "0", "Enable glow/shadow for distance coded textures.") + SHADER_PARAM( GLOWCOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outter glow for distance coded line art." ) + SHADER_PARAM( GLOWALPHA, SHADER_PARAM_TYPE_FLOAT, "1", "Base glow alpha amount for glows/shadows with distance alpha." ) + SHADER_PARAM( GLOWSTART, SHADER_PARAM_TYPE_FLOAT, "0.7", "start value for glow/shadow") + SHADER_PARAM( GLOWEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "end value for glow/shadow") + SHADER_PARAM( GLOWX, SHADER_PARAM_TYPE_FLOAT, "0", "texture offset x for glow mask.") + SHADER_PARAM( GLOWY, SHADER_PARAM_TYPE_FLOAT, "0", "texture offset y for glow mask.") + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + SHADER_PARAM( SCALEOUTLINESOFTNESSBASEDONSCREENRES, SHADER_PARAM_TYPE_BOOL, "0", "Scale the size of the soft part of the outline based upon resolution. 1024x768 = nominal.") + + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_BOOL, "0", "Use texcoord1 for detail texture" ) + + SHADER_PARAM( GAMMACOLORREAD, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of color texture read." ) + SHADER_PARAM( LINEARWRITE, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of shader results." ) + + SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries" ) + SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) + SHADER_PARAM( RECEIVEFLASHLIGHT, SHADER_PARAM_TYPE_INTEGER, "0", "Forces this material to receive flashlights." ) + + END_SHADER_PARAMS + + void SetupVars( VertexLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = -1; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = -1; + info.m_nBumpFrame = -1; + info.m_nBumpTransform = -1; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nVertexAlphaTest = VERTEXALPHATEST; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nHDRColorScale = HDRCOLORSCALE; + info.m_nPhongExponent = -1; + info.m_nPhongExponentTexture = -1; + info.m_nDiffuseWarpTexture = -1; + info.m_nPhongWarpTexture = -1; + info.m_nPhongBoost = -1; + info.m_nPhongFresnelRanges = -1; + info.m_nPhong = -1; + info.m_nPhongTint = -1; + info.m_nPhongAlbedoTint = -1; + info.m_nSelfIllumEnvMapMask_Alpha = -1; + info.m_nAmbientOnly = -1; + info.m_nBaseMapAlphaPhongMask = -1; + info.m_nEnvmapFresnel = -1; + info.m_nSelfIllumMask = -1; + + info.m_nDistanceAlpha = DISTANCEALPHA; + info.m_nDistanceAlphaFromDetail = DISTANCEALPHAFROMDETAIL; + info.m_nSoftEdges = SOFTEDGES; + info.m_nEdgeSoftnessStart = EDGESOFTNESSSTART; + info.m_nEdgeSoftnessEnd = EDGESOFTNESSEND; + info.m_nScaleEdgeSoftnessBasedOnScreenRes = SCALEEDGESOFTNESSBASEDONSCREENRES; + + info.m_nGlow = GLOW; + info.m_nGlowColor = GLOWCOLOR; + info.m_nGlowAlpha = GLOWALPHA; + info.m_nGlowStart = GLOWSTART; + info.m_nGlowEnd = GLOWEND; + info.m_nGlowX = GLOWX; + info.m_nGlowY = GLOWY; + + info.m_nOutline = OUTLINE; + info.m_nOutlineColor = OUTLINECOLOR; + info.m_nOutlineAlpha = OUTLINEALPHA; + info.m_nOutlineStart0 = OUTLINESTART0; + info.m_nOutlineStart1 = OUTLINESTART1; + info.m_nOutlineEnd0 = OUTLINEEND0; + info.m_nOutlineEnd1 = OUTLINEEND1; + info.m_nScaleOutlineSoftnessBasedOnScreenRes = SCALEOUTLINESOFTNESSBASEDONSCREENRES; + + info.m_nSeparateDetailUVs = SEPARATEDETAILUVS; + + info.m_nLinearWrite = LINEARWRITE; + info.m_nGammaColorRead = GAMMACOLORREAD; + + info.m_nDepthBlend = DEPTHBLEND; + info.m_nDepthBlendScale = DEPTHBLENDSCALE; + info.m_nReceiveFlashlight = RECEIVEFLASHLIGHT; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, false, vars ); + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "UnlitGeneric_DX8"; + } + return 0; + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, false, vars ); + } + + SHADER_DRAW + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + + bool bNewFlashlightPath = IsX360() || ( r_flashlight_version2.GetInt() != 0 ); + if ( ( pShaderShadow == NULL ) && ( pShaderAPI != NULL ) && !bNewFlashlightPath && pShaderAPI->InFlashlightMode() ) // Not snapshotting && flashlight pass + { + Draw( false ); + } + else + { + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, false, vars, vertexCompression, pContextDataPtr ); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_inc.vsh b/mp/src/materialsystem/stdshaders/unlitgeneric_inc.vsh new file mode 100644 index 00000000..ac2abb7e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_inc.vsh @@ -0,0 +1,142 @@ +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +; $SHADER_SPECIFIC_CONST_4-$SHADER_SPECIFIC_CONST_5 = Detail texture transform +;------------------------------------------------------------------------------ + +sub UnlitGeneric +{ + local( $detail ) = shift; + local( $envmap ) = shift; + local( $envmapcameraspace ) = shift; + local( $envmapsphere ) = shift; + local( $vertexcolor ) = shift; + local( $separatedetailuvs ) = shift; + + local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + + ;------------------------------------------------------------------------------ + ; Vertex blending + ;------------------------------------------------------------------------------ + &AllocateRegister( \$worldPos ); + if( $envmap ) + { + &AllocateRegister( \$worldNormal ); + &SkinPositionAndNormal( $worldPos, $worldNormal ); + } + else + { + &SkinPosition( $worldPos ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to proj space + ;------------------------------------------------------------------------------ + + &AllocateRegister( \$projPos ); + + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + mov oPos, $projPos + + ;------------------------------------------------------------------------------ + ; Fog + ;------------------------------------------------------------------------------ + &CalcFog( $worldPos, $projPos ); + &FreeRegister( \$projPos ); + + if( !$envmap ) + { + &FreeRegister( \$worldPos ); + } + + ;------------------------------------------------------------------------------ + ; Texture coordinates (use world-space normal for envmap, tex transform for mask) + ;------------------------------------------------------------------------------ + dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 + dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT0.zw, $cZero + } + + if( $envmap ) + { + if( $envmapcameraspace ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + + ; transform reflection vector into view space + dp3 oT1.x, $reflectionVector, $cViewModel0 + dp3 oT1.y, $reflectionVector, $cViewModel1 + dp3 oT1.z, $reflectionVector, $cViewModel2 + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT1.w, $cZero + } + + &FreeRegister( \$reflectionVector ); + } + elsif( $envmapsphere ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + &ComputeSphereMapTexCoords( $reflectionVector, "oT1" ); + + &FreeRegister( \$reflectionVector ); + } + else + { + &ComputeReflectionVector( $worldPos, $worldNormal, "oT1" ); + } + + ; envmap mask + dp4 oT2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + dp4 oT2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT2.zw, $cZero + } + + &FreeRegister( \$worldPos ); + &FreeRegister( \$worldNormal ); + } + + if( $detail ) + { + if ( $separatedetailuvs ) + { + mov oT3, $vTexCoord1 + } + else + { + dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 + dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + } + + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT3.zw, $cZero + } + } + + if( $vertexcolor ) + { + ; Modulation color + mul oD0, $vColor, $cModulationColor + } + else + { + ; Modulation color + mov oD0, $cModulationColor + } +} diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_lightingonly_vs11.fxc b/mp/src/materialsystem/stdshaders/unlitgeneric_lightingonly_vs11.fxc new file mode 100644 index 00000000..dcbd43a2 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_lightingonly_vs11.fxc @@ -0,0 +1,47 @@ +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + o.vDiffuse = 1.0f; + + return o; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps11.fxc b/mp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps11.fxc new file mode 100644 index 00000000..e3970e87 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps11.fxc @@ -0,0 +1,9 @@ +struct PS_INPUT +{ + float4 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return i.vColor0; +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc b/mp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc new file mode 100644 index 00000000..e4fffb83 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc @@ -0,0 +1,14 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( i.vColor0, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_ps11.fxc b/mp/src/materialsystem/stdshaders/unlitgeneric_ps11.fxc new file mode 100644 index 00000000..071d666c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_ps11.fxc @@ -0,0 +1,12 @@ +sampler TextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord0 : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return i.vColor0 * tex2D( TextureSampler, i.vTexCoord0 ); +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_ps2x.fxc b/mp/src/materialsystem/stdshaders/unlitgeneric_ps2x.fxc new file mode 100644 index 00000000..1620638f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_ps2x.fxc @@ -0,0 +1,19 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#include "common_ps_fxc.h" + +sampler TextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord0 : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = i.vColor0 * tex2D( TextureSampler, i.vTexCoord0 ); + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_vs11.vsh b/mp/src/materialsystem/stdshaders/unlitgeneric_vs11.vsh new file mode 100644 index 00000000..b165fa7a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_vs11.vsh @@ -0,0 +1,23 @@ +vs.1.1 + +# STATIC: "DETAIL" "0..1" +# STATIC: "ENVMAP" "0..1" +# STATIC: "ENVMAPCAMERASPACE" "0..0" +# STATIC: "ENVMAPSPHERE" "0..1" +# STATIC: "VERTEXCOLOR" "0..1" +# STATIC: "SEPARATEDETAILUVS" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +# can't have envmapshere or envmapcameraspace without envmap +# SKIP: !$ENVMAP && ( $ENVMAPSPHERE || $ENVMAPCAMERASPACE ) + +# can't have both envmapsphere and envmapcameraspace +# SKIP: $ENVMAPSPHERE && $ENVMAPCAMERASPACE + +# SKIP: !$DETAIL && $SEPARATEDETAILUVS + + +#include "UnlitGeneric_inc.vsh" + +&UnlitGeneric( $DETAIL, $ENVMAP, $ENVMAPCAMERASPACE, $ENVMAPSPHERE, $VERTEXCOLOR, $SEPARATEDETAILUVS ); diff --git a/mp/src/materialsystem/stdshaders/unlitgeneric_vs20.fxc b/mp/src/materialsystem/stdshaders/unlitgeneric_vs20.fxc new file mode 100644 index 00000000..37249305 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/unlitgeneric_vs20.fxc @@ -0,0 +1,91 @@ +// STATIC: "VERTEXCOLOR" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cBaseTextureTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cMaskTextureTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cDetailTextureTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); +const float4 g_vVertexColor : register( SHADER_SPECIFIC_CONST_6 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + +#if VERTEXCOLOR + float4 vColor : COLOR0; +#endif + + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + + float4 vColor : COLOR0; + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + float3 worldNormal; + + //------------------------------------------------------------------------------ + // Vertex blending + //------------------------------------------------------------------------------ + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + vProjPos = dot( float4( worldPos, 1 ), cViewProjZ ); + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + + //------------------------------------------------------------------------------ + // Fog + //------------------------------------------------------------------------------ + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + //------------------------------------------------------------------------------ + // Texture coord transforms + //------------------------------------------------------------------------------ + o.vTexCoord0 = mul( v.vTexCoord0, (float2x4)cBaseTextureTransform ); + o.vTexCoord3 = mul( v.vTexCoord0, (float2x4)cDetailTextureTransform ); + + o.vColor = cModulationColor; + +#if VERTEXCOLOR + // 0 or 1 for g_vVertexColor.x, eliminating a bool + o.vColor = lerp( o.vColor, o.vColor * v.vColor, g_vVertexColor.x ); +#endif + + return o; +} + + + diff --git a/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc new file mode 100644 index 00000000..7768f477 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc @@ -0,0 +1,350 @@ +//======= Copyright © 1996-2008, Valve Corporation, All rights reserved. ====== + +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "SELFILLUMFRESNEL" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..6" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "BLENDTINTBYBASEALPHA" "0..1" + +// DYNAMIC: "PIXELFOGTYPE" "0..1" [ps20] +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] [PC] + +// We don't use light combos when doing the flashlight +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) [PC] + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30] + +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// Don't do diffuse warp on flashlight +// SKIP: ( $FLASHLIGHT == 1 ) && ( $LIGHTWARPTEXTURE == 1 ) [PC] + +// Only warp diffuse if we have it at all +// SKIP: ( $DIFFUSELIGHTING == 0 ) && ( $LIGHTWARPTEXTURE == 1 ) + +// Skip this since it blows ps20 instruction limits +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $LIGHTWARPTEXTURE == 1 ) + +// Only need self illum fresnel when self illum enabled +// SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) [PC] +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUM == 1 ) [PC] +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $DETAILTEXTURE == 1 ) +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $NORMALMAPALPHAENVMAPMASK == 1 ) + +// BlendTintByBaseAlpha is incompatible with other interpretations of alpha +// SKIP: ($BLENDTINTBYBASEALPHA) && ($SELFILLUM) + +// Only _XBOX allows flashlight and cubemap in the current implementation +// SKIP: $FLASHLIGHT && $CUBEMAP [PC] + +// Meaningless combinations +// SKIP: $NORMALMAPALPHAENVMAPMASK && !$CUBEMAP + +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_EnvmapTint_TintReplaceFactor : register( c0 ); +const float4 g_DiffuseModulation : register( c1 ); +const float4 g_EnvmapContrast_ShadowTweaks : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_SelfIllumTint_and_BlendFactor : register( c4 ); +#define g_SelfIllumTint ( g_SelfIllumTint_and_BlendFactor.rgb) +#define g_DetailBlendFactor (g_SelfIllumTint_and_BlendFactor.w) + +const float3 cAmbientCube[6] : register( c5 ); + +// 11, 12 not used? +#if ( SELFILLUMFRESNEL == 1 ) + const float4 g_SelfIllumScaleBiasExpBrightness : register( c11 ); +#endif + +const float4 g_ShaderControls : register( c12 ); +#define g_fPixelFogType g_ShaderControls.x +#define g_fWriteDepthToAlpha g_ShaderControls.y +#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z + + +// 2 registers each - 6 registers total +PixelShaderLightInfo cLightInfo[3] : register( c13 ); // through c18 + +const float3 g_EyePos : register( c20 ); +const float4 g_FogParams : register( c21 ); + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const float3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler DetailSampler : register( s2 ); +sampler BumpmapSampler : register( s3 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler NormalizeSampler : register( s5 ); +sampler RandRotSampler : register( s6 ); // RandomRotation sampler +sampler FlashlightSampler : register( s7 ); +sampler ShadowDepthSampler : register( s8 ); // Flashlight shadow depth map sampler +sampler DiffuseWarpSampler : register( s9 ); // Lighting warp sampler (1D texture for diffuse lighting modification) + +struct PS_INPUT +{ + float4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0; + float3 lightAtten : TEXCOORD1; + float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3 vWorldNormal : TEXCOORD3; // World-space normal + float4 vWorldTangent : TEXCOORD4; +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float4 vProjPos : TEXCOORD5; +#else + float3 vWorldBinormal : TEXCOORD5; +#endif + float4 worldPos_projPosZ : TEXCOORD6; + float3 detailTexCoord_atten3 : TEXCOORD7; + float4 fogFactorW : COLOR1; + +#if defined( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; +#endif +#endif +}; + +// Calculate both types of Fog and lerp to get result +float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float fRangeFog = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + float fHeightFog = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + return lerp( fRangeFog, fHeightFog, fPixelFogType ); +} + +// Blend both types of Fog and lerp to get result +float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType ) +{ + pixelFogFactor = saturate( pixelFogFactor ); + float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + return lerp( fRangeResult, fHeightResult, fPixelFogType ); +} + +float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE, float fWriteDepthToDestAlpha, const float flProjZ ) +{ + float4 result = vShaderColor; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb *= LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb *= GAMMA_LIGHT_SCALE; + } + + result.a = lerp( result.a, DepthToDestAlpha( flProjZ ), fWriteDepthToDestAlpha ); + + result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType ); + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion + + return result; +} + +float4 main( PS_INPUT i ) : COLOR +{ + bool bCubemap = CUBEMAP ? true : false; + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bSelfIllumFresnel = SELFILLUMFRESNEL ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bFlashlight = (FLASHLIGHT!=0) ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + int nNumLights = NUM_LIGHTS; + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float3 vWorldBinormal = cross( i.vWorldNormal.xyz, i.vWorldTangent.xyz ) * i.vWorldTangent.w; +#else + float3 vWorldBinormal = i.vWorldBinormal; +#endif + + // Unpack four light attenuations + float4 vLightAtten = float4( i.lightAtten, i.detailTexCoord_atten3.z ); + + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + +#if DETAILTEXTURE + float4 detailColor = tex2D( DetailSampler, i.detailTexCoord_atten3.xy ); + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + + float specularFactor = 1.0f; + float4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; + + if ( bNormalMapAlphaEnvmapMask ) + specularFactor = normalTexel.a; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + + float3 worldSpaceNormal = float3( 0.0f, 0.0f, 1.0f ); + if ( bDiffuseLighting || bFlashlight || bCubemap || bSelfIllumFresnel ) + { + worldSpaceNormal = Vec3TangentToWorld( tangentSpaceNormal, i.vWorldNormal, i.vWorldTangent, vWorldBinormal ); +#if ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + worldSpaceNormal = normalize( worldSpaceNormal ); +#else + worldSpaceNormal = NormalizeWithCubemap( NormalizeSampler, worldSpaceNormal ); +#endif + } + + if ( bDiffuseLighting ) + { + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, vLightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + false, 1.0f, bDoDiffuseWarp, DiffuseWarpSampler ); + } + + float3 albedo = baseColor; + if (bBlendTintByBaseAlpha) + { + float3 tintedColor = albedo * g_DiffuseModulation.rgb; + tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_EnvmapTint_TintReplaceFactor.w); + albedo = lerp(albedo, tintedColor, baseColor.a); + } + else + { + albedo = albedo * g_DiffuseModulation.rgb; + } + + float alpha = g_DiffuseModulation.a; + if ( !bSelfIllum && !bBlendTintByBaseAlpha ) + { + alpha *= baseColor.a; + } + + +#if FLASHLIGHT + if( bFlashlight ) + { + int nShadowSampleLevel = 0; + bool bDoShadows = false; + float2 vProjPos = float2(0, 0); +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = FLASHLIGHTSHADOWS; + vProjPos = i.vProjPos.xy / i.vProjPos.w; // Screen-space position for shadow map noise +#endif + +#if defined ( _X360 ) + float4 flashlightSpacePosition = i.flashlightSpacePos; +#else + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bDoShadows, false, vProjPos, false, g_EnvmapContrast_ShadowTweaks ); + +#if defined ( _X360 ) + diffuseLighting += flashlightColor; +#else + diffuseLighting = flashlightColor; +#endif + + } +#endif + + + float3 diffuseComponent = albedo * diffuseLighting; + + +#if !FLASHLIGHT || defined ( _X360 ) + if ( bSelfIllum ) + { + #if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file + // This will apply a fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look + #if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float3 vVertexNormal = normalize( i.vWorldNormal.xyz ); + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, normalize( i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ) ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + + float3 selfIllumComponent = g_SelfIllumTint * albedo * g_SelfIllumScaleBiasExpBrightness.w; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a * saturate( flSelfIllumFresnel ) ); + #else + float3 vVertexNormal = i.vWorldNormal.xyz; + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, ( i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ) ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + + float3 selfIllumComponent = g_SelfIllumTint * albedo * g_SelfIllumScaleBiasExpBrightness.w; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a * saturate( flSelfIllumFresnel ) ); + #endif + #else + float3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + #endif + } +#endif + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); +#if !FLASHLIGHT || defined ( _X360 ) + if( bCubemap ) + { + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint_TintReplaceFactor.rgb; + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + } +#endif + + float3 result = diffuseComponent + specularLighting; + +#if defined(SHADER_MODEL_PS_2_0) + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); +#else + float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); +#endif + +#if defined( SHADER_MODEL_PS_2_0 ) + #if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; + #endif +#else // 2b or higher + alpha = lerp( alpha, fogFactor, g_fPixelFogType * g_fWriteWaterFogToDestAlpha ); // Use the fog factor if it's height fog +#endif + +#if defined( SHADER_MODEL_PS_2_0 ) + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.worldPos_projPosZ.w ); +#else + return FinalOutputConst( float4( result.rgb, alpha ), fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.worldPos_projPosZ.w ); +#endif + +} + diff --git a/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc new file mode 100644 index 00000000..06afd956 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc @@ -0,0 +1,198 @@ +//======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ====== +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_WITH_2B" "0..1" +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "FLASHLIGHT" "0..1" [XBOX] +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); // 0 & 1 +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); // 4 & 5 +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); // 6, 7, 8, 9 + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + + +//----------------------------------------------------------------------------- +// Output vertex format +//----------------------------------------------------------------------------- +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + // Stuff that is seen by the pixel shader + + float4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0; + float3 lightAtten : TEXCOORD1; + float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3 vWorldNormal : TEXCOORD3; // World-space normal + float4 vWorldTangent : TEXCOORD4; +#if USE_WITH_2B + float4 vProjPos : TEXCOORD5; +#else + float3 vWorldBinormal : TEXCOORD5; +#endif + float4 worldPos_projPosZ : TEXCOORD6; + float3 detailTexCoord_atten3 : TEXCOORD7; + float4 fogFactorW : COLOR1; + +#if defined( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; +#endif +}; + + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + o.vWorldNormal.xyz = worldNormal.xyz; + o.vWorldTangent = float4( worldTangentS.xyz, vTangent.w ); // Propagate binormal sign in world tangent.w + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + +#if USE_WITH_2B + o.vProjPos = vProjPos; +#else + o.vWorldBinormal.xyz = worldTangentT.xyz; +#endif + + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // Needed for water fog alpha and diffuse lighting + // FIXME: we shouldn't have to compute this all the time. + o.worldPos_projPosZ = float4( worldPos, vProjPos.z ); + + // Needed for cubemapping + parallax mapping + // FIXME: We shouldn't have to compute this all the time. + //o.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz = VSHADER_VECT_SCALE * (cEyePos - worldPos); + o.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz = normalize( cEyePos.xyz - worldPos.xyz ); + +#if defined( SHADER_MODEL_VS_2_0 ) && ( !USE_STATIC_CONTROL_FLOW ) + o.lightAtten.xyz = float3(0,0,0); + o.detailTexCoord_atten3.z = 0.0f; + #if ( NUM_LIGHTS > 0 ) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.detailTexCoord_atten3.z = GetVertexAttenForLight( worldPos, 3, false ); + #endif +#else + // Scalar light attenuation + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, true ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, true ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, true ); + o.detailTexCoord_atten3.z = GetVertexAttenForLight( worldPos, 3, true ); +#endif + + // Base texture coordinate transform + o.baseTexCoord2_tangentSpaceVertToEyeVectorXY.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord2_tangentSpaceVertToEyeVectorXY.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + // Detail texture coordinate transform + o.detailTexCoord_atten3.x = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.detailTexCoord_atten3.y = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); + +#if defined( _X360 ) && FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc new file mode 100644 index 00000000..1d1a47d0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc @@ -0,0 +1,484 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======// +// +//=============================================================================// +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SELFILLUM_ENVMAPMASK_ALPHA" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..9" +// STATIC: "SEAMLESS_BASE" "0..1" +// STATIC: "SEAMLESS_DETAIL" "0..1" +// STATIC: "DISTANCEALPHA" "0..1" +// STATIC: "DISTANCEALPHAFROMDETAIL" "0..1" +// STATIC: "SOFT_MASK" "0..1" +// STATIC: "OUTLINE" "0..1" +// STATIC: "OUTER_GLOW" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "DEPTHBLEND" "0..1" [ps20b] [ps30] +// STATIC: "BLENDTINTBYBASEALPHA" "0..1" +// STATIC: "SRGB_INPUT_ADAPTER" "0..1" [ps20b] +// STATIC: "CUBEMAP_SPHERE_LEGACY" "0..1" + +// DYNAMIC: "PIXELFOGTYPE" "0..1" [ps20] +// DYNAMIC: "LIGHTING_PREVIEW" "0..2" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +// detail blend mode 6 = ps20b only +// SKIP: $DETAIL_BLEND_MODE == 6 [ps20] + +// SKIP: ($DETAILTEXTURE == 0 ) && ( $DETAIL_BLEND_MODE != 0 ) +// SKIP: ($DETAILTEXTURE == 0 ) && ( $SEAMLESS_DETAIL ) +// SKIP: ($ENVMAPMASK || $SELFILLUM_ENVMAPMASK_ALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL) +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM +// SKIP: $SELFILLUM && $SELFILLUM_ENVMAPMASK_ALPHA +// SKIP: $SELFILLUM_ENVMAPMASK_ALPHA && (! $ENVMAPMASK) +// SKIP: $ENVMAPMASK && ($FLASHLIGHT || $FLASHLIGHTSHADOWS) [PC] +// SKIP: $BASEALPHAENVMAPMASK && ($SEAMLESS_BASE || $SEAMLESS_DETAIL) +// SKIP: ($DISTANCEALPHA == 0) && ($DISTANCEALPHAFROMDETAIL || $SOFT_MASK || $OUTLINE || $OUTER_GLOW) +// SKIP: ($DETAILTEXTURE == 0) && ($DISTANCEALPHAFROMDETAIL) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30] + +// DISTANCEALPHA-related skips +// SKIP: ($DISTANCEALPHA) && ($ENVMAPMASK || $BASEALPHAENVMAPMASK || $SELFILLUM || $SELFILLUM_ENVMAPMASK_ALPHA ) +// SKIP: ($DISTANCEALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL || $CUBEMAP || $LIGHTING_PREVIEW ) +// SKIP: ($DISTANCEALPHA) && ($WRITEWATERFOGTODESTALPHA || $PIXELFOGTYPE || $FLASHLIGHT || $FLASHLIGHTSHADOWS || $SRGB_INPUT_ADAPTER ) + +// SKIP: $SEAMLESS_BASE && $SRGB_INPUT_ADAPTER +// SKIP: $SEAMLESS_BASE && ($BLENDTINTBYBASEALPHA ) + +// BlendTintByBaseAlpha is incompatible with other interpretations of alpha +// SKIP: ($BLENDTINTBYBASEALPHA) && ($SELFILLUM || (($DISTANCEALPHA) && ($DISTANCEALPHAFROMDETAIL == 0)) || $BASEALPHAENVMAPMASK) + +// Only _XBOX allows flashlight and cubemap in the current implementation +// SKIP: $FLASHLIGHT && $CUBEMAP [PC] + +// SKIP: $CUBEMAP_SPHERE_LEGACY && ($CUBEMAP == 0) + +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_EnvmapTint_TintReplaceFactor : register( c0 ); +const float4 g_DiffuseModulation : register( c1 ); +const float4 g_EnvmapContrast_ShadowTweaks : register( c2 ); +const float4 g_EnvmapSaturation_SelfIllumMask : register( c3 ); +const float4 g_SelfIllumTint_and_BlendFactor : register( c4 ); + +const float4 g_ShaderControls : register( c12 ); +const float4 g_DepthFeatheringConstants : register( c13 ); + +const float4 g_EyePos : register( c20 ); +const float4 g_FogParams : register( c21 ); + +#define g_SelfIllumTint g_SelfIllumTint_and_BlendFactor.xyz +#define g_DetailBlendFactor g_SelfIllumTint_and_BlendFactor.w +#define g_EnvmapSaturation g_EnvmapSaturation_SelfIllumMask.xyz +#define g_SelfIllumMaskControl g_EnvmapSaturation_SelfIllumMask.w + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const HALF3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler DetailSampler : register( s2 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler RandRotSampler : register( s6 ); // RandomRotation sampler +sampler FlashlightSampler : register( s7 ); +sampler ShadowDepthSampler : register( s8 ); // Flashlight shadow depth map sampler +sampler DepthSampler : register( s10 ); //depth buffer sampler for depth blending +sampler SelfIllumMaskSampler : register( s11 ); // selfillummask + +struct PS_INPUT +{ +#if SEAMLESS_BASE + HALF3 baseTexCoord : TEXCOORD0; // Base texture coordinate +#else + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +#endif +#if SEAMLESS_DETAIL + HALF3 detailTexCoord : TEXCOORD1; // Seamless texture coordinate +#else + HALF2 detailTexCoord : TEXCOORD1; // Detail texture coordinate +#endif + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + float3 worldVertToEyeVector : TEXCOORD3; // Necessary for reflection + float3 worldSpaceNormal : TEXCOORD4; // Necessary for cubemaps and flashlight + +#if defined ( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; +#endif +#endif + + float4 projPos : TEXCOORD6; + float4 worldPos_projPosZ : TEXCOORD7; + float4 fogFactorW : COLOR1; +#if SEAMLESS_BASE || SEAMLESS_DETAIL + float3 SeamlessWeights : COLOR0; // x y z projection weights +#endif +}; + +const float4 g_GlowParameters : register( c5 ); +const float4 g_GlowColor : register( c6 ); +#define GLOW_UV_OFFSET g_GlowParameters.xy +#define OUTER_GLOW_MIN_DVALUE g_GlowParameters.z +#define OUTER_GLOW_MAX_DVALUE g_GlowParameters.w +#define OUTER_GLOW_COLOR g_GlowColor + +#define g_fPixelFogType g_ShaderControls.x +#define g_fWriteDepthToAlpha g_ShaderControls.y +#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z +#define g_fVertexAlpha g_ShaderControls.w + + +const float4 g_DistanceAlphaParams : register( c7 ); +#define SOFT_MASK_MAX g_DistanceAlphaParams.x +#define SOFT_MASK_MIN g_DistanceAlphaParams.y + +const float4 g_OutlineColor : register( c8 ); +#define OUTLINE_COLOR g_OutlineColor + +const float4 g_OutlineParams : register( c9 ); +// these are ordered this way for optimal ps20 swizzling +#define OUTLINE_MIN_VALUE0 g_OutlineParams.x +#define OUTLINE_MAX_VALUE1 g_OutlineParams.y +#define OUTLINE_MAX_VALUE0 g_OutlineParams.z +#define OUTLINE_MIN_VALUE1 g_OutlineParams.w + +#if DETAILTEXTURE +const float3 g_DetailTint : register( c10 ); +#endif + + +// Calculate unified fog +float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float flDepthBelowWater = fPixelFogType*fogParams.y - flWorldPosZ; // above water = negative, below water = positive + float flDepthBelowEye = fPixelFogType*flEyePosZ - flWorldPosZ; // above eye = negative, below eye = positive + // if fPixelFogType == 0, then flDepthBelowWater == flDepthBelowEye and frac will be 1 + float frac = (flDepthBelowEye == 0) ? 1 : saturate(flDepthBelowWater/flDepthBelowEye); + return saturate( min(fogParams.z, flProjPosZ * fogParams.w * frac - fogParams.x) ); +} + +// Blend both types of Fog and lerp to get result +float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType ) +{ + //float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + //float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + //return lerp( fRangeResult, fHeightResult, fPixelFogType ); + pixelFogFactor = lerp( pixelFogFactor*pixelFogFactor, pixelFogFactor, fPixelFogType ); + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor ); +} + + +float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE, float fWriteDepthToDestAlpha, const float flProjZ ) +{ + float4 result = vShaderColor; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb *= LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb *= GAMMA_LIGHT_SCALE; + } + + result.a = lerp( result.a, DepthToDestAlpha( flProjZ ), fWriteDepthToDestAlpha ); + + result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType ); + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion + + return result; +} + + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +float4 main( PS_INPUT i ) : COLOR +#endif +{ + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bHasNormal = bCubemap || bDiffuseLighting; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bVertexColor = VERTEXCOLOR ? true : false; + bool bFlashlight = FLASHLIGHT ? true : false; + bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); +#if SEAMLESS_BASE + baseColor = + i.SeamlessWeights.x * tex2D( BaseTextureSampler, i.baseTexCoord.yz )+ + i.SeamlessWeights.y * tex2D( BaseTextureSampler, i.baseTexCoord.zx )+ + i.SeamlessWeights.z * tex2D( BaseTextureSampler, i.baseTexCoord.xy ); +#else + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + +#if SRGB_INPUT_ADAPTER + baseColor.rgb = GammaToLinear( baseColor.rgb ); +#endif + +#endif // !SEAMLESS_BASE + + +#if DISTANCEALPHA && (DISTANCEALPHAFROMDETAIL == 0) + float distAlphaMask = baseColor.a; +#endif + + +#if DETAILTEXTURE +#if SEAMLESS_DETAIL + float4 detailColor = + i.SeamlessWeights.x * tex2D( DetailSampler, i.detailTexCoord.yz )+ + i.SeamlessWeights.y * tex2D( DetailSampler, i.detailTexCoord.zx )+ + i.SeamlessWeights.z * tex2D( DetailSampler, i.detailTexCoord.xy ); +#else + float4 detailColor = tex2D( DetailSampler, i.detailTexCoord.xy ); +#endif + detailColor.rgb *= g_DetailTint; + +#if DISTANCEALPHA && (DISTANCEALPHAFROMDETAIL == 1) + float distAlphaMask = detailColor.a; + detailColor.a = 1.0; // make tcombine treat as 1.0 +#endif + baseColor = + TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + +#if DISTANCEALPHA + // now, do all distance alpha effects + //if ( OUTLINE && ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) ) + //{ + // float oFactor=1.0; + // if ( distAlphaMask <= OUTLINE_MIN_VALUE1 ) + // { + // oFactor=smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask ); + // } + // else + // { + // oFactor=smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask ); + // } + // baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor ); + //} + if ( OUTLINE ) + { + float4 oFactors = smoothstep(g_OutlineParams.xyzw, g_OutlineParams.wzyx, distAlphaMask ); + baseColor = lerp( baseColor, g_OutlineColor, oFactors.x * oFactors.y ); + } + + float mskUsed; + if ( SOFT_MASK ) + { + mskUsed = smoothstep( SOFT_MASK_MIN, SOFT_MASK_MAX, distAlphaMask ); + baseColor.a *= mskUsed; + } + else + { + mskUsed = distAlphaMask >= 0.5; + if (DETAILTEXTURE ) + baseColor.a *= mskUsed; + else + baseColor.a = mskUsed; + } + + + if ( OUTER_GLOW ) + { +#if DISTANCEALPHAFROMDETAIL + float4 glowTexel = tex2D( DetailSampler, i.detailTexCoord.xy+GLOW_UV_OFFSET ); +#else + float4 glowTexel = tex2D( BaseTextureSampler, i.baseTexCoord.xy+GLOW_UV_OFFSET ); +#endif + float4 glowc = OUTER_GLOW_COLOR*smoothstep( OUTER_GLOW_MIN_DVALUE, OUTER_GLOW_MAX_DVALUE, glowTexel.a ); + baseColor = lerp( glowc, baseColor, mskUsed ); + } + +#endif // DISTANCEALPHA + + float3 specularFactor = 1.0f; + float4 envmapMaskTexel; + if( bEnvmapMask ) + { + envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord.xy ); + specularFactor *= envmapMaskTexel.xyz; + } + + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - baseColor.a; // this blows! + } + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + if( bDiffuseLighting || bVertexColor && !( bVertexColor && bDiffuseLighting ) ) + { + diffuseLighting = i.color.rgb; + } + + float3 albedo = baseColor; + if (bBlendTintByBaseAlpha) + { + float3 tintedColor = albedo * g_DiffuseModulation.rgb; + tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_EnvmapTint_TintReplaceFactor.w); + albedo = lerp(albedo, tintedColor, baseColor.a); + } + else + { + albedo = albedo * g_DiffuseModulation.rgb; + } + + float alpha = g_DiffuseModulation.a; + if ( !bBaseAlphaEnvmapMask && !bSelfIllum && !bBlendTintByBaseAlpha ) + { + alpha *= baseColor.a; + } + + + if( bFlashlight ) + { + int nShadowSampleLevel = 0; + bool bDoShadows = false; +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = true; +#endif + +#if defined ( _X360 ) + float4 flashlightSpacePosition = i.flashlightSpacePos; +#else + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + // We want the N.L to happen on the flashlight pass, but can't afford it on ps20 + bool bUseWorldNormal = true; +#if ( defined( SHADER_MODEL_PS_2_0 ) && ( DETAILTEXTURE ) ) + bUseWorldNormal = false; +#endif + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + i.worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bDoShadows, false, i.projPos.xy / i.projPos.w, false, g_EnvmapContrast_ShadowTweaks, bUseWorldNormal ); + +#if defined ( _X360 ) + diffuseLighting += flashlightColor; +#else + diffuseLighting = flashlightColor; +#endif + } + + if( bVertexColor && bDiffuseLighting ) + { + albedo *= i.color.rgb; + } + + alpha = lerp( alpha, alpha * i.color.a, g_fVertexAlpha ); + + float3 diffuseComponent = albedo * diffuseLighting; + +#if DETAILTEXTURE + diffuseComponent = + TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + +#if !FLASHLIGHT || defined ( _X360 ) + #if SELFILLUM_ENVMAPMASK_ALPHA + // range of alpha: + // 0 - 0.125 = lerp(diffuse,selfillum,alpha*8) + // 0.125-1.0 = selfillum*(1+alpha-0.125)*8 (over bright glows) + HALF3 selfIllumComponent = g_SelfIllumTint * albedo; + half Adj_Alpha=8*envmapMaskTexel.a; + diffuseComponent=( max( 0, 1-Adj_Alpha ) * diffuseComponent) + Adj_Alpha * selfIllumComponent; + #else + if ( bSelfIllum ) + { + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint * albedo, vSelfIllumMask ); + } + #endif + + if( bCubemap ) + { +#if CUBEMAP_SPHERE_LEGACY + HALF3 reflectVect = normalize(CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector.xyz )); + + specularLighting = 0.5 * tex2D( EnvmapSampler, float2(reflectVect.x, reflectVect.y) ) * g_DiffuseModulation.rgb * diffuseLighting; +#else + HALF3 reflectVect = CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint_TintReplaceFactor.rgb; + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); +#endif + } +#endif + + HALF3 result = diffuseComponent + specularLighting; + +#if LIGHTING_PREVIEW +# if LIGHTING_PREVIEW == 1 + float dotprod=0.7+0.25*dot(i.worldSpaceNormal,normalize(float3(1,2,-.5))); + return FinalOutput( float4( dotprod*albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +# else + LPREVIEW_PS_OUT ret; + ret.flags=float4(1,1,1,1); + ret.color=float4( albedo.xyz, alpha ); + ret.normal=float4(i.worldSpaceNormal,alpha); + ret.position=float4(i.worldPos_projPosZ.xyz, alpha); + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +# endif +#else + +# if (DEPTHBLEND == 1) + { + float2 vScreenPos; + vScreenPos.x = i.projPos.x; + vScreenPos.y = -i.projPos.y; + vScreenPos = (vScreenPos + i.projPos.w) * 0.5f; + alpha *= DepthFeathering( DepthSampler, vScreenPos / i.projPos.w, i.projPos.w - i.projPos.z, i.projPos.w, g_DepthFeatheringConstants ); + } +# endif + +#if defined( SHADER_MODEL_PS_2_0 ) + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.projPos.z ); + #if (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = lerp( alpha, fogFactor, g_fWriteWaterFogToDestAlpha ); + #endif + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.projPos.z ); +#else // 2b or higher + float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.projPos.z ); + alpha = lerp( alpha, fogFactor, g_fWriteWaterFogToDestAlpha ); // Use the fog factor if it's height fog + return FinalOutputConst( float4( result.rgb, alpha ), fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.projPos.z ); +#endif + +#endif +} + diff --git a/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc new file mode 100644 index 00000000..9db6f864 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc @@ -0,0 +1,249 @@ +//======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== + +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SEAMLESS_BASE" "0..1" +// STATIC: "SEAMLESS_DETAIL" "0..1" +// STATIC: "SEPARATE_DETAIL_UVS" "0..1" +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] +// STATIC: "DONT_GAMMA_CONVERT_VERTEX_COLOR" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] +// SKIP: ($SEPARATE_DETAIL_UVS) && ($SEAMLESS_DETAIL) +// SKIP: ($DONT_GAMMA_CONVERT_VERTEX_COLOR && ( ! $VERTEXCOLOR ) ) +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; +static const bool g_bCubemap = CUBEMAP ? true : false; +static const bool g_bFlashlight = FLASHLIGHT ? true : false; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +#if (defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL) +static const bool g_bDecalOffset = true; +#else +static const bool g_bDecalOffset = false; +#endif + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +#if SEAMLESS_DETAIL || SEAMLESS_BASE +const float cSeamlessScale : register( SHADER_SPECIFIC_CONST_2); +#define SEAMLESS_SCALE cSeamlessScale.x +#endif + +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#if defined ( _X360 ) +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); // 6, 7, 8, 9 +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; +#endif + +#if SEAMLESS_BASE + HALF3 SeamlessTexCoord : TEXCOORD0; // Base texture x/y/z (indexed by swizzle) +#else + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +#endif +#if SEAMLESS_DETAIL + HALF3 SeamlessDetailTexCoord : TEXCOORD1; // Detail texture coordinate +#else + HALF2 detailTexCoord : TEXCOORD1; // Detail texture coordinate +#endif + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + +#if CUBEMAP || _X360 + float3 worldVertToEyeVector : TEXCOORD3; // Necessary for cubemaps +#endif + + float3 worldSpaceNormal : TEXCOORD4; // Necessary for cubemaps and flashlight + +#if defined ( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; +#endif + + float4 vProjPos : TEXCOORD6; + float4 worldPos_ProjPosZ : TEXCOORD7; + float4 fogFactorW : COLOR1; +#if SEAMLESS_DETAIL || SEAMLESS_BASE + float3 SeamlessWeights : COLOR0; // x y z projection weights +#endif + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + bool bDoLighting = !g_bVertexColor && (bDynamicLight || bStaticLight); + + float4 vPosition = v.vPos; + float3 vNormal = 0; + if ( bDoLighting || FLASHLIGHT || SEAMLESS_BASE || SEAMLESS_DETAIL || LIGHTING_PREVIEW || g_bDecalOffset || CUBEMAP ) + { + // The vertex only contains valid normals if they are actually needed (fetching them when absent makes D3D complain) + DecompressVertex_Normal( v.vNormal, vNormal ); + } + +#if SEAMLESS_BASE || SEAMLESS_DETAIL + // compute blend weights in rgb + float3 NNormal=normalize( vNormal ); + o.SeamlessWeights.xyz = NNormal * NNormal; // sums to 1. +#endif + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal ); +#endif + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + if ( !g_bVertexColor ) + { + worldNormal = normalize( worldNormal ); + } + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + o.worldSpaceNormal = worldNormal; + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.vProjPos = vProjPos; + o.fogFactorW.w = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW.w; +#endif + o.worldPos_ProjPosZ.xyz = worldPos.xyz; + o.worldPos_ProjPosZ.w = vProjPos.z; + + // Needed for cubemaps +#if CUBEMAP + o.worldVertToEyeVector.xyz = VSHADER_VECT_SCALE * (cEyePos - worldPos); +#endif + +#if !defined (_X360) && FLASHLIGHT + o.color = float4( 0.0f, 0.0f, 0.0f, 0.0f ); +#else + if ( g_bVertexColor ) + { + // Assume that this is unlitgeneric if you are using vertex color. + o.color.rgb = ( DONT_GAMMA_CONVERT_VERTEX_COLOR ) ? v.vColor.rgb : GammaToLinear( v.vColor.rgb ); + o.color.a = v.vColor.a; + } + else + { + #if ( ( USE_STATIC_CONTROL_FLOW ) || defined ( SHADER_MODEL_VS_3_0 ) ) + { + o.color.xyz = DoLighting( worldPos, worldNormal, v.vSpecular, bStaticLight, bDynamicLight, g_bHalfLambert ); + } + #else + { + o.color.xyz = DoLightingUnrolled( worldPos, worldNormal, v.vSpecular, bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); + } + #endif + } +#endif + + +#if SEAMLESS_BASE + o.SeamlessTexCoord.xyz = SEAMLESS_SCALE * v.vPos.xyz; +#else + // Base texture coordinates + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); +#endif + +#if SEAMLESS_DETAIL + // FIXME: detail texcoord as a 2d xform doesn't make much sense here, so I just do enough so + // that scale works. More smartness could allow 3d xform. + o.SeamlessDetailTexCoord.xyz = (SEAMLESS_SCALE*cDetailTexCoordTransform[0].x) * v.vPos.xyz; +#else + // Detail texture coordinates + // FIXME: This shouldn't have to be computed all the time. + o.detailTexCoord.x = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.detailTexCoord.y = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); +#endif + +#if SEPARATE_DETAIL_UVS + o.detailTexCoord.xy = v.vTexCoord1.xy; +#endif + +#if LIGHTING_PREVIEW + float dot=0.5+0.5*worldNormal*float3(0.7071,0.7071,0); + o.color.xyz=float3(dot,dot,dot); +#endif + +#if defined ( _X360 ) && FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + return o; +} + + diff --git a/mp/src/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc b/mp/src/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc new file mode 100644 index 00000000..52812637 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc @@ -0,0 +1,68 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "HALFLAMBERT" "0..1" + +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_OverbrightFactor : register( c4 ); +const float3 cAmbientCube[6] : register( c6 ); + +PixelShaderLightInfo cLightInfo[3] : register(c13); + +sampler BumpmapSampler : register( s0 ); +sampler NormalizeSampler : register( s1 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. + float2 detailOrBumpTexCoord : TEXCOORD1; + // bump mapping and a separate envmap mask texture are mutually exclusive. + float2 envmapMaskTexCoord : TEXCOORD2; + float3 worldVertToEyeVector : TEXCOORD3; + float3x3 tangentSpaceTranspose : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vLightAtten = float4( i.lightAtten01, i.lightAtten23 ); + + float3 tangentSpaceNormal = float3( 0.0f, 0.0f, 1.0f ); + float4 normalTexel = 1.0f; + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + + normalTexel = tex2D( BumpmapSampler, i.detailOrBumpTexCoord ); + tangentSpaceNormal = 2.0f * normalTexel - 1.0f; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + if( bDiffuseLighting ) + { + float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal ); + float3 staticLightingColor = float3( 0.0f, 0.0f, 0.0f ); + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, + vLightAtten, cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + false, 0, false, NormalizeSampler ); + // multiply by .5 since we want a 50% (in gamma space) reflective surface) + diffuseLighting *= pow( 0.5f, 2.2f ); + } + + return FinalOutput( float4( diffuseLighting, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/mp/src/materialsystem/stdshaders/vertexlit_notexture.psh b/mp/src/materialsystem/stdshaders/vertexlit_notexture.psh new file mode 100644 index 00000000..8b550bde --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlit_notexture.psh @@ -0,0 +1,13 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +mov r0, v0 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_basealphamaskedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_basealphamaskedenvmap.psh new file mode 100644 index 00000000..5faa681d --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_basealphamaskedenvmap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask (in alpha channel) + +mul r0, t0, c3 ; base times modulation +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailbasealphamaskedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailbasealphamaskedenvmap.psh new file mode 100644 index 00000000..ab653f19 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailbasealphamaskedenvmap.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask (in alpha channel) +tex t3 ; detail texture + +mul r0, t0, c3 ; base times modulation +mul_x2 r0.rgb, r0, t3 ; detail texture +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailenvmap.psh new file mode 100644 index 00000000..ac030f0a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailenvmap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t3 ; detail texture + +mul r0, t0, c3 ; base times modulation +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailmaskedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailmaskedenvmap.psh new file mode 100644 index 00000000..51873a08 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailmaskedenvmap.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +mul r0, t0, c3 ; Base times modulation +mul_x2 r0.rgb, r0, t3 ; detail texture +mul r1, t1, t2 ; Envmap * mask +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedenvmap.psh new file mode 100644 index 00000000..44dee8d4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedenvmap.psh @@ -0,0 +1,28 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +tex t1 +tex t3 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedmaskedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedmaskedenvmap.psh new file mode 100644 index 00000000..4be599ca --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedmaskedenvmap.psh @@ -0,0 +1,29 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask +tex t3 ; Detail + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx6.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx6.cpp new file mode 100644 index 00000000..8ecd111f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx6.cpp @@ -0,0 +1,421 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX6 ) + +BEGIN_SHADER( VertexLitGeneric_DX6, + "Help for VertexLitGeneric_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No envmap uses mode 0, it's one less pass + // Also, if multipass = 0, then go to mode 0 also + if ( ( !params[ENVMAP]->IsDefined() ) || + ( !IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ENVMAPMODE ); + } + + // Vertex color requires mode 1 + if ( IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPMODE ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if ( IS_FLAG_SET(MATERIAL_VAR_DECAL) ) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_SOFTWARE_LIGHTING ); + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + } + + int GetDrawFlagsPass1(IMaterialVar** params) + { + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_COLOR; + if (params[BASETEXTURE]->IsTexture()) + flags |= SHADER_DRAW_TEXCOORD0; + return flags; + } + + void DrawVertexLightingOnly( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + + SetModulationShadowState(); + SetDefaultBlendingShadowState( ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetModulationDynamicState(); + } + Draw(); + } + + void MultiplyByVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + // FIXME: How to deal with texture alpha?? + + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, false ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + + // NOTE: We're not doing lightmapping here, but we want to use the + // same blend mode as we used for lightmapping + pShaderShadow->EnableBlending( true ); + SingleTextureLightmapBlendMode(); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + + // This here will perform color = vertex light * (cc alpha) + 1 * (1 - cc alpha) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_BLEND_CONSTANTALPHA, + SHADER_TEXARG_VERTEXCOLOR, SHADER_TEXARG_CONSTANTCOLOR ); + + // Alpha isn't used, it doesn't matter what we set it to. + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_NONE, SHADER_TEXARG_NONE ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR ); + FogToOOOverbright(); + } + DYNAMIC_STATE + { + // Put the alpha in the color channel to modulate the color down.... + float alpha = GetAlpha(); + pShaderAPI->Color4f( OO_OVERBRIGHT, OO_OVERBRIGHT, OO_OVERBRIGHT, alpha ); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( false ); + } + } + + + //----------------------------------------------------------------------------- + // Used by mode 1 + //----------------------------------------------------------------------------- + + void DrawBaseTimesVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Base times vertex lighting, no vertex color + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + + // Independenly configure alpha and color + + // Color = Color mod * Vertex Light * Tex (x2) + // Alpha = Constant Alpha * Tex Alpha (no tex alpha if self illum == 1) + // Can't have color modulation here + pShaderShadow->EnableConstantColor( IsColorModulating() ); + + // Independenly configure alpha and color + pShaderShadow->EnableAlphaPipe( true ); + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) ); + + if (!IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && !IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, true ); + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetModulationDynamicState(); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableAlphaPipe( false ); + } + } + + //----------------------------------------------------------------------------- + // Envmap times vertex lighting, no vertex color + //----------------------------------------------------------------------------- + + void DrawEnvmapTimesVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + int materialVarFlags = params[FLAGS]->GetIntValue(); + + // alpha test + pShaderShadow->EnableAlphaTest( false ); + + int flags = SetShadowEnvMappingState( ENVMAPMASK ) | SHADER_DRAW_COLOR; + bool hasEnvMapMask = params[ENVMAPMASK]->IsTexture(); + + pShaderShadow->OverbrightValue( hasEnvMapMask ? + SHADER_TEXTURE_STAGE1 : SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + + // Independenly configure alpha and color + + // Color = Env map * Vertex Light * Envmapmask (x2) + // Alpha = Constant Alpha * Vertex light alpha * Env Map mask Alpha + pShaderShadow->EnableConstantColor( IsColorModulating() ); + + pShaderShadow->EnableAlphaPipe( true ); + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + pShaderShadow->EnableVertexAlpha( (materialVarFlags & MATERIAL_VAR_VERTEXALPHA) != 0 ); + if (hasEnvMapMask) + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, true ); + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetDynamicEnvMappingState( ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( false ); + pShaderShadow->EnableAlphaPipe( false ); + } + } + + void DrawMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + bool texDefined = params[BASETEXTURE]->IsTexture(); + bool envDefined = params[ENVMAP]->IsTexture(); +// bool maskDefined = params[ENVMAPMASK]->IsTexture(); + + // Pass 1 : Base + env + + // FIXME: Could make it 1 pass for base + env, if it wasn't + // for the envmap tint. So this is 3 passes for now.... + + // If it's base + mask * env, gotta do that in 2 passes + // Gotta do funky stuff to fade out self-illuminated stuff + bool hasEnvMapTint = !IsWhite(ENVMAPTINT); + + // Special case, can do in one pass + if (!hasEnvMapTint && !texDefined && !IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) && + !IsColorModulating() ) + { + DrawEnvmapTimesVertexLighting( params, pShaderAPI, pShaderShadow ); + return; + } + + if (texDefined) + { + FixedFunctionBaseTimesDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + else + { + FixedFunctionMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + + // We can get here if multipass isn't set if we specify a vertex color + if ( IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) + { + if ( texDefined && envDefined ) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + + // Pass 2 : * vertex lighting + MultiplyByVertexLighting( params, pShaderAPI, pShaderShadow ); + + // FIXME: We could add it to the lightmap + // Draw the selfillum pass (blows away envmap at self-illum points) + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + + void DrawMode0( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Pass 1 : Base * lightmap or just lightmap + if ( params[BASETEXTURE]->IsTexture() ) + { + DrawBaseTimesVertexLighting( params, pShaderAPI, pShaderShadow ); + + // Detail map + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Draw the selfillum pass + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + else + { + DrawVertexLightingOnly( params, pShaderAPI, pShaderShadow ); + + // Detail map + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + + // Pass 2 : Masked environment map + if ( params[ENVMAP]->IsTexture() && + (IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) ) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + + SHADER_DRAW + { + bool useMode1 = IS_FLAG_SET(MATERIAL_VAR_ENVMAPMODE); + if (!useMode1) + { + // Base * Vertex Lighting + env + DrawMode0( params, pShaderAPI, pShaderShadow ); + } + else + { + // ( Base + env ) * Vertex Lighting + DrawMode1( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx7.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx7.cpp new file mode 100644 index 00000000..7a114a56 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx7.cpp @@ -0,0 +1,413 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX7 ) +DEFINE_FALLBACK_SHADER( Skin_DX9, VertexLitGeneric_DX7 ) + +BEGIN_SHADER( VertexLitGeneric_DX7, + "Help for VertexLitGeneric_DX7" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ); + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 70) + return "VertexLitGeneric_DX6"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + } + + void DrawBaseTimesVertexColor( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableCustomPixelPipe( true ); + + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_VERTEXCOLOR ); + + // Get alpha from the texture so that alpha blend and alpha test work properly. + bool bTextureIsTranslucent = TextureIsTranslucent( BASETEXTURE, true ); + if ( bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + } + else + { + if ( IsAlphaModulating() ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_ONE, SHADER_TEXARG_NONE ); + } + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_NORMAL | SHADER_DRAW_TEXCOORD0; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + + if ( IsAlphaModulating() || IsColorModulating() ) + { + pShaderShadow->CustomTextureStages( 2 ); + + if ( IsColorModulating() ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + + // Get alpha from the texture so that alpha blend and alpha test work properly. + if ( IsAlphaModulating() && bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + } + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetModulationDynamicState(); + } + Draw(); + } + + void DrawVertexColorNoBase( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( true ); + + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_ONE, SHADER_TEXARG_VERTEXCOLOR ); + + int flags = SHADER_DRAW_POSITION; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { +// SetModulationDynamicState(); + } + Draw(); + } + + void DrawBaseTimesBakedVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ); + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int flags = SHADER_DRAW_POSITION; + if (params[BASETEXTURE]->IsTexture()) + { + flags |= SHADER_DRAW_TEXCOORD1; + } + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_SPECULARCOLOR, SHADER_TEXARG_TEXTURE ); + + // Get alpha from the texture so that alpha blend and alpha test work properly. + bool bTextureIsTranslucent = TextureIsTranslucent( BASETEXTURE, true ); + if ( bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + } + else + { + if ( IsAlphaModulating() ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_ONE, SHADER_TEXARG_NONE ); + } + } + + if ( IsAlphaModulating() || IsColorModulating() ) + { + pShaderShadow->CustomTextureStages( 2 ); + + if ( IsColorModulating()) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + + // Get alpha from the texture so that alpha blend and alpha test work properly. + if ( IsAlphaModulating() && bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + } + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE1, BASETEXTURETRANSFORM ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetModulationDynamicState(); + } + Draw(); + } + + void DrawBakedVertexLightingNoBase( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + int flags = SHADER_DRAW_POSITION; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_SPECULARCOLOR, SHADER_TEXARG_NONE ); + + // Alpha isn't used, it doesn't matter what we set it to. + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_NONE, SHADER_TEXARG_NONE ); + } + DYNAMIC_STATE + { + } + Draw(); + } + + SHADER_DRAW + { + bool bBakedLighting = IS_FLAG2_SET( MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING ); + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + return; + } + // Pass 1 : Base * lightmap or just lightmap + if ( params[BASETEXTURE]->IsTexture() ) + { + // Draw base times lighting. + // Lighting is either sent down per vertex from the app, or it's in the second + // stream as color values. + if( bBakedLighting ) + { + DrawBaseTimesBakedVertexLighting( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawBaseTimesVertexColor( params, pShaderAPI, pShaderShadow ); + } + + // Detail map + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Draw the selfillum pass + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + else + { + if( bBakedLighting ) + { + DrawBakedVertexLightingNoBase( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawVertexColorNoBase( params, pShaderAPI, pShaderShadow ); + } + + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + + + // Pass 2 : Masked environment map + if ( params[ENVMAP]->IsTexture() && (IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) ) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx8.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx8.cpp new file mode 100644 index 00000000..31addf42 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx8.cpp @@ -0,0 +1,807 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "vertexlitgeneric_vs11.inc" +#include "vertexlitgeneric_selfillumonly.inc" +#include "emissive_scroll_blended_pass_helper.h" +#include "flesh_interior_blended_pass_helper.h" +#include "cloak_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX8 ) +DEFINE_FALLBACK_SHADER( Skin_DX9, VertexLitGeneric_DX8 ) + +BEGIN_VS_SHADER( VertexLitGeneric_DX8, + "Help for VertexLitGeneric" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + SHADER_PARAM( FORCEBUMP, SHADER_PARAM_TYPE_BOOL, "0", "0 == Do bumpmapping if the card says it can handle it. 1 == Always do bumpmapping." ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + // Color Replacement Pass + SHADER_PARAM( BLENDTINTBYBASEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use the base alpha to blend in the $color modulation") + SHADER_PARAM( BLENDTINTCOLOROVERBASE, SHADER_PARAM_TYPE_FLOAT, "0", "blend between tint acting as a multiplication versus a replace" ) + + END_SHADER_PARAMS + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + // Delete these lines if not bump mapping! + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = EMISSIVEBLENDBASETEXTURE; + info.m_nFlowTexture = -1; // Not used in DX8 + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + info.m_nTime = TIME; + } + + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + // We don't want no stinking bump mapping on models in dx8. + // Wait a minute! We want specular bump. .need to make that work by itself. +// params[BUMPMAP]->SetUndefined(); +// if( IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) ) +// { +// CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); +// params[ENVMAP]->SetUndefined(); +// } + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + if( !params[DETAILBLENDFACTOR]->IsDefined() ) + params[DETAILBLENDFACTOR]->SetFloatValue( 1.0f ); + + if( !params[DETAILBLENDMODE]->IsDefined() ) + params[DETAILBLENDMODE]->SetFloatValue( 0 ); + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + + if( !params[ENVMAPSATURATION]->IsDefined() ) + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPFRAME]->IsDefined() ) + params[ENVMAPFRAME]->SetIntValue( 0 ); + + if( !params[BUMPFRAME]->IsDefined() ) + params[BUMPFRAME]->SetIntValue( 0 ); + + if( !params[ALPHATESTREFERENCE]->IsDefined() ) + params[ALPHATESTREFERENCE]->SetFloatValue( 0.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If a bumpmap is defined but an envmap isn't, then ignore the bumpmap. + // It was meant to be used with diffuse + if ( !params[ENVMAP]->IsDefined() ) + { + params[BUMPMAP]->SetUndefined(); + } + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + // Color Replacement Pass + if ( !params[BLENDTINTBYBASEALPHA]->IsDefined() ) + { + params[BLENDTINTBYBASEALPHA]->SetIntValue(0); + } + + if ( !params[BLENDTINTCOLOROVERBASE]->IsDefined() ) + { + params[BLENDTINTCOLOROVERBASE]->SetFloatValue(0); + } + } + + SHADER_FALLBACK + { + if ( IsPC() ) + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 70) + return "VertexLitGeneric_DX6"; + + if ( g_pHardwareConfig->GetDXSupportLevel() < 80) + return "VertexLitGeneric_DX7"; + + if ( g_pHardwareConfig->PreferReducedFillrate() ) + return "VertexLitGeneric_NoBump_DX8"; + } + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + if (g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined()) + { + LoadBumpMap( BUMPMAP ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + LoadCubeMap( ENVMAP ); + } + else + { + LoadTexture( ENVMAP ); + } + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + { + LoadTexture( ENVMAPMASK ); + } + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + } + + inline const char *GetUnbumpedPixelShaderName( IMaterialVar** params, bool bSkipEnvmap ) + { + static char const* s_pPixelShaders[] = + { + "VertexLitGeneric_EnvmapV2", + "VertexLitGeneric_SelfIlluminatedEnvmapV2", + + "VertexLitGeneric_BaseAlphaMaskedEnvmapV2", + "VertexLitGeneric_SelfIlluminatedEnvmapV2", + + // Env map mask + "VertexLitGeneric_MaskedEnvmapV2", + "VertexLitGeneric_SelfIlluminatedMaskedEnvmapV2", + + "VertexLitGeneric_MaskedEnvmapV2", + "VertexLitGeneric_SelfIlluminatedMaskedEnvmapV2", + + // Detail + "VertexLitGeneric_DetailEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedEnvmapV2", + + "VertexLitGeneric_DetailBaseAlphaMaskedEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedEnvmapV2", + + // Env map mask + "VertexLitGeneric_DetailMaskedEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedMaskedEnvmapV2", + + "VertexLitGeneric_DetailMaskedEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedMaskedEnvmapV2", + }; + + if ( !params[BASETEXTURE]->IsTexture() ) + { + if (params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + if (!params[ENVMAPMASK]->IsTexture()) + { + return "VertexLitGeneric_EnvmapNoTexture"; + } + else + { + return "VertexLitGeneric_MaskedEnvmapNoTexture"; + } + } + else + { + if ( params[DETAIL]->IsTexture() ) + { + return "VertexLitGeneric_DetailNoTexture"; + } + else + { + return "VertexLitGeneric_NoTexture"; + } + } + } + else + { + if ( params[BLENDTINTBYBASEALPHA]->GetIntValue() ) + { + return "VertexLitGeneric_BlendTint"; + } + else if ( params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + int pshIndex = 0; + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + pshIndex |= 0x1; + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pshIndex |= 0x2; + if (params[ENVMAPMASK]->IsTexture()) + pshIndex |= 0x4; + if (params[DETAIL]->IsTexture()) + pshIndex |= 0x8; + return s_pPixelShaders[pshIndex]; + } + else + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + { + if ( params[DETAIL]->IsTexture() ) + return "VertexLitGeneric_DetailSelfIlluminated"; + else + return "VertexLitGeneric_SelfIlluminated"; + } + else if ( params[DETAIL]->IsTexture() ) + { + switch( params[DETAILBLENDMODE]->GetIntValue() ) + { + case 0: + return "VertexLitGeneric_Detail"; + + case 1: // additive modes + return "VertexLitGeneric_Detail_Additive"; + + case 5: + case 6: + return "VertexLitGeneric_Detail_Additive_selfillum"; + break; + + default: + return "VertexLitGeneric_Detail_LerpBase"; + } + } + else + { + return "VertexLitGeneric"; + } + } + } + } + + void DrawUnbumpedUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bSkipEnvmap ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + if ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + + // FIXME: We could enable this, but we'd never get it working on dx7 or lower + // FIXME: This isn't going to work until we make more vertex shaders that + // pass the vertex color and alpha values through. +#if 0 + if ( IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) || IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ) ) + fmt |= VERTEX_COLOR; +#endif + + if (params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + // envmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // envmapmask on stage 2 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + } + + if (params[BASETEXTURE]->IsTexture()) + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetDefaultBlendingShadowState( ENVMAPMASK, false ); + } + + if ( params[DETAIL]->IsTexture()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // Set up the vertex shader index. + vertexlitgeneric_vs11_Static_Index vshIndex; + vshIndex.SetHALF_LAMBERT( IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + //vshIndex.SetDETAIL( params[DETAIL]->IsTexture() ); + if( params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + vshIndex.SetENVMAP( true ); + vshIndex.SetENVMAPCAMERASPACE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ); + if( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ) + { + vshIndex.SetENVMAPSPHERE( false ); + } + else + { + vshIndex.SetENVMAPSPHERE( IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ) ); + } + } + else + { + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + } + pShaderShadow->SetVertexShader( "vertexlitgeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetUnbumpedPixelShaderName( params, bSkipEnvmap ); + pShaderShadow->SetPixelShader( pshName ); + DefaultFog(); + pShaderShadow->EnableAlphaWrites( true ); + } + DYNAMIC_STATE + { + if (params[BASETEXTURE]->IsTexture()) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + +// if (params[ENVMAP]->IsTexture()) + if (params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + BindTexture( SHADER_SAMPLER1, ENVMAP, ENVMAPFRAME ); + + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + if (params[ENVMAPMASK]->IsTexture() ) + BindTexture( SHADER_SAMPLER2, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || + IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + SetEnvMapTintPixelShaderDynamicState( 2, ENVMAPTINT, -1 ); + } + + if ( params[DETAIL]->IsTexture()) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + } + + SetAmbientCubeDynamicStateVertexShader(); + SetModulationPixelShaderDynamicState( 3 ); + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + + if ( params[DETAIL]->IsTexture() && ( ! IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) ) ) + { + float c1[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c1[0] = c1[1] = c1[2] = c1[3] = params[DETAILBLENDFACTOR]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, c1, 1 ); + } + + if ( params[BLENDTINTBYBASEALPHA]->GetIntValue() ) + { + float c1[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c1[0] = c1[1] = c1[2] = c1[3] = params[BLENDTINTCOLOROVERBASE]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, c1 ); + } + + vertexlitgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetLIGHT_COMBO( pShaderAPI->GetCurrentLightCombo() ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + if( pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA ) ) + { + pShaderAPI->SetPixelShaderIndex( 0 ); + } + else + { + // write 255 to alpha if we aren't told to write depth to dest alpha (We don't ever actually write depth to dest alpha in dx8) + pShaderAPI->SetPixelShaderIndex( 1 ); + float c4[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + pShaderAPI->SetPixelShaderConstant( 4, c4, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( false/*disabled! no effect*/ && params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + // There is some strangeness in DX8 when trying to skip the main pass, so leave this alone for now + //bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + // FLASHLIGHTFIXME: need to make these the same. + bool hasFlashlight = UsingFlashlight( params ); + bool bBump = g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsTexture(); + + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, false, false, 0, -1, -1 ); + } + else if( bBump ) + { + bool bSkipEnvmap = true; + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bSkipEnvmap ); + + // specular pass + bool bBlendSpecular = true; + if( params[ENVMAP]->IsTexture() ) + { + DrawModelBumpedSpecularLighting( BUMPMAP, BUMPFRAME, ENVMAP, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, BUMPTRANSFORM, bBlendSpecular ); + } + } + else + { + bool bSkipEnvmap = false; + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bSkipEnvmap ); + } + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// Version that doesn't do bumpmapping +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( VertexLitGeneric_NoBump_DX8, VertexLitGeneric_DX8, + "Help for VertexLitGeneric_NoBump_DX8" ) + + SHADER_FALLBACK + { + if (g_pConfig->bSoftwareLighting) + return "VertexLitGeneric_DX6"; + + if (!g_pHardwareConfig->SupportsVertexAndPixelShaders()) + return "VertexLitGeneric_DX7"; + + return 0; + } + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + if ( !g_pConfig->UseBumpmapping() ) + return false; + + if ( !params[BUMPMAP]->IsDefined() ) + return false; + + return ( params[FORCEBUMP]->GetIntValue() != 0 ); + } + +END_INHERITED_SHADER + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp new file mode 100644 index 00000000..47105813 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp @@ -0,0 +1,520 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=====================================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "emissive_scroll_blended_pass_helper.h" +#include "cloak_blended_pass_helper.h" +#include "flesh_interior_blended_pass_helper.h" +#include "weapon_sheen_pass_helper.h" + + +BEGIN_VS_SHADER( VertexLitGeneric, "Help for VertexLitGeneric" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( COMPRESS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "compression wrinklemap" ) + SHADER_PARAM( STRETCH, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "expansion wrinklemap" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPCOMPRESS, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "compression bump map" ) + SHADER_PARAM( BUMPSTRETCH, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "expansion bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( SELFILLUM_ENVMAPMASK_ALPHA, SHADER_PARAM_TYPE_FLOAT,"0.0","defines that self illum value comes from env map mask alpha" ) + SHADER_PARAM( SELFILLUMFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "Self illum fresnel" ) + SHADER_PARAM( SELFILLUMFRESNELMINMAXEXP, SHADER_PARAM_TYPE_VEC4, "0", "Self illum fresnel min, max, exp" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( FLASHLIGHTNOLAMBERT, SHADER_PARAM_TYPE_BOOL, "0", "Flashlight pass sets N.L=1.0" ) + + // Debugging term for visualizing ambient data on its own + SHADER_PARAM( AMBIENTONLY, SHADER_PARAM_TYPE_INTEGER, "0", "Control drawing of non-ambient light ()" ) + + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "warp the specular term" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + SHADER_PARAM( BASEMAPALPHAPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "indicates that there is no normal map and that the phong mask is in base alpha" ) + SHADER_PARAM( INVERTPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "invert the phong mask (0=full phong, 1=no phong)" ) + SHADER_PARAM( ENVMAPFRESNEL, SHADER_PARAM_TYPE_FLOAT, "0", "Degree to which Fresnel should be applied to env map" ) + SHADER_PARAM( SELFILLUMMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "If we bind a texture here, it overrides base alpha (if any) for self illum" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + + // Rim lighting terms + SHADER_PARAM( RIMLIGHT, SHADER_PARAM_TYPE_BOOL, "0", "enables rim lighting" ) + SHADER_PARAM( RIMLIGHTEXPONENT, SHADER_PARAM_TYPE_FLOAT, "4.0", "Exponent for rim lights" ) + SHADER_PARAM( RIMLIGHTBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Boost for rim lights" ) + SHADER_PARAM( RIMMASK, SHADER_PARAM_TYPE_BOOL, "0", "Indicates whether or not to use alpha channel of exponent texture to mask the rim term" ) + + // Seamless mapping scale + SHADER_PARAM( SEAMLESS_BASE, SHADER_PARAM_TYPE_BOOL, "0", "whether to apply seamless mapping to the base texture. requires a smooth model." ) + SHADER_PARAM( SEAMLESS_DETAIL, SHADER_PARAM_TYPE_BOOL, "0", "where to apply seamless mapping to the detail texture." ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "the scale for the seamless mapping. # of repetions of texture per inch." ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Weapon Sheen Pass + SHADER_PARAM( SHEENPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables weapon sheen render in a second pass" ) + SHADER_PARAM( SHEENMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "sheenmap" ) + SHADER_PARAM( SHEENMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "sheenmap mask" ) + SHADER_PARAM( SHEENMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( SHEENMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "sheenmap tint" ) + SHADER_PARAM( SHEENMAPMASKSCALEX, SHADER_PARAM_TYPE_FLOAT, "1", "X Scale the size of the map mask to the size of the target" ) + SHADER_PARAM( SHEENMAPMASKSCALEY, SHADER_PARAM_TYPE_FLOAT, "1", "Y Scale the size of the map mask to the size of the target" ) + SHADER_PARAM( SHEENMAPMASKOFFSETX, SHADER_PARAM_TYPE_FLOAT, "0", "X Offset of the mask relative to model space coords of target" ) + SHADER_PARAM( SHEENMAPMASKOFFSETY, SHADER_PARAM_TYPE_FLOAT, "0", "Y Offset of the mask relative to model space coords of target" ) + SHADER_PARAM( SHEENMAPMASKDIRECTION, SHADER_PARAM_TYPE_INTEGER, "0", "The direction the sheen should move (length direction of weapon) XYZ, 0,1,2" ) + SHADER_PARAM( SHEENINDEX, SHADER_PARAM_TYPE_INTEGER, "0", "Index of the Effect Type (Color Additive, Override etc...)" ) + + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_BOOL, "0", "Use texcoord1 for detail texture" ) + SHADER_PARAM( LINEARWRITE, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of shader results." ) + SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries. Only supported without bumpmaps" ) + SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) + + SHADER_PARAM( BLENDTINTBYBASEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use the base alpha to blend in the $color modulation") + SHADER_PARAM( BLENDTINTCOLOROVERBASE, SHADER_PARAM_TYPE_FLOAT, "0", "blend between tint acting as a multiplication versus a replace" ) + END_SHADER_PARAMS + + void SetupVars( VertexLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nWrinkle = COMPRESS; + info.m_nStretch = STRETCH; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nNormalWrinkle = BUMPCOMPRESS; + info.m_nNormalStretch = BUMPSTRETCH; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nFlashlightNoLambert = FLASHLIGHTNOLAMBERT; + + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nSelfIllumEnvMapMask_Alpha = SELFILLUM_ENVMAPMASK_ALPHA; + info.m_nSelfIllumFresnel = SELFILLUMFRESNEL; + info.m_nSelfIllumFresnelMinMaxExp = SELFILLUMFRESNELMINMAXEXP; + + info.m_nAmbientOnly = AMBIENTONLY; + info.m_nPhongExponent = PHONGEXPONENT; + info.m_nPhongExponentTexture = PHONGEXPONENTTEXTURE; + info.m_nPhongTint = PHONGTINT; + info.m_nPhongAlbedoTint = PHONGALBEDOTINT; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + info.m_nPhongWarpTexture = PHONGWARPTEXTURE; + info.m_nPhongBoost = PHONGBOOST; + info.m_nPhongFresnelRanges = PHONGFRESNELRANGES; + info.m_nPhong = PHONG; + info.m_nBaseMapAlphaPhongMask = BASEMAPALPHAPHONGMASK; + info.m_nEnvmapFresnel = ENVMAPFRESNEL; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + // Rim lighting parameters + info.m_nRimLight = RIMLIGHT; + info.m_nRimLightPower = RIMLIGHTEXPONENT; + info.m_nRimLightBoost = RIMLIGHTBOOST; + info.m_nRimMask = RIMMASK; + + // seamless + info.m_nSeamlessScale = SEAMLESS_SCALE; + info.m_nSeamlessDetail = SEAMLESS_DETAIL; + info.m_nSeamlessBase = SEAMLESS_BASE; + + info.m_nSeparateDetailUVs = SEPARATEDETAILUVS; + + info.m_nLinearWrite = LINEARWRITE; + info.m_nDetailTint = DETAILTINT; + info.m_nInvertPhongMask = INVERTPHONGMASK; + + info.m_nDepthBlend = DEPTHBLEND; + info.m_nDepthBlendScale = DEPTHBLENDSCALE; + + info.m_nSelfIllumMask = SELFILLUMMASK; + info.m_nBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA; + info.m_nTintReplacesBaseColor = BLENDTINTCOLOROVERBASE; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + // Delete these lines if not bump mapping! + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + // Weapon Sheen Pass + void SetupVarsWeaponSheenPass( WeaponSheenPassVars_t &info ) + { + info.m_nSheenMap = SHEENMAP; + info.m_nSheenMapMask = SHEENMAPMASK; + info.m_nSheenMapMaskFrame = SHEENMAPMASKFRAME; + info.m_nSheenMapTint = SHEENMAPTINT; + info.m_nSheenMapMaskScaleX = SHEENMAPMASKSCALEX; + info.m_nSheenMapMaskScaleY = SHEENMAPMASKSCALEY; + info.m_nSheenMapMaskOffsetX = SHEENMAPMASKOFFSETX; + info.m_nSheenMapMaskOffsetY = SHEENMAPMASKOFFSETY; + info.m_nSheenMapMaskDirection = SHEENMAPMASKDIRECTION; + info.m_nSheenIndex = SHEENINDEX; + + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + if ( params[SHEENPASSENABLED]->GetIntValue() ) // If material supports weapon sheen + return true; + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = EMISSIVEBLENDBASETEXTURE; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + info.m_nTime = TIME; + } + + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, true, vars ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Sheen Pass + if ( !params[SHEENPASSENABLED]->IsDefined() ) + { + params[SHEENPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[SHEENPASSENABLED]->GetIntValue() ) + { + WeaponSheenPassVars_t info; + SetupVarsWeaponSheenPass( info ); + InitParamsWeaponSheenPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 70) + return "VertexLitGeneric_DX6"; + + if (g_pHardwareConfig->GetDXSupportLevel() < 80) + return "VertexLitGeneric_DX7"; + + if (g_pHardwareConfig->GetDXSupportLevel() < 90) + return "VertexLitGeneric_DX8"; + + return 0; + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, true, vars ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // TODO : Only do this if we're in range of the camera + // Weapon Sheen + if ( params[SHEENPASSENABLED]->GetIntValue() ) + { + WeaponSheenPassVars_t info; + SetupVarsWeaponSheenPass( info ); + InitWeaponSheenPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, true, vars, vertexCompression, pContextDataPtr ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Weapon sheen pass + // only if doing standard as well (don't do it if cloaked) + if ( params[SHEENPASSENABLED]->GetIntValue() ) + { + WeaponSheenPassVars_t info; + SetupVarsWeaponSheenPass( info ); + if ( ( pShaderShadow != NULL ) || ( bDrawStandardPass && ShouldDrawMaterialSheen( params, info ) ) ) + { + DrawWeaponSheenPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx95_helper.h b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx95_helper.h new file mode 100644 index 00000000..3736bfe8 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx95_helper.h @@ -0,0 +1,71 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VERTEXLITGENERIC_DX95_HELPER_H +#define VERTEXLITGENERIC_DX95_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VertexLitGeneric_DX95_Vars_t +{ + VertexLitGeneric_DX95_Vars_t() { memset( this, 0xFF, sizeof(VertexLitGeneric_DX95_Vars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTexture2; + int m_nBaseTextureFrame2; + int m_nBaseTexture3; + int m_nBaseTextureFrame3; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nSelfIllumTint; + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpmap2; + int m_nBumpFrame2; + int m_nBumpMask; + int m_nBumpmap3; + int m_nBumpFrame3; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nAlphaTestReference; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + int m_nSelfIllumEnvMapMask_Alpha; + +}; + +void InitParamsVertexLitGeneric_DX95( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX95_Vars_t &info ); +void InitVertexLitGeneric_DX95( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX95_Vars_t &info ); +void DrawVertexLitGeneric_DX95( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bVertexLitGeneric, VertexLitGeneric_DX95_Vars_t &info ); + + +#endif // VERTEXLITGENERIC_DX95_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp new file mode 100644 index 00000000..b1f49eab --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp @@ -0,0 +1,1434 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "skin_dx9_helper.h" + +#include "VertexLit_and_unlit_Generic_vs20.inc" +#include "VertexLit_and_unlit_Generic_bump_vs20.inc" + +#include "vertexlit_and_unlit_generic_ps20.inc" +#include "vertexlit_and_unlit_generic_ps20b.inc" +#include "vertexlit_and_unlit_generic_bump_ps20.inc" +#include "vertexlit_and_unlit_generic_bump_ps20b.inc" + +#ifndef _X360 +#include "vertexlit_and_unlit_generic_vs30.inc" +#include "vertexlit_and_unlit_generic_ps30.inc" +#include "vertexlit_and_unlit_generic_bump_vs30.inc" +#include "vertexlit_and_unlit_generic_bump_ps30.inc" +#endif + +#include "commandbuilder.h" +#include "convar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity","0", FCVAR_CHEAT ); + + +static inline bool WantsSkinShader( IMaterialVar** params, const VertexLitGeneric_DX9_Vars_t &info ) +{ + if ( info.m_nPhong == -1) // Don't use skin without Phong + return false; + + if ( params[info.m_nPhong]->GetIntValue() == 0 ) // Don't use skin without Phong turned on + return false; + + if ( ( info.m_nDiffuseWarpTexture != -1 ) && params[info.m_nDiffuseWarpTexture]->IsTexture() ) // If there's Phong and diffuse warp do skin + return true; + + if ( ( info.m_nBaseMapAlphaPhongMask != -1 ) && params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 1 ) + { + if ( info.m_nBumpmap == -1 ) // Don't use without a bump map + return false; + + if ( !params[info.m_nBumpmap]->IsTexture() ) // Don't use if the texture isn't specified + return false; + } + + return true; +} + +int g_nSnapShots; + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ) +{ + InitIntParam( info.m_nPhong, params, 0 ); + + InitFloatParam( info.m_nAlphaTestReference, params, 0.0f ); + InitIntParam( info.m_nVertexAlphaTest, params, 0 ); + + InitIntParam( info.m_nFlashlightNoLambert, params, 0 ); + + if ( info.m_nDetailTint != -1 && !params[info.m_nDetailTint]->IsDefined() ) + { + params[info.m_nDetailTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if ( info.m_nEnvmapTint != -1 && !params[info.m_nEnvmapTint]->IsDefined() ) + { + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + InitIntParam( info.m_nEnvmapFrame, params, 0 ); + InitIntParam( info.m_nBumpFrame, params, 0 ); + InitFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + InitIntParam( info.m_nReceiveFlashlight, params, 0 ); + + InitFloatParam( info.m_nDetailScale, params, 4.0f ); + + if ( (info.m_nBlendTintByBaseAlpha != -1) && (!params[info.m_nBlendTintByBaseAlpha]->IsDefined()) ) + { + params[info.m_nBlendTintByBaseAlpha]->SetIntValue( 0 ); + } + + InitFloatParam( info.m_nTintReplacesBaseColor, params, 0 ); + + if ( (info.m_nSelfIllumTint != -1) && (!params[info.m_nSelfIllumTint]->IsDefined()) ) + { + params[info.m_nSelfIllumTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + + if ( WantsSkinShader( params, info ) ) + { + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() || !g_pConfig->UsePhong() ) + { + params[info.m_nPhong]->SetIntValue( 0 ); + } + else + { + InitParamsSkin_DX9( pShader, params, pMaterialName, info ); + return; + } + } + + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + if ( info.m_nFlashlightTexture != -1 ) + { + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + } + + // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping. + if ( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if ( bVertexLitGeneric ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + else + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + InitIntParam( info.m_nEnvmapMaskFrame, params, 0 ); + InitFloatParam( info.m_nEnvmapContrast, params, 0.0 ); + InitFloatParam( info.m_nEnvmapSaturation, params, 1.0f ); + InitFloatParam( info.m_nSeamlessScale, params, 0.0 ); + + // handle line art parms + InitFloatParam( info.m_nEdgeSoftnessStart, params, 0.5 ); + InitFloatParam( info.m_nEdgeSoftnessEnd, params, 0.5 ); + InitFloatParam( info.m_nGlowAlpha, params, 1.0 ); + InitFloatParam( info.m_nOutlineAlpha, params, 1.0 ); + + // No texture means no self-illum or env mask in base alpha + if ( info.m_nBaseTexture != -1 && !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + if( ( (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) + // we don't need a tangent space if we have envmap without bumpmap + // || ( info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() ) + ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) // diffuse warp goes down bump path... + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else // no tangent space needed + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } + + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + if ( hasNormalMapAlphaEnvmapMask ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ) && info.m_nBumpmap != -1 && + params[info.m_nBumpmap]->IsDefined() && !hasNormalMapAlphaEnvmapMask ) + { + Warning( "material %s has a normal map and $basealphaenvmapmask. Must use $normalmapalphaenvmapmask to get specular.\n\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + if ( !hasNormalMapAlphaEnvmapMask ) + { + Warning( "material %s has a normal map and an envmapmask. Must use $normalmapalphaenvmapmask.\n\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + } + + // If mat_specular 0, then get rid of envmap + if ( !g_pConfig->UseSpecular() && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nEnvmap]->SetUndefined(); + } + + InitFloatParam( info.m_nHDRColorScale, params, 1.0f ); + + InitIntParam( info.m_nLinearWrite, params, 0 ); + InitIntParam( info.m_nGammaColorRead, params, 0 ); + + InitIntParam( info.m_nDepthBlend, params, 0 ); + InitFloatParam( info.m_nDepthBlendScale, params, 50.0f ); +} + + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- + +void InitVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ) +{ + // both detailed and bumped = needs skin shader (for now) + bool bNeedsSkinBecauseOfDetail = false; + + //bool bHasBump = ( info.m_nBumpmap != -1 ) && params[info.m_nBumpmap]->IsTexture(); + //if ( bHasBump ) + //{ + // if ( ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsDefined() ) + // bNeedsSkinBecauseOfDetail = true; + //} + + if ( bNeedsSkinBecauseOfDetail || + ( info.m_nPhong != -1 && + params[info.m_nPhong]->GetIntValue() && + g_pHardwareConfig->SupportsPixelShaders_2_b() ) ) + { + InitSkin_DX9( pShader, params, info ); + return; + } + + if ( info.m_nFlashlightTexture != -1 ) + { + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + } + + bool bIsBaseTextureTranslucent = false; + if ( info.m_nBaseTexture != -1 && params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, ( info.m_nGammaColorRead != -1 ) && ( params[info.m_nGammaColorRead]->GetIntValue() == 1 ) ? 0 : TEXTUREFLAGS_SRGB ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + } + + bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsDefined(); + + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + // Can still be self illum with no base alpha if using one of these alternate modes + if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() ) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + if ( nDetailBlendMode == 0 ) //Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail, TEXTUREFLAGS_SRGB ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + else if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if ( info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() ) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + else + { + pShader->LoadTexture( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + + if ( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + } + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + if ( bHasSelfIllumMask ) + { + pShader->LoadTexture( info.m_nSelfIllumMask ); + } +} + +class CVertexLitGeneric_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; + +}; + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + bool bVertexLitGeneric, bool bHasFlashlight, + VertexLitGeneric_DX9_Vars_t &info, + VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) + +{ + CVertexLitGeneric_DX9_Context *pContextData = reinterpret_cast< CVertexLitGeneric_DX9_Context *> ( *pContextDataPtr ); + +/*^*/ // printf("\t\t>DrawVertexLitGeneric_DX9_Internal\n"); + + bool bHasBump = IsTextureSet( info.m_nBumpmap, params ); +#if !defined( _X360 ) + bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); +#endif + + bool hasDiffuseLighting = bVertexLitGeneric; +/*^*/ // printf("\t\t[%d] bVertexLitGeneric\n",(int)bVertexLitGeneric); + + if ( IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + bHasFlashlight = false; + } + + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bHasDiffuseWarp = (!bHasFlashlight || IsX360() ) && hasDiffuseLighting && (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + + + //bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL ); + bool bFlashlightNoLambert = false; + if ( ( info.m_nFlashlightNoLambert != -1 ) && params[info.m_nFlashlightNoLambert]->GetIntValue() ) + { + bFlashlightNoLambert = true; + } + + bool bAmbientOnly = IsBoolSet( info.m_nAmbientOnly, params ); + + float fBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + bool bHasDetailTexture = IsTextureSet( info.m_nDetail, params ); + int nDetailBlendMode = bHasDetailTexture ? GetIntParam( info.m_nDetailTextureCombineMode, params ) : 0; + int nDetailTranslucencyTexture = -1; + + if ( bHasDetailTexture ) + { + if ( ( nDetailBlendMode == 6 ) && ( ! (g_pHardwareConfig->SupportsPixelShaders_2_b() ) ) ) + { + nDetailBlendMode = 5; // skip fancy threshold blending if ps2.0 + } + if ( ( nDetailBlendMode == 3 ) || ( nDetailBlendMode == 8 ) || ( nDetailBlendMode == 9 ) ) + nDetailTranslucencyTexture = info.m_nDetail; + } + + bool bBlendTintByBaseAlpha = IsBoolSet( info.m_nBlendTintByBaseAlpha, params ); + float fTintReplaceFactor = GetFloatParam( info.m_nTintReplacesBaseColor, params, 0.0 ); + + BlendType_t nBlendType; + bool bHasBaseTexture = IsTextureSet( info.m_nBaseTexture, params ); + if ( bHasBaseTexture ) + { + // if base alpha is used for tinting, ignore the base texture for computing translucency + nBlendType = pShader->EvaluateBlendRequirements( bBlendTintByBaseAlpha ? -1 : info.m_nBaseTexture, true, nDetailTranslucencyTexture ); + } + else + { + nBlendType = pShader->EvaluateBlendRequirements( info.m_nEnvmapMask, false ); + } + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && (!bHasFlashlight || IsX360() ); //dest alpha is free for special use + + bool bHasEnvmap = (!bHasFlashlight || IsX360() ) && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsTexture(); + + + bool bHasVertexColor = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); +/*^*/ // printf("\t\t[%d] bHasVertexColor\n",(int)bHasVertexColor); +/*^*/ // printf("\t\t[%d] bHasVertexAlpha\n",(int)bHasVertexAlpha); + + if ( pShader->IsSnapshotting() || (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) + { +/*^*/ // printf("\t\t[1] snapshotting=%d pContextData=%08x pContextData->m_bMaterialVarsChanged=%d \n",(int)pShader->IsSnapshotting(), (int)pContextData, pContextData ? (int)pContextData->m_bMaterialVarsChanged : -1 ); + bool bSeamlessBase = IsBoolSet( info.m_nSeamlessBase, params ); + bool bSeamlessDetail = IsBoolSet( info.m_nSeamlessDetail, params ); + bool bDistanceAlpha = IsBoolSet( info.m_nDistanceAlpha, params ); + bool bHasSelfIllum = (!bHasFlashlight || IsX360() ) && IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + bool bHasEnvmapMask = (!bHasFlashlight || IsX360() ) && info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsTexture(); + bool bHasSelfIllumFresnel = ( !IsTextureSet( info.m_nDetail, params ) ) && ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + bool bHasSelfIllumMask = bHasSelfIllum && IsTextureSet( info.m_nSelfIllumMask, params ); + bool hasSelfIllumInEnvMapMask = + ( info.m_nSelfIllumEnvMapMask_Alpha != -1 ) && + ( params[info.m_nSelfIllumEnvMapMask_Alpha]->GetFloatValue() != 0.0 ) ; + + if ( pShader->IsSnapshotting() ) + { +/*^*/ // printf("\t\t[2] snapshotting...\n"); + + bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + + if ( info.m_nVertexAlphaTest != -1 && params[info.m_nVertexAlphaTest]->GetIntValue() > 0 ) + { + bHasVertexAlpha = true; + } + + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + if ( bHasSelfIllumFresnel ) + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + hasNormalMapAlphaEnvmapMask = false; + } + + bool bHasEnvmap = (!bHasFlashlight || IsX360() ) && ( info.m_nEnvmap != -1 ) && params[info.m_nEnvmap]->IsTexture(); + bool bHasLegacyEnvSphereMap = bHasEnvmap && IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE); + bool bHasNormal = bVertexLitGeneric || bHasEnvmap || bHasFlashlight || bSeamlessBase || bSeamlessDetail; + if ( IsPC() ) + { + // On PC, LIGHTING_PREVIEW requires normals (they won't use much memory - unlitgeneric isn't used on many models) + bHasNormal = true; + } + + bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ); + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if ( bHasFlashlight ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + if ( !IsX360() ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + else + { + pShader->SetAdditiveBlendingShadowState( info.m_nEnvmapMask, false ); + } + + if ( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + } + else + { + pShader->SetBlendingShadowState( nBlendType ); + } + } + else + { + pShader->SetBlendingShadowState( nBlendType ); + } + + unsigned int flags = VERTEX_POSITION; + if ( bHasNormal ) + { + flags |= VERTEX_NORMAL; + } +/*^*/ // printf("\t\t[%1d] VERTEX_NORMAL\n",(flags&VERTEX_NORMAL)!=0); + + int userDataSize = 0; + bool bSRGBInputAdapter = false; + + // basetexture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + if ( bHasBaseTexture ) + { + if ( ( info.m_nGammaColorRead != -1 ) && ( params[info.m_nGammaColorRead]->GetIntValue() == 1 ) ) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + else + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + // If we're on OSX GL on a crappy OS which can't do sRGB from render targets, check to see if we're reading from one... + if ( IsOSX() && !g_pHardwareConfig->CanDoSRGBReadFromRTs() ) + { + ITexture *pBaseTexture = params[info.m_nBaseTexture]->GetTextureValue(); + if ( pBaseTexture && pBaseTexture->IsRenderTarget() ) + { + bSRGBInputAdapter = true; + } + } + } + + if ( bHasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + } + if ( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Depth texture + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER8 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true ); + userDataSize = 4; // tangent S + } + + if ( bHasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + + if ( bHasBump || bHasDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + userDataSize = 4; // tangent S + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + if ( bHasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + if ( bHasVertexColor || bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } +/*^*/ // printf("\t\t[%1d] VERTEX_COLOR\n",(flags&VERTEX_COLOR)!=0); +/*^*/ // printf("\t\t[%1d] VERTEX_COLOR_STREAM_1\n",(flags&VERTEX_COLOR_STREAM_1)!=0); + + + if( bHasDiffuseWarp && (!bHasFlashlight || IsX360() ) && !bHasSelfIllumFresnel ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Diffuse warp texture + } + + if ( (info.m_nDepthBlend != -1) && (params[info.m_nDepthBlend]->GetIntValue()) ) + { + if( bHasBump ) + Warning( "DEPTHBLEND not supported by bump mapped variations of vertexlitgeneric to avoid shader bloat. Either remove the bump map or convince a graphics programmer that it's worth it.\n" ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); + } + + if( bHasSelfIllum ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // self illum mask + } + + bool bSRGBWrite = true; + if( (info.m_nLinearWrite != -1) && (params[info.m_nLinearWrite]->GetIntValue() == 1) ) + { + bSRGBWrite = false; + } + + pShaderShadow->EnableSRGBWrite( bSRGBWrite ); + + // texcoord0 : base texcoord + int pTexCoordDim[3] = { 2, 2, 3 }; + int nTexCoordCount = 1; + + if ( IsBoolSet( info.m_nSeparateDetailUVs, params ) ) + { + ++nTexCoordCount; + } + else + { + pTexCoordDim[1] = 0; + } + +#ifndef _X360 + // Special morphed decal information + if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; +/*^*/ // printf("\t\t[%1d] VERTEX_FORMAT_COMPRESSED\n",(flags&VERTEX_FORMAT_COMPRESSED)!=0); + +/*^*/ // printf("\t\t -> CShaderShadowDX8::VertexShaderVertexFormat( flags=%08x, texcount=%d )\n",flags,nTexCoordCount); + + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + if ( bHasBump || bHasDiffuseWarp ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER_COMBO( USE_WITH_2B, g_pHardwareConfig->SupportsPixelShaders_2_b() ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); +#endif + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL this way + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + } + else // ps_2_0 + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER_COMBO( USE_WITH_2B, true ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + } +#endif + } + else // !(bHasBump || bHasDiffuseWarp) + { + bool bDistanceAlphaFromDetail = false; + bool bSoftMask = false; + bool bGlow = false; + bool bOutline = false; + + static ConVarRef mat_reduceparticles( "mat_reduceparticles" ); + bool bDoDepthBlend = IsBoolSet( info.m_nDepthBlend, params ) && !mat_reduceparticles.GetBool(); + + if ( bDistanceAlpha ) + { + bDistanceAlphaFromDetail = IsBoolSet( info.m_nDistanceAlphaFromDetail, params ); + bSoftMask = IsBoolSet( info.m_nSoftEdges, params ); + bGlow = IsBoolSet( info.m_nGlow, params ); + bOutline = IsBoolSet( info.m_nOutline, params ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_VERTEX_SHADER_COMBO( SEPARATE_DETAIL_UVS, IsBoolSet( info.m_nSeparateDetailUVs, params ) ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER_COMBO( DONT_GAMMA_CONVERT_VERTEX_COLOR, (! bSRGBWrite ) && bHasVertexColor ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send Gl this way + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, ( hasSelfIllumInEnvMapMask && ( bHasEnvmapMask ) ) ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP_SPHERE_LEGACY, bHasLegacyEnvSphereMap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDoDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB_INPUT_ADAPTER, bSRGBInputAdapter ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + } + else // ps_2_0 + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, ( hasSelfIllumInEnvMapMask && ( bHasEnvmapMask ) ) ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP_SPHERE_LEGACY, bHasLegacyEnvSphereMap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_VERTEX_SHADER_COMBO( SEPARATE_DETAIL_UVS, IsBoolSet( info.m_nSeparateDetailUVs, params ) ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER_COMBO( DONT_GAMMA_CONVERT_VERTEX_COLOR, bSRGBWrite ? 0 : 1 ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, ( hasSelfIllumInEnvMapMask && ( bHasEnvmapMask ) ) ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP_SPHERE_LEGACY, bHasLegacyEnvSphereMap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDoDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + } +#endif + } + + if ( bHasFlashlight && !IsX360() ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff and the loadout and character select screens. + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + + if ( pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) ) + { +/*^*/ // printf("\t\t[3] pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) TRUE \n"); + if ( ! pContextData ) // make sure allocated + { + ++g_nSnapShots; + pContextData = new CVertexLitGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFogParams( 21 ); + if ( bHasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + if( bHasEnvmap ) + { + // if we only have an envmap (no basetexture), then we want the albedo to be black. + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + } + if ( bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nDetail, info.m_nDetailFrame ); + } + if ( bHasSelfIllum ) + { + if ( bHasSelfIllumMask ) // Separate texture for self illum? + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nSelfIllumMask, -1 ); // Bind it + } + else // else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER11, TEXTURE_BLACK ); // Bind dummy + } + } + + if ( (info.m_nDepthBlend != -1) && (params[info.m_nDepthBlend]->GetIntValue()) ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + if ( bSeamlessDetail || bSeamlessBase ) + { + float flSeamlessData[4]={ params[info.m_nSeamlessScale]->GetFloatValue(), + 0,0,0}; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, flSeamlessData ); + } + + if ( info.m_nBaseTextureTransform != -1 ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + } + + + if ( bHasDetailTexture ) + { + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nDetailTextureTransform, info.m_nDetailScale ); + else + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBaseTextureTransform, info.m_nDetailScale ); + //Assert( !bHasBump ); + if ( info.m_nDetailTint != -1 ) + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstantGammaToLinear( 10, info.m_nDetailTint ); + else + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 10, 1, 1, 1, 1 ); + } + } + if ( bDistanceAlpha ) + { + float flSoftStart = GetFloatParam( info.m_nEdgeSoftnessStart, params ); + float flSoftEnd = GetFloatParam( info.m_nEdgeSoftnessEnd, params ); + // set all line art shader parms + bool bScaleEdges = IsBoolSet( info.m_nScaleEdgeSoftnessBasedOnScreenRes, params ); + bool bScaleOutline = IsBoolSet( info.m_nScaleOutlineSoftnessBasedOnScreenRes, params ); + + float flResScale = 1.0; + + float flOutlineStart0 = GetFloatParam( info.m_nOutlineStart0, params ); + float flOutlineStart1 = GetFloatParam( info.m_nOutlineStart1, params ); + float flOutlineEnd0 = GetFloatParam( info.m_nOutlineEnd0, params ); + float flOutlineEnd1 = GetFloatParam( info.m_nOutlineEnd1, params ); + + if ( bScaleEdges || bScaleOutline ) + { + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + flResScale=max( 0.5, max( 1024.0/nWidth, 768/nHeight ) ); + + if ( bScaleEdges ) + { + float flMid = 0.5 * ( flSoftStart + flSoftEnd ); + flSoftStart = clamp( flMid + flResScale * ( flSoftStart - flMid ), 0.05, 0.99 ); + flSoftEnd = clamp( flMid + flResScale * ( flSoftEnd - flMid ), 0.05, 0.99 ); + } + + + if ( bScaleOutline ) + { + // shrink the soft part of the outline, enlarging hard part + float flMidS = 0.5 * ( flOutlineStart1 + flOutlineStart0 ); + flOutlineStart1 = clamp( flMidS + flResScale * ( flOutlineStart1 - flMidS ), 0.05, 0.99 ); + float flMidE = 0.5 * ( flOutlineEnd1 + flOutlineEnd0 ); + flOutlineEnd1 = clamp( flMidE + flResScale * ( flOutlineEnd1 - flMidE ), 0.05, 0.99 ); + } + + } + + float flConsts[]={ + // c5 - glow values + GetFloatParam( info.m_nGlowX, params ), + GetFloatParam( info.m_nGlowY, params ), + GetFloatParam( info.m_nGlowStart, params ), + GetFloatParam( info.m_nGlowEnd, params ), + // c6 - glow color + 0,0,0, // will be filled in + GetFloatParam( info.m_nGlowAlpha, params ), + // c7 - mask range parms + flSoftStart, + flSoftEnd, + 0,0, + // c8 - outline color + 0,0,0, + GetFloatParam( info.m_nOutlineAlpha, params ), + // c9 - outline parms. ordered for optimal ps20 .wzyx swizzling + flOutlineStart0, + flOutlineEnd1, + flOutlineEnd0, + flOutlineStart1, + }; + + if ( info.m_nGlowColor != -1 ) + { + params[info.m_nGlowColor]->GetVecValue( flConsts+4, 3 ); + } + if ( info.m_nOutlineColor != -1 ) + { + params[info.m_nOutlineColor]->GetVecValue( flConsts+12, 3 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 5, flConsts, 5 ); + + } + if ( !g_pConfig->m_bFastNoBump ) + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + } + else if ( bHasDiffuseWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + else + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + // Setting w to 1 means use separate selfillummask + float vEnvMapSaturation_SelfIllumMask[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + if ( info.m_nEnvmapSaturation != -1 ) + params[info.m_nEnvmapSaturation]->GetVecValue( vEnvMapSaturation_SelfIllumMask, 3 ); + + vEnvMapSaturation_SelfIllumMask[3] = bHasSelfIllumMask ? 1.0f : 0.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 3, vEnvMapSaturation_SelfIllumMask, 1 ); + if ( bHasEnvmap ) + { + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicStateGammaToLinear( 0, info.m_nEnvmapTint, fTintReplaceFactor ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicStateGammaToLinear( 0, -1, fTintReplaceFactor); + } + + if ( bHasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if ( bHasSelfIllumFresnel && (!bHasFlashlight || IsX360() ) ) + { + float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f; + float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f; + float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f; + + vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias + vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale + vConstScaleBiasExp[2] = flExp; // Exp + vConstScaleBiasExp[3] = flMax; // Brightness + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 11, vConstScaleBiasExp ); + } + + if( bHasDiffuseWarp && (!bHasFlashlight || IsX360() ) && !bHasSelfIllumFresnel ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, info.m_nDiffuseWarpTexture, -1 ); + } + } + + if ( bHasFlashlight ) + { + // Tweaks associated with a given flashlight + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + float tweaks[4]; + tweaks[0] = flashlightState.m_flShadowFilterSize / flashlightState.m_flShadowMapResolution; + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( 2, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( 31, vScreenScale, 1 ); + } + + if ( ( !bHasFlashlight || IsX360() ) && ( info.m_nEnvmapContrast != -1 ) ) + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + + // mat_fullbright 2 handling + bool bLightingOnly = bVertexLitGeneric && mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + if ( bHasBaseTexture ) + { + if( ( bHasSelfIllum && !hasSelfIllumInEnvMapMask ) ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + } + if ( bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + } + + if ( bHasBump || bHasDiffuseWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderStateAmbientLightCube( 5 ); + pContextData->m_SemiStaticCmdsOut.CommitPixelShaderLighting( 13 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( 4, info.m_nSelfIllumTint, fBlendFactor ); + pContextData->m_SemiStaticCmdsOut.SetAmbientCubeDynamicStateVertexShader(); + pContextData->m_SemiStaticCmdsOut.End(); + } + } + if ( pShaderAPI ) + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + if ( bHasEnvmap ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + bool bFlashlightShadows = false; + if ( bHasFlashlight ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER8, pFlashlightDepthTexture, 0 ); + DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER6, TEXTURE_SHADOW_NOISE_2D ); + } + + SetFlashLightColorFromState( state, pShaderAPI, 28, bFlashlightNoLambert ); + + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER7, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + } + + + // Set up light combo state + LightState_t lightState = {0, false, false}; + if ( bVertexLitGeneric && (!bHasFlashlight || IsX360() ) ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + if ( bHasBump || bHasDiffuseWarp ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_vs20 ); + + // Bind ps_2_b shader so we can get shadow mapping... + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL this way + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + else // !( bHasBump || bHasDiffuseWarp ) + { + if ( bAmbientOnly ) // Override selected light combo to be ambient only + { + lightState.m_bAmbientLight = true; + lightState.m_bStaticLight = false; + lightState.m_nNumLights = 0; + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( + LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_vs20 ); + + // Bind ps_2_b shader so we can get shadow mapping + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL this way + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( + LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( + LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + + if ( ( info.m_nHDRColorScale != -1 ) && pShader->IsHDREnabled() ) + { + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() ); + } + else + { + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + } + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + DynamicCmdsOut.SetPixelShaderConstant( 20, eyePos ); + + // Non-bump case does its own depth feathering work + if ( !bHasBump && !bHasDiffuseWarp ) + { + DynamicCmdsOut.SetDepthFeatheringPixelShaderConstant( 13, GetFloatParam( info.m_nDepthBlendScale, params, 50.0f ) ); + } + + float fPixelFogType = pShaderAPI->GetPixelFogCombo() == 1 ? 1 : 0; + float fWriteDepthToAlpha = bWriteDepthToAlpha && IsPC() ? 1 : 0; + float fWriteWaterFogToDestAlpha = (pShaderAPI->GetPixelFogCombo() == 1 && bWriteWaterFogToAlpha) ? 1 : 0; + float fVertexAlpha = bHasVertexAlpha ? 1 : 0; + + // Controls for lerp-style paths through shader code (bump and non-bump have use different register) + float vShaderControls[4] = { fPixelFogType, fWriteDepthToAlpha, fWriteWaterFogToDestAlpha, fVertexAlpha }; + DynamicCmdsOut.SetPixelShaderConstant( 12, vShaderControls, 1 ); + + // flashlightfixme: put this in common code. + if ( bHasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, 28, bFlashlightNoLambert ); + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 ); + + pShader->BindTexture( SHADER_SAMPLER7, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + float atten_pos[8]; + atten_pos[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten_pos[1] = flashlightState.m_fLinearAtten; + atten_pos[2] = flashlightState.m_fQuadraticAtten; + atten_pos[3] = flashlightState.m_FarZ; + atten_pos[4] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + atten_pos[5] = flashlightState.m_vecLightOrigin[1]; + atten_pos[6] = flashlightState.m_vecLightOrigin[2]; + atten_pos[7] = 1.0f; + DynamicCmdsOut.SetPixelShaderConstant( 22, atten_pos, 2 ); + + DynamicCmdsOut.SetPixelShaderConstant( 24, worldToTexture.Base(), 4 ); + } + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); + +/*^*/ // printf("\t\tSupportsPixelShaders_2_b() && g_pConfig->UseBumpmapping() && g_pConfig->UsePhong() ) + { + DrawSkin_DX9( pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + return; + } + + bool bReceiveFlashlight = bVertexLitGeneric; + bool bNewFlashlight = IsX360(); + if ( bNewFlashlight ) + { + bReceiveFlashlight = bReceiveFlashlight || ( GetIntParam( info.m_nReceiveFlashlight, params ) != 0 ); + } + bool bHasFlashlight = bReceiveFlashlight && pShader->UsingFlashlight( params ); + + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, info, vertexCompression, pContextDataPtr ); +} diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h new file mode 100644 index 00000000..0b5b02e4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h @@ -0,0 +1,144 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VERTEXLITGENERIC_DX9_HELPER_H +#define VERTEXLITGENERIC_DX9_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VertexLitGeneric_DX9_Vars_t +{ + VertexLitGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); } + + int m_nBaseTexture; + int m_nWrinkle; + int m_nStretch; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nNormalWrinkle; + int m_nNormalStretch; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nAlphaTestReference; + int m_nVertexAlphaTest; + int m_nFlashlightNoLambert; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + + int m_nSelfIllumTint; + int m_nSelfIllumFresnel; + int m_nSelfIllumFresnelMinMaxExp; + + int m_nPhongExponent; + int m_nPhongTint; + int m_nPhongAlbedoTint; + int m_nPhongExponentTexture; + int m_nDiffuseWarpTexture; + int m_nPhongWarpTexture; + int m_nPhongBoost; + int m_nPhongFresnelRanges; + int m_nSelfIllumEnvMapMask_Alpha; + int m_nAmbientOnly; + int m_nHDRColorScale; + int m_nPhong; + int m_nBaseMapAlphaPhongMask; + int m_nEnvmapFresnel; + + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + + // Rim lighting parameters + int m_nRimLight; + int m_nRimLightPower; + int m_nRimLightBoost; + int m_nRimMask; + + int m_nSeamlessScale; + int m_nSeamlessBase; + int m_nSeamlessDetail; + + // distance coded line art parameters + int m_nDistanceAlpha; + int m_nDistanceAlphaFromDetail; + + int m_nSoftEdges; + int m_nEdgeSoftnessStart; + int m_nEdgeSoftnessEnd; + int m_nScaleEdgeSoftnessBasedOnScreenRes; + + int m_nGlow; + int m_nGlowColor; + int m_nGlowAlpha; + int m_nGlowStart; + int m_nGlowEnd; + int m_nGlowX; + int m_nGlowY; + int m_nOutline; + int m_nOutlineColor; + int m_nOutlineAlpha; + int m_nOutlineStart0; + int m_nOutlineStart1; + int m_nOutlineEnd0; + int m_nOutlineEnd1; + int m_nScaleOutlineSoftnessBasedOnScreenRes; + + int m_nSeparateDetailUVs; + int m_nDetailTextureTransform; + + int m_nLinearWrite; + int m_nGammaColorRead; + + int m_nDetailTint; + int m_nInvertPhongMask; + + int m_nDepthBlend; + int m_nDepthBlendScale; + + int m_nSelfIllumMask; + int m_nReceiveFlashlight; + + int m_nBlendTintByBaseAlpha; + + int m_nTintReplacesBaseColor; + +}; + +void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); +void InitVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); +void DrawVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr + ); + + +#endif // VERTEXLITGENERIC_DX9_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_envmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_envmap.psh new file mode 100644 index 00000000..e539da67 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_envmap.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map + +mul r0, t0, c3 ; base times modulation +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh new file mode 100644 index 00000000..a5810b5e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh @@ -0,0 +1,137 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" +# STATIC: "TEETH" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos ); + +alloc $worldPos +alloc $worldNormal +alloc $projPos + +if( 0 ) +{ + ; NOTE: Don't do this optimization anymore since it would mean a gazillion combos + ; Special case for static prop lighting. We can go directly from + ; world to proj space for position, with the exception of z, which + ; is needed for fogging *if* height fog is enabled. + + ; NOTE: We don't use this path if $envmap is defined since we need + ; worldpos for envmapping. + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + ; Need this for height fog if it's enabled and for height clipping + dp4 $worldPos.z, $vPos, $cModel2 +} +else +{ + &SkinPositionAndNormal( $worldPos, $worldNormal ); + + if( $SKINNING == 1 ) + { + &Normalize( $worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to view space + ;------------------------------------------------------------------------------ + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 +} + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +; base tex coords +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_6 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_7 + +; normal map coords +;dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_8 +;dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_9 + +; spotlight texcoords +dp4 oT0.x, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp4 oT0.z, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp4 oT0.w, $worldPos, $SHADER_SPECIFIC_CONST_4 + +local( $worldPosToLightVector, $distFactors ); + +alloc $worldPosToLightVector + +sub $worldPosToLightVector, $SHADER_SPECIFIC_CONST_0, $worldPos +mov oT2, $worldPosToLightVector + +local( $distatten ); +alloc $distatten +; $distatten = [ 1, 1/dist, 1/distsquared ] + +; dist squared +dp3 $distatten.z, $worldPosToLightVector, $worldPosToLightVector + +; oodist +rsq $distatten.y, $distatten.z + +mov $distatten.x, $cOne + +local( $dist ); +alloc $dist +mul $dist.x, $distatten.z, $distatten.y + +rcp $distatten.z, $distatten.z ; 1/distsquared + +local( $endFalloffFactor ); +alloc $endFalloffFactor + +; ( dist - farZ ) +sub $endFalloffFactor.x, $dist.x, $SHADER_SPECIFIC_CONST_5.w +; 1 / ( (0.6f * farZ) - farZ) +mul $endFalloffFactor, $endFalloffFactor.x, $SHADER_SPECIFIC_CONST_0.w +max $endFalloffFactor, $endFalloffFactor, $cZero +min $endFalloffFactor, $endFalloffFactor, $cOne + +local( $vertAtten ); +alloc $vertAtten +dp3 $vertAtten, $distatten, $SHADER_SPECIFIC_CONST_5 +mul $vertAtten, $vertAtten, $endFalloffFactor + +if( $TEETH ) +{ + alloc $mouthAtten + dp3 $mouthAtten, $worldNormal.xyz, $SHADER_SPECIFIC_CONST_10.xyz + max $mouthAtten, $cZero, $mouthAtten + mul $mouthAtten, $mouthAtten, $SHADER_SPECIFIC_CONST_10.w + mul $vertAtten, $vertAtten, $mouthAtten + free $mouthAtten +} + +mov oD0, $vertAtten + +mov oT3.xyz, $worldNormal.xyz + + +free $dist +free $endFalloffFactor +free $worldPos +free $worldNormal +free $projPos +free $worldPosToLightVector +free $distatten +free $vertAtten diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_inc.vsh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_inc.vsh new file mode 100644 index 00000000..da6b6bf9 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_inc.vsh @@ -0,0 +1,145 @@ +#include "macros.vsh" + +sub VertexLitGeneric +{ + local( $detail ) = shift; + local( $envmap ) = shift; + local( $envmapcameraspace ) = shift; + local( $envmapsphere ) = shift; + local( $decal ) = shift; + + local( $worldPos, $worldNormal, $projPos ); + local( $reflectionVector ); + + ;------------------------------------------------------------------------------ + ; Vertex blending + ;------------------------------------------------------------------------------ + &AllocateRegister( \$worldPos ); + &AllocateRegister( \$worldNormal ); + &AllocateRegister( \$projPos ); +; if( $g_staticLightType eq "static" && $g_ambientLightType eq "none" && +; $g_localLightType1 eq "none" && $g_localLightType2 eq "none" && !$envmap ) + if( 0 ) + { + ; NOTE: Don't do this optimization anymore since it would mean a gazillion combos + ; of the flashlight shaders + ; Special case for static prop lighting. We can go directly from + ; world to proj space for position, with the exception of z, which + ; is needed for fogging *if* height fog is enabled. + + ; NOTE: We don't use this path if $envmap is defined since we need + ; worldpos for envmapping. + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + ; Need this for height fog if it's enabled and for height clipping + dp4 $worldPos.z, $vPos, $cModel2 + } + else + { + &SkinPositionAndNormal( $worldPos, $worldNormal ); + + if( $SKINNING == 1 ) + { + &Normalize( $worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to view space + ;------------------------------------------------------------------------------ + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + } + + mov oPos, $projPos + + ;------------------------------------------------------------------------------ + ; Fog + ;------------------------------------------------------------------------------ + &CalcFog( $worldPos, $projPos ); + &FreeRegister( \$projPos ); + + ;------------------------------------------------------------------------------ + ; Lighting + ;------------------------------------------------------------------------------ + &DoLighting( $worldPos, $worldNormal ); + + if( !$envmap ) + { + &FreeRegister( \$worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Texture coordinates + ;------------------------------------------------------------------------------ + + dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 + dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + if( $envmap ) + { + if( $envmapcameraspace ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + + ; transform reflection vector into view space + dp3 oT1.x, $reflectionVector, $cViewModel0 + dp3 oT1.y, $reflectionVector, $cViewModel1 + dp3 oT1.z, $reflectionVector, $cViewModel2 + + &FreeRegister( \$reflectionVector ); + } + elsif( $envmapsphere ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + &ComputeSphereMapTexCoords( $reflectionVector, "oT1" ); + + &FreeRegister( \$reflectionVector ); + } + else + { + &ComputeReflectionVector( $worldPos, $worldNormal, "oT1" ); + } + + ; envmap mask + dp4 oT2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + dp4 oT2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + + &FreeRegister( \$worldNormal ); + } + else + { + if ( $decal ) + { + &AllocateRegister( \$temp ); + mov $temp, $vTexCoord0 + sub oT1.xyz, $temp.xyz, $vTexCoord1.xyz + sub oT2.xyz, $vTexCoord2.xyz, $temp.xyz + &FreeRegister( \$temp ); + } + else + { + ; YUCK! This is to make texcoords continuous for mat_softwaretl + mov oT1, $cZero + mov oT2, $cZero + } + } + + if( $detail ) + { + dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 + dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + } + &FreeRegister( \$worldPos ); +} + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2.psh new file mode 100644 index 00000000..dd19efce --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2.psh @@ -0,0 +1,5 @@ +ps.1.1 + +mov r0, v0 + + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2_ps11.fxc b/mp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2_ps11.fxc new file mode 100644 index 00000000..70ad7094 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2_ps11.fxc @@ -0,0 +1,9 @@ +struct PS_INPUT +{ + float3 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return float4( i.vColor0, 1.0 ); +} diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_maskedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_maskedenvmap.psh new file mode 100644 index 00000000..c10600e3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_maskedenvmap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, t2 ; Envmap * mask +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedenvmap.psh new file mode 100644 index 00000000..321e797b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedenvmap.psh @@ -0,0 +1,25 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +tex t1 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedmaskedenvmap.psh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedmaskedenvmap.psh new file mode 100644 index 00000000..e7c52910 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedmaskedenvmap.psh @@ -0,0 +1,26 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_vs11.vsh b/mp/src/materialsystem/stdshaders/vertexlitgeneric_vs11.vsh new file mode 100644 index 00000000..c0ab2765 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_vs11.vsh @@ -0,0 +1,22 @@ +vs.1.1 + +# STATIC: "HALF_LAMBERT" "0..1" +# STATIC: "ENVMAP" "0..1" +# STATIC: "ENVMAPCAMERASPACE" "0..0" +# STATIC: "ENVMAPSPHERE" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "LIGHT_COMBO" "0..21" +# DYNAMIC: "SKINNING" "0..1" + +# can't have envmapshere or envmapcameraspace without envmap +# SKIP: !$ENVMAP && ( $ENVMAPSPHERE || $ENVMAPCAMERASPACE ) + +# can't have both envmapsphere and envmapcameraspace +# SKIP: $ENVMAPSPHERE && $ENVMAPCAMERASPACE + +# decal is by itself +# SKIP: $DECAL && ( $DETAIL || $ENVMAP || $ENVMAPCAMERASPACE || $ENVMAPSPHERE ) + +#include "VertexLitGeneric_inc.vsh" + +&VertexLitGeneric( 1, $ENVMAP, $ENVMAPCAMERASPACE, $ENVMAPSPHERE, 0 ); diff --git a/mp/src/materialsystem/stdshaders/volume_clouds.cpp b/mp/src/materialsystem/stdshaders/volume_clouds.cpp new file mode 100644 index 00000000..1421dbb4 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/volume_clouds.cpp @@ -0,0 +1,59 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "volume_clouds_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VolumeClouds, VolumeClouds_dx9 ) +BEGIN_VS_SHADER( VolumeClouds_dx9, "VolumeClouds" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 1" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 2" ) + SHADER_PARAM( BASETEXTURE3, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 3" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + END_SHADER_PARAMS + + void SetupVarsVolumeClouds( VolumeCloudsVars_t &info ) + { + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nTexture1 = BASETEXTURE; + info.m_nTexture2 = BASETEXTURE2; + info.m_nTexture3 = BASETEXTURE3; + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + InitParamsVolumeClouds( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + // Fallback to unlit generic + return "UnlitGeneric_DX8"; + } + + return 0; + } + + SHADER_INIT + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + InitVolumeClouds( this, params, info ); + } + + SHADER_DRAW + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + DrawVolumeClouds( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/volume_clouds_helper.cpp b/mp/src/materialsystem/stdshaders/volume_clouds_helper.cpp new file mode 100644 index 00000000..cd2e889e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/volume_clouds_helper.cpp @@ -0,0 +1,138 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "volume_clouds_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "volume_clouds_vs20.inc" +#include "volume_clouds_ps20.inc" +#include "volume_clouds_ps20b.inc" + + +void InitParamsVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VolumeCloudsVars_t &info ) +{ + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); + + // Set material parameter default values + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nRefractAmount, kDefaultRefractAmount ); +} + +void InitVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, VolumeCloudsVars_t &info ) +{ + // Load textures + if ( (info.m_nTexture1 != -1) && params[info.m_nTexture1]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture1, TEXTUREFLAGS_SRGB ); + } + + if ( (info.m_nTexture2 != -1) && params[info.m_nTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture2, TEXTUREFLAGS_SRGB ); + } + + if ( (info.m_nTexture3 != -1) && params[info.m_nTexture3]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture3, TEXTUREFLAGS_SRGB ); + } +} + +void DrawVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, VolumeCloudsVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( volume_clouds_vs20 ); + SET_STATIC_VERTEX_SHADER( volume_clouds_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() && !IsOpenGL() ) // Always send POSIX down the 20 path (rg - why?) + { + DECLARE_STATIC_PIXEL_SHADER( volume_clouds_ps20b ); + SET_STATIC_PIXEL_SHADER( volume_clouds_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( volume_clouds_ps20 ); + SET_STATIC_PIXEL_SHADER( volume_clouds_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); + + // !!! We need to turn this back on because EnableAlphaBlending() above disables it! + //pShaderShadow->EnableDepthWrites( true ); + } + DYNAMIC_STATE + { + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( volume_clouds_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( volume_clouds_vs20 ); + + // Set Vertex Shader Constants + + // Time + float vPackedVsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float flTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + float flRotateSpeed = 0.065f; + vPackedVsConst1[0] = flTime * flRotateSpeed * 1.0f; + vPackedVsConst1[1] = flTime * flRotateSpeed * 2.0f; + vPackedVsConst1[2] = flTime * flRotateSpeed * 4.0f; + vPackedVsConst1[0] -= (float)( (int)( vPackedVsConst1[0] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + vPackedVsConst1[1] -= (float)( (int)( vPackedVsConst1[1] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + vPackedVsConst1[2] -= (float)( (int)( vPackedVsConst1[2] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vPackedVsConst1, 1 ); + + // Set Pixel Shader Combos + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() && !IsOpenGL() ) // Always send POSIX down the 20 path (rg - why?) + { + DECLARE_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20 ); + } + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nTexture1 ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nTexture2 ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nTexture3 ); + + // Set Pixel Shader Constants + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 5, vEyePos, 1 ); + + float vPackedConst6[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst6[0] = IS_PARAM_DEFINED( info.m_nRefractAmount ) ? params[info.m_nRefractAmount]->GetFloatValue() : kDefaultRefractAmount; + vPackedConst6[1] = vPackedVsConst1[0]; // Time % 1000 + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 ); + } + pShader->Draw(); +} diff --git a/mp/src/materialsystem/stdshaders/volume_clouds_helper.h b/mp/src/materialsystem/stdshaders/volume_clouds_helper.h new file mode 100644 index 00000000..abbb63b7 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/volume_clouds_helper.h @@ -0,0 +1,41 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef VOLUME_CLOUDS_HELPER_H +#define VOLUME_CLOUDS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VolumeCloudsVars_t +{ + VolumeCloudsVars_t() { memset( this, 0xFF, sizeof( VolumeCloudsVars_t ) ); } + + int m_nRefractAmount; + int m_nTexture1; + int m_nTexture2; + int m_nTexture3; + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultRefractAmount = 0.1f; + +void InitParamsVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VolumeCloudsVars_t &info ); +void InitVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, VolumeCloudsVars_t &info ); +void DrawVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, VolumeCloudsVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // VolumeClouds_HELPER_H diff --git a/mp/src/materialsystem/stdshaders/volume_clouds_ps2x.fxc b/mp/src/materialsystem/stdshaders/volume_clouds_ps2x.fxc new file mode 100644 index 00000000..7435f305 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/volume_clouds_ps2x.fxc @@ -0,0 +1,66 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tInnerSampler : register( s0 ); +sampler g_tMiddleSampler : register( s1 ); +sampler g_tOuterSampler : register( s2 ); + +// Shaders Constants and Globals ================================================================== +//const float4 g_vPackedConst6 : register( c6 ); +//#define g_flTime g_vPackedConst6.w + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float4 v2DTangentViewVector01 : TEXCOORD0; + float4 vUv01 : TEXCOORD1; + float4 v2DTangentViewVector2_vUv2 : TEXCOORD2; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + float4 vFinalColor = float4( 0.0f, 0.0f, 0.0f, 1.0f ); + +#if defined(SHADER_MODEL_PS_2_0) + float flNumLayers = 2.0f; +#else + float flNumLayers = 10.0f; +#endif + + //float flColorDim = 1.0f; + for ( float j=flNumLayers-1.0f; j>=0.0f; j-=1.0f ) // From hightest to lowest layer + { + float4 vInnerTexel = tex2D( g_tInnerSampler, saturate( i.vUv01.xy + i.v2DTangentViewVector01.xy * 0.005 * j ) ); + float4 vMiddleTexel = tex2D( g_tMiddleSampler, saturate( i.vUv01.wz + i.v2DTangentViewVector01.wz * 0.005 * j ) ); + float4 vOuterTexel = tex2D( g_tOuterSampler, saturate( i.v2DTangentViewVector2_vUv2.wz + i.v2DTangentViewVector2_vUv2.xy * 0.005 * j ) ); + + float4 vThisTexel; + vThisTexel.rgb = ( vInnerTexel.rgb * vInnerTexel.a ) + ( vMiddleTexel.rgb * vMiddleTexel.a ) + ( vOuterTexel.rgb * vOuterTexel.a ); + vThisTexel.a = 1.0f - ( ( 1.0f - vOuterTexel.a ) * ( 1.0f - vMiddleTexel.a ) * ( 1.0f - vInnerTexel.a ) ); + + //vThisTexel.rgb *= flColorDim; + //flColorDim *= 0.95f; + + // 5.0 and 0.8625 are magic numbers that look good with the current textures + float flBlendValue = saturate( pow( vThisTexel.a, lerp( 5.0f, 0.8625f, saturate( j/(flNumLayers-1.0f) ) ) ) ); + + vFinalColor.rgb = vThisTexel.rgb + ( vFinalColor.rgb * ( 1.0f - flBlendValue ) ); + vFinalColor.a *= 1.0f - flBlendValue; // Dest alpha scalar + } + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = vFinalColor.rgb; + result.a = 1.0f - vFinalColor.a; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); //go back to final output when it'll fit. +} diff --git a/mp/src/materialsystem/stdshaders/volume_clouds_vs20.fxc b/mp/src/materialsystem/stdshaders/volume_clouds_vs20.fxc new file mode 100644 index 00000000..ccab2574 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/volume_clouds_vs20.fxc @@ -0,0 +1,103 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const bool g_bSkinning = SKINNING ? true : false; + +const float3 g_vTime : register( SHADER_SPECIFIC_CONST_0 ); +#define g_flTime1x g_vTime.x +#define g_flTime2x g_vTime.y +#define g_flTime4x g_vTime.z + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float4 vUserData : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float4 v2DTangentViewVector01 : TEXCOORD0; + float4 vUv01 : TEXCOORD1; + float4 v2DTangentViewVector2_vUv2 : TEXCOORD2; +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Decompress compressed normal and tangent + float4 vObjPosition = i.vPos.xyzw; + float3 vObjNormal; + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vUserData, vObjNormal, vObjTangent ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + vWorldTangent.xyz = normalize( vWorldTangent.xyz ); + vWorldBinormal.xyz = normalize( vWorldBinormal.xyz ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // View vector + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + float3 vTangentViewVector = Vec3WorldToTangentNormalized( vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Texture coordinates + float4 mRotate; + float2 vBaseUv = i.vTexCoord0.xy; + + // Inner layer + mRotate.x = cos( g_flTime4x ); + mRotate.y = -sin( g_flTime4x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + o.vUv01.xy = ( vBaseUv.xy - 0.5f ) * 1.0f; + o.vUv01.xy = float2( dot( o.vUv01.xy, mRotate.xy ), dot( o.vUv01.xy, mRotate.zw ) ); + o.vUv01.xy += 0.5f; + o.v2DTangentViewVector01.xy = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + // Middle layer + mRotate.x = cos( g_flTime2x ); + mRotate.y = -sin( g_flTime2x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + o.vUv01.wz = ( vBaseUv.xy - 0.5f ) * 1.0f; + o.vUv01.wz = float2( dot( o.vUv01.wz, mRotate.xy ), dot( o.vUv01.wz, mRotate.zw ) ); + o.vUv01.wz += 0.5f; + o.v2DTangentViewVector01.wz = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + // Outer layer + mRotate.x = cos( g_flTime1x ); + mRotate.y = -sin( g_flTime1x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + float2 vUv2 = ( vBaseUv.xy - 0.5f ) * 1.0f; + vUv2.xy = float2( dot( vUv2.xy, mRotate.xy ), dot( vUv2.xy, mRotate.zw ) ); + vUv2.xy += 0.5f; + o.v2DTangentViewVector2_vUv2.wz = vUv2.xy; + o.v2DTangentViewVector2_vUv2.xy = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/vr_distort_hud.cpp b/mp/src/materialsystem/stdshaders/vr_distort_hud.cpp new file mode 100644 index 00000000..b78a3e51 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vr_distort_hud.cpp @@ -0,0 +1,224 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "commandbuilder.h" + +#include "vr_distort_hud_ps20.inc" +#include "vr_distort_hud_ps20b.inc" +#include "vr_distort_hud_vs20.inc" +#include "vr_distort_hud_ps30.inc" +#include "vr_distort_hud_vs30.inc" + +#include "../materialsystem_global.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +class CVRDistortTexture_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > m_SemiStaticCmdsOut; + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CVRDistortTexture_DX9_Context( void ) + { + m_pStaticCmds = NULL; + } + + ~CVRDistortTexture_DX9_Context( void ) + { + ResetStaticCmds(); + } + +}; + + +BEGIN_VS_SHADER( vr_distort_hud, "Help for hud warp" ) + BEGIN_SHADER_PARAMS + + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_gui", "" ) + SHADER_PARAM( DISTORTMAP, SHADER_PARAM_TYPE_TEXTURE, "vr_distort_map_left", "" ) + SHADER_PARAM( DISTORTBOUNDS, SHADER_PARAM_TYPE_VEC4, "[ 0 0 1 1 ]", "" ) + SHADER_PARAM( HUDTRANSLUCENT, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( HUDUNDISTORT, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( DISTORTMAP, TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NODEBUGOVERRIDE | TEXTUREFLAGS_SINGLECOPY | + TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ); + } + + SHADER_DRAW + { + CVRDistortTexture_DX9_Context *pContextData = reinterpret_cast< CVRDistortTexture_DX9_Context *> ( *pContextDataPtr ); + bool bNeedRegenStaticCmds = ( !pContextData ) || pShaderShadow; + + if ( !pContextData ) // make sure allocated + { + pContextData = new CVRDistortTexture_DX9_Context; + *pContextDataPtr = pContextData; + } + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER0, BASETEXTURE, -1 ); + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER1, DISTORTMAP, -1 ); + + staticCmdsBuf.End(); + + // now, copy buf + pContextData->m_pStaticCmds = new uint8[ staticCmdsBuf.Size() ]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + + if ( pShaderAPI && pContextData->m_bMaterialVarsChanged ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + pContextData->m_SemiStaticCmdsOut.SetAmbientCubeDynamicStateVertexShader(); + pContextData->m_SemiStaticCmdsOut.End(); + } + + SHADOW_STATE + { + SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->EnableSRGBWrite( true ); + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->EnableBlending( false ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ZERO ); + } + + DefaultFog(); + + int nFormat = 0; + nFormat |= VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( nFormat, 2, 0, 0 ); + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + SET_STATIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + SET_STATIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + SET_STATIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + } + } + else + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + SET_STATIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + SET_STATIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + } + } + + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + pShaderAPI->SetDefaultState(); + + SetPixelShaderConstant( 0, DISTORTBOUNDS ); + SetPixelShaderConstant( 1, HUDTRANSLUCENT ); + + int hudUndistortEnabled = ( params[ HUDUNDISTORT ]->GetIntValue() == 0 ) ? 0 : 1; + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_HUDUNDISTORT, hudUndistortEnabled ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_HUDUNDISTORT, hudUndistortEnabled ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + } + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_HUDUNDISTORT, hudUndistortEnabled ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + + Draw(); + + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/vr_distort_hud_ps2x.fxc b/mp/src/materialsystem/stdshaders/vr_distort_hud_ps2x.fxc new file mode 100644 index 00000000..331c1897 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vr_distort_hud_ps2x.fxc @@ -0,0 +1,78 @@ +// DYNAMIC: "CMBO_HUDUNDISTORT" "0..1" + +#include "shader_constant_register_map.h" +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler DistortMapTextureSampler : register( s1 ); + +const float4 DistortBounds : register( c0 ); +const int bHudTranslucent : register( c1 ); + +struct PS_INPUT +{ + float2 vBaseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float2 vOriginal = i.vBaseTexCoord.xy; + + + // The full uv 0->1 range of the base texture here is shifted/scaled so that it maps + // to the region that would be minUV->maxUV of the base texture in the regular undistort + // code. This lets us overlay a higher-resolution inset rectangle directly onto the + // render target with undistort, which results in a much higher-quality HUD. + + float2 minUV = DistortBounds.xy; + float2 maxUV = DistortBounds.zw; + float2 scaleUV = 1.0 / ( maxUV - minUV ); + + + float2 vGreen; + float4 vFinal; + + #if ( CMBO_HUDUNDISTORT ) + { + float4 vRead = tex2D( DistortMapTextureSampler, vOriginal ); + + float2 vRed = vRead.xy; + float2 vBlue = vRead.zw; + + vGreen = ( vRed + vBlue ) / 2.0; + + vRed = ( vRed - minUV ) * scaleUV; + vGreen = ( vGreen - minUV ) * scaleUV; + vBlue = ( vBlue - minUV ) * scaleUV; + + vFinal.r = tex2D( BaseTextureSampler, vRed ).r; + vFinal.ga = tex2D( BaseTextureSampler, vGreen ).ga; + vFinal.b = tex2D( BaseTextureSampler, vBlue ).b; + } + #else + { + vGreen = ( vOriginal - minUV ) * scaleUV; + vFinal = tex2D( BaseTextureSampler, vGreen ); + } + #endif + + + // When the HUD isn't supposed to be rendered as translucent, some of its elements do occasionally have non-unit alpha. + // We always have blending and alphatest enabled here, so if the hud itself is not supposed to be translucent we need + // to fix up the alphas. + vFinal.a = lerp( 1, vFinal.a, bHudTranslucent ); + + + // Smooth off the edges of the quad. This also gives (0,0,0,0) in the outer areas, for alpha test and for blackout. + + const float edgeRampFrac = 0.005; + float2 uvEdgeRamp = smoothstep( float2(-edgeRampFrac,-edgeRampFrac), float2(edgeRampFrac,edgeRampFrac), vGreen ) * + ( 1 - smoothstep( float2(1-edgeRampFrac,1-edgeRampFrac), float2(1+edgeRampFrac,1+edgeRampFrac), vGreen ) ); + + float edgeRamp = uvEdgeRamp.x * uvEdgeRamp.y; + + vFinal *= edgeRamp; + + + return vFinal; +} diff --git a/mp/src/materialsystem/stdshaders/vr_distort_hud_vs20.fxc b/mp/src/materialsystem/stdshaders/vr_distort_hud_vs20.fxc new file mode 100644 index 00000000..b82bfa13 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vr_distort_hud_vs20.fxc @@ -0,0 +1,26 @@ +#include "common_vs_fxc.h" + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + o.vProjPos = v.vPos; + o.vBaseTexCoord = v.vBaseTexCoord; + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/vr_distort_texture.cpp b/mp/src/materialsystem/stdshaders/vr_distort_texture.cpp new file mode 100644 index 00000000..1e87d72a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vr_distort_texture.cpp @@ -0,0 +1,213 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "commandbuilder.h" + +#include "vr_distort_texture_ps20.inc" +#include "vr_distort_texture_ps20b.inc" +#include "vr_distort_texture_vs20.inc" +#include "vr_distort_texture_ps30.inc" +#include "vr_distort_texture_vs30.inc" + +#include "../materialsystem_global.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + + + + + + +class CVRDistortTexture_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > m_SemiStaticCmdsOut; + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CVRDistortTexture_DX9_Context( void ) + { + m_pStaticCmds = NULL; + } + + ~CVRDistortTexture_DX9_Context( void ) + { + ResetStaticCmds(); + } + +}; + + +static const float kAllZeros[ 4 ] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + +BEGIN_VS_SHADER( vr_distort_texture, "Help for warp" ) + BEGIN_SHADER_PARAMS + + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( DISTORTMAP, SHADER_PARAM_TYPE_TEXTURE, "vr_distort_map", "" ) + SHADER_PARAM( USERENDERTARGET, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( DISTORTMAP, TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NODEBUGOVERRIDE | + TEXTUREFLAGS_SINGLECOPY | TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ); + } + + SHADER_DRAW + { + CVRDistortTexture_DX9_Context *pContextData = reinterpret_cast< CVRDistortTexture_DX9_Context *> ( *pContextDataPtr ); + bool bNeedRegenStaticCmds = ( !pContextData ) || pShaderShadow; + + if ( !pContextData ) // make sure allocated + { + pContextData = new CVRDistortTexture_DX9_Context; + *pContextDataPtr = pContextData; + } + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER0, BASETEXTURE, -1 ); + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER1, DISTORTMAP, -1 ); + + staticCmdsBuf.End(); + + // now, copy buf + pContextData->m_pStaticCmds = new uint8[ staticCmdsBuf.Size() ]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + + if ( pShaderAPI && pContextData->m_bMaterialVarsChanged ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + pContextData->m_SemiStaticCmdsOut.SetAmbientCubeDynamicStateVertexShader(); + pContextData->m_SemiStaticCmdsOut.End(); + } + + SHADOW_STATE + { + SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + + pShaderShadow->EnableBlending( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->EnableSRGBWrite( true ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableAlphaTest( false ); + + DefaultFog(); + + int nFormat = 0; + nFormat |= VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( nFormat, 2, 0, 0 ); + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + SET_STATIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + SET_STATIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + SET_STATIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + } + } + else + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + SET_STATIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + SET_STATIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + } + } + + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + pShaderAPI->SetDefaultState(); + + int useRenderTarget = ( params[ USERENDERTARGET ]->GetIntValue() == 0 ) ? 0 : 1; + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_USERENDERTARGET, useRenderTarget ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_USERENDERTARGET, useRenderTarget ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + } + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_USERENDERTARGET, useRenderTarget ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + Draw(); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/vr_distort_texture_ps2x.fxc b/mp/src/materialsystem/stdshaders/vr_distort_texture_ps2x.fxc new file mode 100644 index 00000000..23ff3f5f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vr_distort_texture_ps2x.fxc @@ -0,0 +1,49 @@ +// DYNAMIC: "CMBO_USERENDERTARGET" "0..1" + +#include "shader_constant_register_map.h" +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler DistortMapTextureSampler : register( s1 ); + + +struct PS_INPUT +{ + float2 vBaseTexCoord : TEXCOORD0; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + float2 vOriginal = i.vBaseTexCoord.xy; + + float4 vRead = tex2D( DistortMapTextureSampler, vOriginal ); + + float2 vGreen; + vGreen.r = ( vRead.x + vRead.z ) / 2.0; + vGreen.g = ( vRead.y + vRead.w ) / 2.0; + + float4 vFinal; + vFinal.r = tex2D( BaseTextureSampler, vRead.xy ).r; + vFinal.ga = tex2D( BaseTextureSampler, vGreen ).ga; + vFinal.b = tex2D( BaseTextureSampler, vRead.zw ).b; + + float fBoundsCheck; + #if ( CMBO_USERENDERTARGET ) + { + fBoundsCheck = saturate( dot( (vGreen.xy < float2(0.01,0.01)), float2(1,1)) + dot( (vGreen.xy > float2(0.99,0.99)), float2(1,1)) ); + } + #else + { + fBoundsCheck = saturate( dot( (vGreen.xy < float2(0.005,0.005)), float2(1,1)) + dot( (vGreen.xy > float2(0.995,0.995)), float2(1,1)) + + (vGreen.x > 0.495 && vGreen.x < 0.505 ) ); + } + #endif + + vFinal.xyz = lerp( vFinal.xyz, float3(0,0,0), fBoundsCheck ); + + return vFinal; +} + + + diff --git a/mp/src/materialsystem/stdshaders/vr_distort_texture_vs20.fxc b/mp/src/materialsystem/stdshaders/vr_distort_texture_vs20.fxc new file mode 100644 index 00000000..b82bfa13 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/vr_distort_texture_vs20.fxc @@ -0,0 +1,26 @@ +#include "common_vs_fxc.h" + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + o.vProjPos = v.vPos; + o.vBaseTexCoord = v.vBaseTexCoord; + + return o; +} diff --git a/mp/src/materialsystem/stdshaders/water.cpp b/mp/src/materialsystem/stdshaders/water.cpp new file mode 100644 index 00000000..92a26375 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water.cpp @@ -0,0 +1,614 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "common_hlsl_cpp_consts.h" // hack hack hack! +#include "convar.h" + +#include "WaterCheap_vs20.inc" +#include "WaterCheap_ps20.inc" +#include "WaterCheap_ps20b.inc" +#include "Water_vs20.inc" +#include "Water_ps20.inc" +#include "water_ps20b.inc" + +#ifndef _X360 +static ConVar r_waterforceexpensive( "r_waterforceexpensive", "0", FCVAR_ARCHIVE ); +#endif + +DEFINE_FALLBACK_SHADER( Water, Water_DX9_HDR ) + +BEGIN_VS_SHADER( Water_DX90, + "Help for Water" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterRefraction", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.8", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "dev/water_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( FOGSTART, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FOGEND, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( ABOVEWATER, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( NOLOWENDLIGHTMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( SCROLL1, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( SCROLL2, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( BLURREFRACT, SHADER_PARAM_TYPE_BOOL, "0", "Cause the refraction to be blurry on ps2b hardware" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[ABOVEWATER]->IsDefined() ) + { + Warning( "***need to set $abovewater for material %s\n", pMaterialName ); + params[ABOVEWATER]->SetIntValue( 1 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCALE]->IsDefined() ) + { + params[SCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[SCROLL1]->IsDefined() ) + { + params[SCROLL1]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + if( !params[SCROLL2]->IsDefined() ) + { + params[SCROLL2]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + + // By default, we're force expensive on dx9. NO WE DON'T!!!! + if( !params[FORCEEXPENSIVE]->IsDefined() ) + { +#ifdef _X360 + params[FORCEEXPENSIVE]->SetIntValue( 0 ); +#else + params[FORCEEXPENSIVE]->SetIntValue( 1 ); +#endif + } + if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + + // Fallbacks for water need lightmaps usually + if ( !params[NOLOWENDLIGHTMAP]->GetIntValue() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[NORMALMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Water_DX81"; + } + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE, TEXTUREFLAGS_SRGB ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE, TEXTUREFLAGS_SRGB ); + } + if ( params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP, TEXTUREFLAGS_SRGB ); + } + if ( params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + } + } + + inline void GetVecParam( int constantVar, float *val ) + { + if( constantVar == -1 ) + return; + + IMaterialVar* pVar = s_ppParams[constantVar]; + Assert( pVar ); + + if (pVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pVar->GetFloatValue(); + } + + inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bReflection, bool bRefraction ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + if( bRefraction ) + { + // refract sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + if( bReflection ) + { + // reflect sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + if( params[BASETEXTURE]->IsTexture() ) + { + // BASETEXTURE + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + // LIGHTMAP + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); + } + } + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 1; + if( params[BASETEXTURE]->IsTexture() ) + { + numTexCoords = 3; + } + pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 ); + + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( params[NORMALMAP]->IsTexture() && g_pHardwareConfig->SupportsNormalMapCompression() ) + { + ITexture *pNormalMap = params[NORMALMAP]->GetTextureValue(); + if ( pNormalMap ) + { + // Clamp this to 0 or 1 since that's how we've authored the water shader (i.e. no separate alpha map/channel) + nNormalDecodeMode = pNormalMap->GetNormalDecodeMode() == NORMAL_DECODE_NONE ? NORMAL_DECODE_NONE : NORMAL_DECODE_ATI2N; + } + } + + DECLARE_STATIC_VERTEX_SHADER( water_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_VERTEX_SHADER( water_vs20 ); + + // "REFLECT" "0..1" + // "REFRACT" "0..1" + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( water_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( ABOVEWATER, params[ABOVEWATER]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER_COMBO( BLURRY_REFRACT, params[BLURREFRACT]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( water_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( water_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( ABOVEWATER, params[ABOVEWATER]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( water_ps20 ); + } + + FogToFogColor(); + + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + if( bRefraction ) + { + // HDRFIXME: add comment about binding.. Specify the number of MRTs in the enable + BindTexture( SHADER_SAMPLER0, REFRACTTEXTURE, -1 ); + } + if( bReflection ) + { + BindTexture( SHADER_SAMPLER2, REFLECTTEXTURE, -1 ); + } + BindTexture( SHADER_SAMPLER4, NORMALMAP, BUMPFRAME ); + if( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // Refraction tint + if( bRefraction ) + { + SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT ); + } + // Reflection tint + if( bReflection ) + { + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER ) + { + // Need to multiply by 4 in linear space since we premultiplied into + // the render target by .25 to get overbright data in the reflection render target. + float gammaReflectTint[3]; + params[REFLECTTINT]->GetVecValue( gammaReflectTint, 3 ); + float linearReflectTint[4]; + linearReflectTint[0] = GammaToLinear( gammaReflectTint[0] ) * 4.0f; + linearReflectTint[1] = GammaToLinear( gammaReflectTint[1] ) * 4.0f; + linearReflectTint[2] = GammaToLinear( gammaReflectTint[2] ) * 4.0f; + linearReflectTint[3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 4, linearReflectTint, 1 ); + } + else + { + SetPixelShaderConstantGammaToLinear( 4, REFLECTTINT ); + } + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + float curtime=pShaderAPI->CurrentTime(); + float vc0[4]; + float v0[4]; + params[SCROLL1]->GetVecValue(v0,4); + vc0[0]=curtime*v0[0]; + vc0[1]=curtime*v0[1]; + params[SCROLL2]->GetVecValue(v0,4); + vc0[2]=curtime*v0[0]; + vc0[3]=curtime*v0[1]; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vc0, 1 ); + + float c0[4] = { 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + + float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + // fresnel constants + float c3[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, c3, 1 ); + + float c5[4] = { params[REFLECTAMOUNT]->GetFloatValue(), params[REFLECTAMOUNT]->GetFloatValue(), + params[REFRACTAMOUNT]->GetFloatValue(), params[REFRACTAMOUNT]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + + SetPixelShaderConstantGammaToLinear( 6, FOGCOLOR ); + + float c7[4] = + { + params[FOGSTART]->GetFloatValue(), + params[FOGEND]->GetFloatValue() - params[FOGSTART]->GetFloatValue(), + 1.0f, + 0.0f + }; + if (g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER ) + { + // water overbright factor + c7[2] = 4.0; + } + pShaderAPI->SetPixelShaderConstant( 7, c7, 1 ); + + pShaderAPI->SetPixelShaderFogParams( 8 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( water_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( water_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( water_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( water_ps20 ); + } + } + Draw(); + } + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bRefraction ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + if( bBlend ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + // envmap + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( bRefraction && bBlend ) + { + // refraction map (used for alpha) + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( params[NORMALMAP]->IsTexture() && g_pHardwareConfig->SupportsNormalMapCompression() ) + { + ITexture *pNormalMap = params[NORMALMAP]->GetTextureValue(); + if ( pNormalMap ) + { + // Clamp this to 0 or 1 since that's how we've authored the water shader (i.e. no separate alpha map/channel) + nNormalDecodeMode = pNormalMap->GetNormalDecodeMode() == NORMAL_DECODE_NONE ? NORMAL_DECODE_NONE : NORMAL_DECODE_ATI2N; + } + } + + DECLARE_STATIC_VERTEX_SHADER( watercheap_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( BLEND, bBlend && bRefraction ); + SET_STATIC_VERTEX_SHADER( watercheap_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( watercheap_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL, params[NOFRESNEL]->GetIntValue() == 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLEND, bBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTALPHA, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( watercheap_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( watercheap_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL, params[NOFRESNEL]->GetIntValue() == 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLEND, bBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTALPHA, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( watercheap_ps20 ); + } + + // HDRFIXME: test cheap water! + if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) + { + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + } + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + BindTexture( SHADER_SAMPLER0, ENVMAP, ENVMAPFRAME ); + BindTexture( SHADER_SAMPLER1, NORMALMAP, BUMPFRAME ); + if( bRefraction && bBlend ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTEXTURE, -1 ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + + float cheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float cheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + float cheapWaterParams[4] = + { + cheapWaterStartDistance * VSHADER_VECT_SCALE, + cheapWaterEndDistance * VSHADER_VECT_SCALE, + PSHADER_VECT_SCALE / ( cheapWaterEndDistance - cheapWaterStartDistance ), + cheapWaterStartDistance / ( cheapWaterEndDistance - cheapWaterStartDistance ), + }; + pShaderAPI->SetPixelShaderConstant( 1, cheapWaterParams ); + + if( g_pConfig->bShowSpecular ) + { + SetPixelShaderConstant( 2, REFLECTTINT, REFLECTBLENDFACTOR ); + } + else + { + float zero[4] = { 0.0f, 0.0f, 0.0f, params[REFLECTBLENDFACTOR]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 2, zero ); + } + + pShaderAPI->SetPixelShaderFogParams( 3 ); + + if( params[SCROLL1]->IsDefined()) + { + float curtime=pShaderAPI->CurrentTime(); + float vc0[4]; + float v0[4]; + params[SCROLL1]->GetVecValue(v0,4); + vc0[0]=curtime*v0[0]; + vc0[1]=curtime*v0[1]; + params[SCROLL2]->GetVecValue(v0,4); + vc0[2]=curtime*v0[0]; + vc0[3]=curtime*v0[1]; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vc0, 1 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( watercheap_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( watercheap_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20 ); + } + } + Draw(); + } + + SHADER_DRAW + { + // TODO: fit the cheap water stuff into the water shader so that we don't have to do + // 2 passes. +#ifdef _X360 + bool bForceExpensive = false; +#else + bool bForceExpensive = r_waterforceexpensive.GetBool(); +#endif + bool bForceCheap = (params[FORCECHEAP]->GetIntValue() != 0) || UsingEditor( params ); + if ( bForceCheap ) + { + bForceExpensive = false; + } + else + { + bForceExpensive = bForceExpensive || (params[FORCEEXPENSIVE]->GetIntValue() != 0); + } + Assert( !( bForceCheap && bForceExpensive ) ); + + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); +#ifdef _X360 + bool bReflection = params[REFLECTTEXTURE]->IsTexture(); +#else + bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture(); +#endif + bool bDrewSomething = false; + if ( !bForceCheap && ( bReflection || bRefraction ) ) + { + bDrewSomething = true; + DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction ); + } + + // Use $decal to see if we are a decal or not. . if we are, then don't bother + // drawing the cheap version for now since we don't have access to env_cubemap +#ifdef _X360 + if( params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) && !bForceExpensive ) +#else + if( !bReflection && params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) +#endif + { + bDrewSomething = true; + DrawCheapWater( params, pShaderShadow, pShaderAPI, !bForceCheap, bRefraction ); + } + + if( !bDrewSomething ) + { + // We are likely here because of the tools. . . draw something so that + // we won't go into wireframe-land. + Draw(); + } + } +END_SHADER + +//----------------------------------------------------------------------------- +// This allows us to use a block labelled 'Water_DX9_HDR' in the water materials +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( Water_DX9_HDR, Water_DX90, + "Help for Water_DX9_HDR" ) + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "WATER_DX90"; + } + return 0; + } +END_INHERITED_SHADER + diff --git a/mp/src/materialsystem/stdshaders/water_dudv.cpp b/mp/src/materialsystem/stdshaders/water_dudv.cpp new file mode 100644 index 00000000..cf29c183 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water_dudv.cpp @@ -0,0 +1,95 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + + +#include "BaseVSShader.h" + +#include "waterdudv_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Water_DuDv, "Help for Water_DuDv" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "dudv bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + if( !params[REFRACTTINT]->IsDefined() ) + { + params[REFRACTTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( true ); + pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0, 0 ); + + pShaderShadow->SetVertexShader( "WaterDuDv_vs11", 0 ); + pShaderShadow->SetPixelShader( "WaterDuDv_ps11", 0 ); + DisableFog(); + } + DYNAMIC_STATE + { + waterdudv_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetDOFOG( pShaderAPI->GetSceneFogMode() != MATERIAL_FOG_NONE ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + Vector4D vec; + const float *pTint = params[REFRACTTINT]->GetVecValue(); + float flAverage = ( pTint[0] + pTint[1] + pTint[2] ) / 3.0f; + vec.Init( flAverage, flAverage, flAverage, 1.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vec.Base() ); + + // Amount to refract + SetPixelShaderConstant( 0, REFRACTAMOUNT ); + + // Used to renormalize + vec.Init( 1.0f, 1.0f, 1.0f, 1.0f ); + pShaderAPI->SetPixelShaderConstant( 1, vec.Base() ); + + // Used to deal with the red channel + vec.Init( 0.0f, 1.0f, 1.0f, 1.0f ); + pShaderAPI->SetPixelShaderConstant( 2, vec.Base() ); + + vec.Init( 1.0f, 0.0f, 0.0f, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 3, vec.Base() ); + + BindTexture( SHADER_TEXTURE_STAGE0, BUMPMAP, BUMPFRAME ); + } + Draw(); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/water_dx60.cpp b/mp/src/materialsystem/stdshaders/water_dx60.cpp new file mode 100644 index 00000000..b6c952b3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water_dx60.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// NOTE: Water DX60 is located in LightmappedGeneric_DX6 so it can inherit +DEFINE_FALLBACK_SHADER( Water, Water_DX60 ) + diff --git a/mp/src/materialsystem/stdshaders/water_dx80.cpp b/mp/src/materialsystem/stdshaders/water_dx80.cpp new file mode 100644 index 00000000..2f31bb5b --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water_dx80.cpp @@ -0,0 +1,419 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" + +#include "water_vs11.inc" +#include "watercheappervertexfresnel_vs11.inc" +#include "watercheap_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Water_DX80, + "Help for Water_DX80" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "dudv bump map" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCALE]->IsDefined() ) + { + params[SCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[FORCEEXPENSIVE]->IsDefined() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + if ( IsPC() && ( g_pHardwareConfig->GetDXSupportLevel() < 80 || !g_pHardwareConfig->HasProjectedBumpEnv() ) ) + { + return "Water_DX60"; + } + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE ); + } + if (params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + if (params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP ); + } + if (params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + } + + inline void SetCheapWaterFactors( IMaterialVar **params, IShaderDynamicAPI* pShaderAPI, int nConstantReg ) + { + float flCheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float flCheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + float flCheapWaterConstants[4] = + { + flCheapWaterStartDistance, + 1.0f / ( flCheapWaterEndDistance - flCheapWaterStartDistance ), + 0.0f, + 0.0f + }; + pShaderAPI->SetVertexShaderConstant( nConstantReg, flCheapWaterConstants ); + } + + inline void DrawReflection( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlendReflection ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + if( bBlendReflection ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + water_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WaterReflect_ps11", 0 ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + + float fReflectionAmount = params[REFLECTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fReflectionAmount, 0.0f, 0.0f, fReflectionAmount ); + + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER1, REFLECTTEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + pShaderAPI->SetVertexShaderIndex( 0 ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + // used to invert y + float c[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFLECTTINT ); + + water_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline void DrawRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + water_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WaterRefract_ps11", 0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount ); + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER1, REFRACTTEXTURE ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + // used to invert y + float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFRACTTINT ); + + water_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline void DrawRefractionForFresnel( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI ) + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + water_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WaterRefractFresnel_ps11", 0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount ); + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER1, REFRACTTEXTURE ); + BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + SetCheapWaterFactors( params, pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 ); + + // used to invert y + float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFRACTTINT ); + + water_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bBlendFresnel, bool bNoPerVertexFresnel ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( bBlend ) + { + if ( bBlendFresnel ) + { + EnableAlphaBlending( SHADER_BLEND_DST_ALPHA, SHADER_BLEND_ONE_MINUS_DST_ALPHA ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + } + + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | + VERTEX_TANGENT_T, 1, 0, 0 ); + + if( bNoPerVertexFresnel ) + { + watercheap_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WaterCheap_vs11", vshIndex.GetIndex() ); + } + else + { + watercheappervertexfresnel_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WaterCheapPerVertexFresnel_vs11", vshIndex.GetIndex() ); + } + + static const char *s_pPixelShaderName[] = + { + "WaterCheapOpaque_ps11", + "WaterCheap_ps11", + "WaterCheapNoFresnelOpaque_ps11", + "WaterCheapNoFresnel_ps11", + }; + + int nPshIndex = 0; + if ( bBlend ) nPshIndex |= 0x1; + if ( bNoPerVertexFresnel ) nPshIndex |= 0x2; + pShaderShadow->SetPixelShader( s_pPixelShaderName[nPshIndex] ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, NORMALMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER3, ENVMAP, ENVMAPFRAME ); + + if( bBlend && !bBlendFresnel ) + { + SetCheapWaterFactors( params, pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_2 ); + } + else + { + float flCheapWaterConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, flCheapWaterConstants ); + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + SetPixelShaderConstant( 1, REFLECTTINT, REFLECTBLENDFACTOR ); + + if( bNoPerVertexFresnel ) + { + watercheap_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + watercheappervertexfresnel_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); + } + + SHADER_DRAW + { + // NOTE: Here's what all this means. + // 1) ForceCheap means use env_cubemap only + // 2) ForceExpensive means do real reflection instead of env_cubemap. + // By default, it will do refraction and use env_cubemap for the reflection. + // If dest alpha is available, it will also use dest alpha for a fresnel term. + // otherwise there will be no fresnel term as it looks bizzare. + + bool bBlendReflection = false; + bool bForceCheap = params[FORCECHEAP]->GetIntValue() != 0 || UsingEditor( params ); + bool bForceExpensive = !bForceCheap && (params[FORCEEXPENSIVE]->GetIntValue() != 0); + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); + bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture(); + bool bReflectionUseFresnel = false; + + // Can't do fresnel when forcing cheap or if there's no refraction + if( !bForceCheap ) + { + if( bRefraction ) + { + // NOTE: Expensive reflection does the fresnel correctly per-pixel + if ( g_pHardwareConfig->HasDestAlphaBuffer() && !bReflection && !params[NOFRESNEL]->GetIntValue() ) + { + DrawRefractionForFresnel( params, pShaderShadow, pShaderAPI ); + bReflectionUseFresnel = true; + } + else + { + DrawRefraction( params, pShaderShadow, pShaderAPI ); + } + bBlendReflection = true; + } + if( bReflection ) + { + DrawReflection( params, pShaderShadow, pShaderAPI, bBlendReflection ); + } + } + + // Use $decal to see if we are a decal or not. . if we are, then don't bother + // drawing the cheap version for now since we don't have access to env_cubemap + if( !bReflection && params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) + { + bool bNoPerVertexFresnel = ( params[NOFRESNEL]->GetIntValue() || bReflectionUseFresnel || bForceCheap || !bRefraction ); + DrawCheapWater( params, pShaderShadow, pShaderAPI, bBlendReflection, bReflectionUseFresnel, bNoPerVertexFresnel ); + } + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/water_dx81.cpp b/mp/src/materialsystem/stdshaders/water_dx81.cpp new file mode 100644 index 00000000..764ffe9e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water_dx81.cpp @@ -0,0 +1,311 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" + +#include "water_ps14.inc" +#include "watercheap_vs14.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Water, Water_DX81 ) + +BEGIN_VS_SHADER( Water_DX81, + "Help for Water_DX81" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCALE]->IsDefined() ) + { + params[SCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[FORCEEXPENSIVE]->IsDefined() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + if( !params[FORCEEXPENSIVE]->GetIntValue() && !params[ENVMAP]->IsDefined() ) + { + params[ENVMAP]->SetStringValue( "engine/defaultcubemap" ); + } + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 81 ) + { + return "Water_DX80"; + } + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE ); + } + if (params[ENVMAP]->IsDefined() ) + { + LoadTexture( ENVMAP ); + } + if (params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + } + + inline int GetReflectionRefractionPixelShaderIndex( bool bReflection, bool bRefraction ) + { + // "REFLECT" "0..1" + // "REFRACT" "0..1" + int pshIndex = ( bReflection ? 1 : 0 ) | ( bRefraction ? 2 : 0 ); + return pshIndex; + } + + inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bReflection, bool bRefraction ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( bRefraction ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( bReflection ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + water_ps14_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_ps14", vshIndex.GetIndex() ); + + int pshIndex = GetReflectionRefractionPixelShaderIndex( bReflection, bRefraction ); + pShaderShadow->SetPixelShader ( "Water_ps14", pshIndex ); + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_NORMALIZATION_CUBEMAP ); + if( bRefraction ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTEXTURE, -1 ); + } + BindTexture( SHADER_SAMPLER3, NORMALMAP, BUMPFRAME ); + if( bReflection ) + { + BindTexture( SHADER_SAMPLER4, REFLECTTEXTURE, -1 ); + } + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, REFLECTAMOUNT ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, REFRACTAMOUNT ); + + float c0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + + SetPixelShaderConstant( 1, REFRACTTINT ); + SetPixelShaderConstant( 4, REFLECTTINT ); + + float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + // ERASE ME! + float c3[4] = { 5.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, c3, 1 ); + + // reflection/refraction scale + float reflectionRefractionScale[4] = { params[REFLECTAMOUNT]->GetFloatValue(), + params[REFRACTAMOUNT]->GetFloatValue(), 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 5, reflectionRefractionScale, 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, reflectionRefractionScale, 1 ); + + water_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + enum DrawCheapType_t + { + DRAW_CHEAP_OPAQUE = 0, + DRAW_CHEAP_FRESNEL_OPAQUE, + DRAW_CHEAP_LOD_ONLY, + DRAW_CHEAP_FRESNEL_AND_LOD, + }; + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, DrawCheapType_t type ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + if ( (type != DRAW_CHEAP_OPAQUE) && (type != DRAW_CHEAP_FRESNEL_OPAQUE) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | + VERTEX_TANGENT_T, 1, 0, 0 ); + + watercheap_vs14_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WaterCheap_vs14", vshIndex.GetIndex() ); + + static const char *s_pPixelShader[] = + { + "WaterCheapOpaque_ps14", + "WaterCheapFresnelOpaque_ps14", + "WaterCheap_ps14", + "WaterCheapFresnel_ps14", + }; + + pShaderShadow->SetPixelShader( s_pPixelShader[type] ); + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, NORMALMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER3, ENVMAP, ENVMAPFRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALIZATION_CUBEMAP ); + + float pCheapWaterConstants[4] = { 0, 0, 0, 0 }; + if ( (type != DRAW_CHEAP_OPAQUE) && (type != DRAW_CHEAP_FRESNEL_OPAQUE) ) + { + float flCheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float flCheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + pCheapWaterConstants[0] = flCheapWaterStartDistance; + pCheapWaterConstants[1] = 1.0f / ( flCheapWaterEndDistance - flCheapWaterStartDistance ); + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, pCheapWaterConstants ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + SetPixelShaderConstant( 1, REFLECTTINT, REFLECTBLENDFACTOR ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); + + watercheap_vs14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + // NOTE: Here's what all this means. + // 1) ForceCheap means use env_cubemap only + // 2) ForceExpensive means do real reflection instead of env_cubemap. + // By default, it will do refraction and use env_cubemap for the reflection. + + // Also, it will fade to cheap water at a particular distance, + // based on CheapWaterStartDistance and CheapWaterEndDistance + // * In the ForceCheap case, no fading is required + // * In the default case, it will fade based on these parameters in a single pass + // * In the expensive case, it will have to perform the fade in a separate pass. + + bool bForceCheap = params[FORCECHEAP]->GetIntValue() != 0 || UsingEditor( params ); + bool bForceExpensive = params[FORCEEXPENSIVE]->GetIntValue() != 0; + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); + bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture(); + DrawCheapType_t type = params[NOFRESNEL]->GetIntValue() ? DRAW_CHEAP_OPAQUE : DRAW_CHEAP_FRESNEL_OPAQUE; + if( !bForceCheap && (bRefraction || bReflection) ) + { + DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction ); + if ( !bReflection ) + { + type = params[NOFRESNEL]->GetIntValue() ? DRAW_CHEAP_LOD_ONLY : DRAW_CHEAP_FRESNEL_AND_LOD; + } + else + { + type = DRAW_CHEAP_LOD_ONLY; + } + } + + // Use $decal to see if we are a decal or not. . if we are, then don't bother + // drawing the cheap version for now since we don't have access to env_cubemap + if( params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) && !bReflection ) + { + DrawCheapWater( params, pShaderShadow, pShaderAPI, type ); + } + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/water_ps2x.fxc b/mp/src/materialsystem/stdshaders/water_ps2x.fxc new file mode 100644 index 00000000..a80a8a15 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water_ps2x.fxc @@ -0,0 +1,110 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b] [= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "REFLECT" "0..1" +// STATIC: "REFRACT" "0..1" +// STATIC: "ABOVEWATER" "0..1" +// STATIC: "BLURRY_REFRACT" "0..1" [ps20b] + +// When we turn NORMAL_DECODE_MODE on, this shader only needs 0..1, not 0..2 +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $MULTITEXTURE && $BASETEXTURE + +#if defined(SHADER_MODEL_PS_2_0) +# define BLURRY_REFRACT 0 +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "water_ps2x_helper.h" + + +sampler RefractSampler : register( s0 ); +#if BASETEXTURE +sampler BaseTextureSampler : register( s1 ); +#endif +sampler ReflectSampler : register( s2 ); +#if BASETEXTURE +sampler LightmapSampler : register( s3 ); +#endif +sampler NormalSampler : register( s4 ); + +const HALF4 vRefractTint : register( c1 ); +const HALF4 vReflectTint : register( c4 ); +const float4 g_ReflectRefractScale : register( c5 ); // xy - reflect scale, zw - refract scale +const HALF4 g_WaterFogColor : register( c6 ); +const HALF4 g_WaterFogParams : register( c7 ); + +const float4 g_PixelFogParams : register( c8 ); + + +#define g_WaterFogStart g_WaterFogParams.x +#define g_WaterFogEndMinusStart g_WaterFogParams.y +#define g_Reflect_OverBright g_WaterFogParams.z + +struct PS_INPUT +{ + float2 vBumpTexCoord : TEXCOORD0; + half3 vTangentEyeVect : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float W : TEXCOORD3; + float4 vProjPos : TEXCOORD4; + float screenCoord : TEXCOORD5; +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; +#endif +#if BASETEXTURE +// CENTROID: TEXCOORD6 + HALF4 lightmapTexCoord1And2 : TEXCOORD6; +// CENTROID: TEXCOORD7 + HALF4 lightmapTexCoord3 : TEXCOORD7; +#endif + + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + DrawWater_params_t params; + + params.vBumpTexCoord = i.vBumpTexCoord; +#if MULTITEXTURE + params.vExtraBumpTexCoord = i.vExtraBumpTexCoord; +#endif + params.vReflectXY_vRefractYX = i.vReflectXY_vRefractYX; + params.w = i.W; + params.vReflectRefractScale = g_ReflectRefractScale; + params.fReflectOverbright = g_Reflect_OverBright; + params.vReflectTint = vReflectTint; + params.vRefractTint = vRefractTint; + params.vTangentEyeVect = i.vTangentEyeVect; + params.waterFogColor = g_WaterFogColor; +#if BASETEXTURE + params.lightmapTexCoord1And2 = i.lightmapTexCoord1And2; + params.lightmapTexCoord3 = i.lightmapTexCoord3; +#endif + params.vProjPos = i.vProjPos; + params.pixelFogParams = g_PixelFogParams; + params.fWaterFogStart = g_WaterFogStart; + params.fWaterFogEndMinusStart = g_WaterFogEndMinusStart; + + float4 result; + float fogFactor; + DrawWater( params, + // yay. . can't put sampler in a struct. +#if BASETEXTURE + BaseTextureSampler, + LightmapSampler, +#endif + NormalSampler, RefractSampler, ReflectSampler, + result, fogFactor ); + + return FinalOutput( float4( result.rgb, 1.0f ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.vProjPos.z ); +} + diff --git a/mp/src/materialsystem/stdshaders/water_ps2x_helper.h b/mp/src/materialsystem/stdshaders/water_ps2x_helper.h new file mode 100644 index 00000000..b15b9986 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/water_ps2x_helper.h @@ -0,0 +1,239 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include "common_ps_fxc.h" + +struct DrawWater_params_t +{ + float2 vBumpTexCoord; +#if MULTITEXTURE + float4 vExtraBumpTexCoord; +#endif + float4 vReflectXY_vRefractYX; + float w; + float4 vReflectRefractScale; + float fReflectOverbright; + float4 vReflectTint; + float4 vRefractTint; + half3 vTangentEyeVect; + float4 waterFogColor; +#if BASETEXTURE + HALF4 lightmapTexCoord1And2; + HALF4 lightmapTexCoord3; +#endif + float4 vProjPos; + float4 pixelFogParams; + float fWaterFogStart; + float fWaterFogEndMinusStart; +}; + +void DrawWater( in DrawWater_params_t i, +#if BASETEXTURE + in sampler BaseTextureSampler, + in sampler LightmapSampler, +#endif + in sampler NormalSampler, + in sampler RefractSampler, + in sampler ReflectSampler, + out float4 result, out float fogFactor ) +{ + bool bReflect = REFLECT ? true : false; + bool bRefract = REFRACT ? true : false; + +#if MULTITEXTURE + float4 vNormal = tex2D( NormalSampler, i.vBumpTexCoord ); + float4 vNormal1 = tex2D( NormalSampler, i.vExtraBumpTexCoord.xy ); + float4 vNormal2 = tex2D( NormalSampler, i.vExtraBumpTexCoord.zw ); + vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 ); + +#if ( NORMAL_DECODE_MODE == NORM_DECODE_ATI2N ) + vNormal.xy = vNormal.xy * 2.0f - 1.0f; + vNormal.z = sqrt( 1.0f - dot(vNormal.xy, vNormal.xy) ); + vNormal.a = 1.0f; +#else + vNormal.xyz = 2.0 * vNormal.xyz - 1.0; +#endif + +#else + float4 vNormal = DecompressNormal( NormalSampler, i.vBumpTexCoord, NORMAL_DECODE_MODE ); +#endif + + // Perform division by W only once + float ooW = 1.0f / i.w; + + float2 unwarpedRefractTexCoord = i.vReflectXY_vRefractYX.wz * ooW; + +#if ABOVEWATER + float waterFogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a; +#else + // We don't actually have valid depth values in alpha when we are underwater looking out, so + // just set to farthest value. + float waterFogDepthValue = 1.0f; +#endif + float4 reflectRefractScale = i.vReflectRefractScale; +#if !BASETEXTURE +#if ( BLURRY_REFRACT == 0 ) + reflectRefractScale *= waterFogDepthValue; +#endif +#endif + + // Compute coordinates for sampling Reflection + float2 vReflectTexCoord; + float2 vRefractTexCoord; + + // vectorize the dependent UV calculations (reflect = .xy, refract = .wz) + float4 vN; + vN.xy = vNormal.xy; + vN.w = vNormal.x; + vN.z = vNormal.y; + float4 vDependentTexCoords = vN * vNormal.a * reflectRefractScale; + + vDependentTexCoords += ( i.vReflectXY_vRefractYX * ooW ); + vReflectTexCoord = vDependentTexCoords.xy; + vRefractTexCoord = vDependentTexCoords.wz; + + HALF4 vReflectColor = tex2D( ReflectSampler, vReflectTexCoord ); +#if BLURRY_REFRACT + // Sample reflection and refraction + float2 ddx1=float2(0.005,0); + float2 ddy1=float2(0,0.005); + float4 vRefractColor=float4(0,0,0,0); + +#if 0 + float sumweights=0; + for(int ix=-2;ix<=2;ix++) + { + for(int iy=-2;iy<=2;iy++) + { + float weight=1; ///(1+abs(ix)+abs(iy)); + vRefractColor += weight*tex2D( RefractSampler, vRefractTexCoord+ix*ddx1+iy*ddy1); + sumweights+=weight; + } + } +#else + // NOTE: Generated by genwaterloop.pl in the stdshaders directory. + // Need to unroll for 360 to avoid shader compilation problems. + // Modified genwaterloop.pl and regenerate if you need different params + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 2 * ddy1 ); + float sumweights = 25; + // NOTE: end of generated code. +#endif + + vRefractColor *= (1.0/sumweights); + vReflectColor *= i.fReflectOverbright; + vReflectColor *= i.vReflectTint; + vRefractColor *= i.vRefractTint; +# if ABOVEWATER + // Don't mess with this in the underwater case since we don't really have + // depth values there. + // get the blurred depth value to be used for fog. + waterFogDepthValue = vRefractColor.a; +# endif +#else + vReflectColor *= i.vReflectTint; + HALF4 vRefractColor = tex2D( RefractSampler, vRefractTexCoord ); + // get the depth value from the refracted sample to be used for fog. +# if ABOVEWATER + // Don't mess with this in the underwater case since we don't really have + // depth values there. + waterFogDepthValue = tex2D( RefractSampler, vRefractTexCoord ).a; +# endif +#endif + + half3 vEyeVect; + vEyeVect = normalize( i.vTangentEyeVect ); + + // Fresnel term + HALF fNdotV = saturate( dot( vEyeVect, vNormal ) ); + HALF fFresnel = pow( 1.0 - fNdotV, 5 ); + +#if !BASETEXTURE + // fFresnel == 1.0f means full reflection + fFresnel *= saturate( ( waterFogDepthValue - 0.05f ) * 20.0f ); +#endif + + + // blend between refraction and fog color. +#if ABOVEWATER + vRefractColor = lerp( vRefractColor, i.waterFogColor * LINEAR_LIGHT_SCALE, saturate( waterFogDepthValue - 0.05f ) ); +#else + float waterFogFactor = saturate( ( i.vProjPos.z - i.fWaterFogStart ) / i.fWaterFogEndMinusStart ); + vRefractColor = lerp( vRefractColor, i.waterFogColor * LINEAR_LIGHT_SCALE, waterFogFactor ); +#endif + +#if BASETEXTURE + float4 baseSample = tex2D( BaseTextureSampler, i.vBumpTexCoord.xy ); + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + HALF3 lightmapColor1 = lightmapSample1.rgb; + HALF3 lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + HALF3 lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + + float3 dp; + dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); + dp *= dp; + + float3 diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= LIGHT_MAP_SCALE / sum; + HALF3 diffuseComponent = baseSample.rgb * diffuseLighting; +#endif + + if( bReflect && bRefract ) + { + result = lerp( vRefractColor, vReflectColor, fFresnel ); + } + else if( bReflect ) + { +#if BASETEXTURE + result = float4( diffuseComponent, 1.0f ) + vReflectColor * fFresnel * baseSample.a; +#else + result = vReflectColor; +#endif + } + else if( bRefract ) + { + result = vRefractColor; + } + else + { + result = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + } + +#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE) + fogFactor = CalcRangeFog( i.vProjPos.z, i.pixelFogParams.x, i.pixelFogParams.z, i.pixelFogParams.w ); +#else + fogFactor = 0; +#endif +} diff --git a/mp/src/materialsystem/stdshaders/waterreflect_ps14.psh b/mp/src/materialsystem/stdshaders/waterreflect_ps14.psh new file mode 100644 index 00000000..7104e45c --- /dev/null +++ b/mp/src/materialsystem/stdshaders/waterreflect_ps14.psh @@ -0,0 +1,8 @@ +ps.1.4 + +texld r0, t0_dw.xyw ; sample dudv map + +phase + +texld r0, t0 + diff --git a/mp/src/materialsystem/stdshaders/waterrefract_ps14.psh b/mp/src/materialsystem/stdshaders/waterrefract_ps14.psh new file mode 100644 index 00000000..5b5d1755 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/waterrefract_ps14.psh @@ -0,0 +1,23 @@ +ps.1.4 + +; non-fresnel version +; t0: +; texture: dudv map +; texcoords: coords for normal map +; t1: +; texcoords: uvw for first dp3 +; t2: +; texture: renderable texture that we are going to perturb +; texcoords: uvw for second dp3 +;tex t0 ; sample dudv map +;texm3x2pad t1, t0 ; +;texm3x2tex t2, t0 ; sample renderabletexture + +;mul r0, t2, c1 + + +texld r0, t0 ; sample dudv map + +phase + +texld r0, t2_dw.xyw diff --git a/mp/src/materialsystem/stdshaders/worldtwotextureblend.cpp b/mp/src/materialsystem/stdshaders/worldtwotextureblend.cpp new file mode 100644 index 00000000..542013e0 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldtwotextureblend.cpp @@ -0,0 +1,500 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "convar.h" + +#include "lightmappedgeneric_vs20.inc" +#include "WorldTwoTextureBlend_ps20.inc" +#include "WorldTwoTextureBlend_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern ConVar r_flashlight_version2; + +// FIXME: Need to make a dx9 version so that "CENTROID" works. +BEGIN_VS_SHADER( WorldTwoTextureBlend, + "Help for WorldTwoTextureBlend" ) + +BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) +END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "WorldTwoTextureBlend_DX6"; + + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "WorldTwoTextureBlend_DX8"; + + return 0; + } + + SHADER_INIT_PARAMS() + { + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + { + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + } + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() && params[ALBEDO]->IsDefined() && + params[BASETEXTURE]->IsDefined() && + !( params[NODIFFUSEBUMPLIGHTING]->IsDefined() && params[NODIFFUSEBUMPLIGHTING]->GetIntValue() ) ) + { + params[BASETEXTURE]->SetStringValue( params[ALBEDO]->GetStringValue() ); + } + + if( !params[NODIFFUSEBUMPLIGHTING]->IsDefined() ) + { + params[NODIFFUSEBUMPLIGHTING]->SetIntValue( 0 ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[DETAILFRAME]->IsDefined() ) + { + params[DETAILFRAME]->SetIntValue( 0 ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + } + + SHADER_INIT + { + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + LoadBumpMap( BUMPMAP ); + } + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + // We always need this because of the flashlight. + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + + void DrawPass( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool hasFlashlight, VertexCompressionType_t vertexCompression ) + { + bool hasBump = params[BUMPMAP]->IsTexture(); + bool hasDiffuseBumpmap = hasBump && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0); + bool hasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool hasDetailTexture = /*!hasBump && */params[DETAIL]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) != 0; + bool bHasDetailAlpha = params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() != 0; + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + bool bSeamlessMapping = params[SEAMLESS_SCALE]->GetFloatValue() != 0.0; + + SHADOW_STATE + { + int nShadowFilterMode = 0; + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + if( hasFlashlight ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + } + else + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + + unsigned int flags = VERTEX_POSITION; + if( hasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + // if( hasLightmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ); + } + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + } + if( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + if( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + if( hasVertexColor ) + { + flags |= VERTEX_COLOR; + } + + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + + pShaderShadow->EnableSRGBWrite( true ); + + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, hasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, false ); + SET_STATIC_VERTEX_SHADER_COMBO( RELIEF_MAPPING, 0 ); //( bumpmap_variant == 2 )?1:0); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); //( bumpmap_variant == 2 )?1:0); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); +#endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff. + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + + if( hasFlashlight ) + { + FogToBlack(); + } + else + { + DefaultFog(); + } + } + DYNAMIC_STATE + { + if( hasBaseTexture ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + // if( hasLightmap ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + } + + bool bFlashlightShadows = false; + if( hasFlashlight ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + SetFlashLightColorFromState( state, pShaderAPI ); + + BindTexture( SHADER_SAMPLER2, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() ) + { + BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture ); + } + } + if( hasDetailTexture ) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + } + if( hasBump ) + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER4, BUMPMAP, BUMPFRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT ); + } + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[BASETEXTURETRANSFORM]->MatrixIsIdentity() && + params[BUMPTRANSFORM]->MatrixIsIdentity() ); + + bool bVertexShaderFastPath = !bHasTextureTransform; + if( params[DETAIL]->IsTexture() ) + { + bVertexShaderFastPath = false; + } + if( pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0 ) + { + bVertexShaderFastPath = false; + } + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + if( !( bVertexShaderFastPath && color[0] == 1.0f && color[1] == 1.0f && color[2] == 1.0f && color[3] == 1.0f ) ) + { + bVertexShaderFastPath = false; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + if (! bSeamlessMapping) + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + if( hasBump && !bHasDetailAlpha ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BUMPTRANSFORM ); + Assert( !hasDetailTexture ); + } + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( + LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z) && + (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + } + + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + if( hasDetailTexture ) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, DETAILSCALE ); + Assert( !( hasBump && !bHasDetailAlpha ) ); + } + + SetPixelShaderConstantGammaToLinear( 7, SELFILLUMTINT ); + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 10, eyePos, 1 ); + pShaderAPI->SetPixelShaderFogParams( 11 ); + + if ( bSeamlessMapping ) + { + float map_scale[4]={ params[SEAMLESS_SCALE]->GetFloatValue(),0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + } + + + if( hasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( 20, atten, 1 ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 15, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( 16, worldToTexture.Base(), 4 ); + } + } + Draw(); + } + + SHADER_DRAW + { + bool bHasFlashlight = UsingFlashlight( params ); + if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawPass( params, pShaderAPI, pShaderShadow, false, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState( ); + } + } + DrawPass( params, pShaderAPI, pShaderShadow, bHasFlashlight, vertexCompression ); + } + +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/worldtwotextureblend_dx6.cpp b/mp/src/materialsystem/stdshaders/worldtwotextureblend_dx6.cpp new file mode 100644 index 00000000..3ae6383a --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldtwotextureblend_dx6.cpp @@ -0,0 +1,258 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( WorldTwoTextureBlend, WorldTwoTextureBlend_DX6 ) + + +BEGIN_SHADER( WorldTwoTextureBlend_DX6, + "Help for WorldTwoTextureBlend" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + LoadTexture( DETAIL ); + } + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SHADER_DRAW + { + float detailScale = params[DETAILSCALE]->GetFloatValue(); + + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + return; + } + + // DX6 fallback mode. + if ( params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() ) + { + DetailAlphaMaskPass1( pShaderShadow, pShaderAPI, params, detailScale ); + DetailAlphaMaskPass2( pShaderShadow, pShaderAPI, detailScale ); + } + else + { + // FIXME: add multitexture support! + NormalModePass1( pShaderShadow, pShaderAPI ); + NormalModePass2( pShaderShadow, pShaderAPI, params, detailScale ); + NormalModePass3( pShaderShadow, pShaderAPI, params, detailScale ); + } + } + + + // ------------------------------------------------------------------------------ // + // "Normal" mode - doesn't use the detail texture's alpha mask. + // ------------------------------------------------------------------------------ // + + void NormalModePass1( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + } + + void NormalModePass2( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, + IMaterialVar **params, + float detailScale ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + if ( detailScale != 1.0f ) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE0 ); + pShaderAPI->LoadIdentity(); + pShaderAPI->ScaleXY( detailScale, detailScale ); + } + BindTexture( SHADER_SAMPLER0, DETAIL ); + } + Draw(); + } + + void NormalModePass3( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, + IMaterialVar **params, + float detailScale ) + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + SingleTextureLightmapBlendMode(); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + FogToOOOverbright(); + } + DYNAMIC_STATE + { + if ( detailScale != 1.0f ) + pShaderAPI->LoadIdentity( ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + Draw(); + } + + + // ------------------------------------------------------------------------------ // + // "Detail alpha mask mode". + // ------------------------------------------------------------------------------ // + + void DetailAlphaMaskPass1( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, + IMaterialVar **params, + float detailScale ) + { + // The equation is [B*Da + (1-Da)] * [D * L] + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Stage 0 + // Color = B*2 + // Note the 2x here.. we do 4x total in this shader and + // the first 2x is here. The second is in SingleTextureLightmapBlendMode in the 2nd pass. + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + // Stage 1 [where P = prev stage] + // Color = B*Da + (1-Da) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATEINVCOLOR_ADDALPHA, + SHADER_TEXARG_INVTEXTUREALPHA, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_TEXCOORD1 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, DETAIL ); + + pShaderAPI->Color4f( 1, 1, 1, 1 ); + + if ( detailScale != 1.0f ) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE1 ); + pShaderAPI->LoadIdentity(); + pShaderAPI->ScaleXY( detailScale, detailScale ); + } + + } + Draw(); + } + + void DetailAlphaMaskPass2( IShaderShadow *pShaderShadow, IShaderDynamicAPI *pShaderAPI, float detailScale ) + { + SHADOW_STATE + { + s_pShaderShadow->EnableCustomPixelPipe( true ); + s_pShaderShadow->CustomTextureStages( 2 ); + + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true); + + // Make sure the texgen transform is applied to the texture coordinates and not to an auto-generated reflection vector or whatever. + s_pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_OBJECT_LINEAR ); + + // This turns on blending and does overbrighting if it's enabled. + SingleTextureLightmapBlendMode(); + + // Stage 0, color = D + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + // Stage 1, color = D*L + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_TEXTURE ); + + // Use the lightmap coordinates in both stages. + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_LIGHTMAP_TEXCOORD1 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, DETAIL); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( detailScale != 1.0f ) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE1 ); + pShaderAPI->LoadIdentity(); + + pShaderAPI->MatrixMode( MATERIAL_TEXTURE0 ); + pShaderAPI->LoadIdentity(); + pShaderAPI->ScaleXY( detailScale, detailScale ); + } + } + + Draw(); + } + +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/worldtwotextureblend_dx8.cpp b/mp/src/materialsystem/stdshaders/worldtwotextureblend_dx8.cpp new file mode 100644 index 00000000..a58d9dfb --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldtwotextureblend_dx8.cpp @@ -0,0 +1,175 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "lightmappedgeneric_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( WorldTwoTextureBlend, WorldTwoTextureBlend_DX8 ) + +BEGIN_VS_SHADER( WorldTwoTextureBlend_DX8, + "Help for WorldTwoTextureBlend_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "WorldTwoTextureBlend_DX6"; + + return 0; + } + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + } + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + { + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + const char *GetPixelShaderName( IMaterialVar** params, bool bHasBaseTexture, bool bHasDetailTexture ) + { + bool bSelfIllum = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM); + if ( !bHasBaseTexture ) + { + if ( !bHasDetailTexture ) + return "LightmappedGeneric_NoTexture"; + + return "LightmappedGeneric_DetailNoTexture"; + } + + if ( !bHasDetailTexture ) + { + if ( bSelfIllum ) + return "LightmappedGeneric_SelfIlluminated"; + + return "LightmappedGeneric"; + } + + if ( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() ) + { + if ( bSelfIllum ) + return "WorldTwoTextureBlend_SelfIlluminated"; + + return "WorldTwoTextureBlend"; + } + + return "WorldTwoTextureBlend_DetailAlpha"; + } + + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + return; + } + + bool bHasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool bHasDetailTexture = params[DETAIL]->IsTexture(); + bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + + SHADOW_STATE + { + if ( bHasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( bHasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + pShaderShadow->EnableBlending( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, 0, 0 ); + + // Let the shaders do the fun stuff. + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( bHasDetailTexture ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( bHasVertexColor ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pPixelShaderName = GetPixelShaderName( params, bHasBaseTexture, bHasDetailTexture ); + pShaderShadow->SetPixelShader( pPixelShaderName ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + if ( bHasBaseTexture ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( bHasDetailTexture ) + { + BindTexture( SHADER_SAMPLER2, DETAIL ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + } + + SetModulationVertexShaderDynamicState(); + + // Dynamic vertex shader index. + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + } + Draw(); + } + +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc b/mp/src/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc new file mode 100644 index 00000000..b81fa7bd --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc @@ -0,0 +1,217 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "BUMPMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "DETAIL_ALPHA_MASK_BASE_TEXTURE" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] + +// SKIP: $DETAILTEXTURE && ( $BUMPMAP && !$DETAIL_ALPHA_MASK_BASE_TEXTURE ) +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: $VERTEXCOLOR && $BUMPMAP +// SKIP: FLASHLIGHT && $SELFILLUM +// SKIP: FLASHLIGHT && $DETAIL_ALPHA_MASK_BASE_TEXTURE +// SKIP: FLASHLIGHT && ($BUMPMAP || $DIFFUSEBUMPMAP) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + + +#define HDRTYPE HDR_TYPE_NONE +#include "common_flashlight_fxc.h" +#include "common_ps_fxc.h" + +const HALF4 g_SelfIllumTint : register( c7 ); +static const HALF g_OverbrightFactor = 2.0f; + +const HALF3 g_EyePos : register( c10 ); +const HALF4 g_FogParams : register( c11 ); + +const HALF3 g_FlashlightPos : register( c15 ); +// flashlightfixme: Move this math into the vertex shader. +const float4x4 g_FlashlightWorldToTexture : register( c16 ); + +const float4 g_FlashlightAttenuationFactors : register( c20 ); + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler FlashlightSampler : register( s2 ); +sampler DetailSampler : register( s3 ); +sampler BumpmapSampler : register( s4 ); +sampler NormalizeSampler : register( s6 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; + HALF4 detailOrBumpTexCoord : TEXCOORD1; + HALF4 lightmapTexCoord1And2 : TEXCOORD2; // CENTROID: TEXCOORD2 + HALF2 lightmapTexCoord3 : TEXCOORD3; // CENTROID: TEXCOORD3 + HALF4 worldPos_projPosZ : TEXCOORD4; + HALF3x3 tangentSpaceTranspose : TEXCOORD5; + // tangentSpaceTranspose : TEXCOORD6; + // tangentSpaceTranspose : TEXCOORD7; + HALF4 vertexColor : COLOR; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBumpmap = BUMPMAP ? true : false; + bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false; + bool bVertexColor = VERTEXCOLOR ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE ? true : false; + bool bFlashlight = FLASHLIGHT ? true : false; + + HALF3 lightmapColor1 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor2 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor3 = HALF3( 1.0f, 1.0f, 1.0f ); + if( bBumpmap && bDiffuseBumpmap ) + { + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + lightmapColor1 = lightmapSample1.rgb; + lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + } + else + { + if( !bFlashlight ) + { + HALF2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + lightmapColor1 = lightmapSample1.rgb; + } + } + + HALF4 detailColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bDetailTexture ) + { + detailColor = tex2D( DetailSampler, i.detailOrBumpTexCoord.xy ); + } + + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + if ( bDetailAlphaMaskBaseTexture ) + { + // This is what WorldTwoTextureBlend_DX6 does. + baseColor.rgb = saturate( saturate( baseColor * 2 ) * detailColor.a + (1 - detailColor.a) ); + baseColor.rgb *= detailColor; + } + else + { + baseColor.rgb = lerp( baseColor, detailColor, detailColor.a ); + } + + HALF3 normal = HALF3( 0.0f, 0.0f, 1.0f ); + if( bBumpmap ) + { + HALF3 normalTexel; + normalTexel = tex2D( BumpmapSampler, i.detailOrBumpTexCoord.xy ); + normal = 2.0 * normalTexel - 1.0; + } + + HALF3 albedo = HALF3( 1.0f, 1.0f, 1.0f ); + HALF alpha = 1.0f; + albedo *= baseColor; + if( !bSelfIllum ) + { + alpha *= baseColor.a; + } + + // The vertex color contains the modulation color + vertex color combined + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + HALF3 diffuseLighting; + if( bFlashlight ) + { + float3 worldSpaceNormal; + // Make the unbumped version not so fucking stupid and not need tangentSpaceTranspose you knob. + worldSpaceNormal = mul( normal, i.tangentSpaceTranspose ); + + int nShadowSampleLevel = 0; + bool bDoShadows = false; +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = true; +#endif + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); + + diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, FlashlightSampler, NormalizeSampler, + nShadowSampleLevel, bDoShadows, false, float2(0, 0), false ); + } + else + { + if( bBumpmap && bDiffuseBumpmap ) + { + float dot1 = saturate( dot( normal, bumpBasis[0] ) ); + float dot2 = saturate( dot( normal, bumpBasis[1] ) ); + float dot3 = saturate( dot( normal, bumpBasis[2] ) ); + + float sum = dot1 + dot2 + dot3; + diffuseLighting = dot1 * lightmapColor1 + + dot2 * lightmapColor2 + + dot3 * lightmapColor3; + diffuseLighting *= 1.0f / sum; + } + else + { + diffuseLighting = lightmapColor1; + } + + // Only scale here since the flashlight will already be scaled properly + diffuseLighting *= g_OverbrightFactor; + } + + HALF3 diffuseComponent = albedo * diffuseLighting; + + if( bSelfIllum ) + { + HALF3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + HALF3 result = diffuseComponent + specularLighting; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} + diff --git a/mp/src/materialsystem/stdshaders/worldvertexalpha.cpp b/mp/src/materialsystem/stdshaders/worldvertexalpha.cpp new file mode 100644 index 00000000..85bad1c1 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertexalpha.cpp @@ -0,0 +1,259 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "WorldVertexAlpha.inc" +#include "worldvertexalpha_ps20.inc" +#include "worldvertexalpha_ps20b.inc" + +BEGIN_VS_SHADER( WorldVertexAlpha, + "Help for WorldVertexAlpha" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + SET_FLAGS2( MATERIAL_VAR2_BLEND_WITH_LIGHTMAP_ALPHA ); + } + SHADER_INIT + { + // Load the base texture here! + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { +// if( g_pHardwareConfig->GetDXSupportLevel() < 90 || g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "WorldVertexAlpha_DX8"; + } + return 0; + } + + SHADER_DRAW + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() && !UsingEditor( params ) ) + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + // NOTE: This is the DX8, Non-Hammer version. + + SHADOW_STATE + { + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WorldVertexAlpha" ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + Draw(); + } + else + { + // DX 9 version with HDR support + + // Pass 1 + SHADOW_STATE + { + SetInitialShadowState(); + + pShaderShadow->EnableAlphaWrites( true ); + + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 0 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 0 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + } + Draw(); + + // Pass 2 + SHADOW_STATE + { + SetInitialShadowState(); + + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( false ); + + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 1 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 1 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + } + Draw(); + } + } + else + { + // NOTE: This is the DX7, Hammer version. + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); +// pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + // Use vertex color for Hammer because it puts the blending alpha in the vertices. + unsigned int colorFlag = 0; + if( UsingEditor( params ) ) + { + colorFlag |= SHADER_DRAW_COLOR; + } + + pShaderShadow->DrawFlags( colorFlag | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | + SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + + Draw(); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/worldvertexalpha_dx8.cpp b/mp/src/materialsystem/stdshaders/worldvertexalpha_dx8.cpp new file mode 100644 index 00000000..0ea139ee --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertexalpha_dx8.cpp @@ -0,0 +1,113 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "worldvertexalpha.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WorldVertexAlpha, WorldVertexAlpha_DX8 ) + +BEGIN_VS_SHADER( WorldVertexAlpha_DX8, + "Help for WorldVertexAlpha_DX8" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + SHADER_INIT + { + // Load the base texture here! + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() && !UsingEditor( params ) ) + { + // NOTE: This is the DX8, Non-Hammer version. + + SHADOW_STATE + { + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WorldVertexAlpha" ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + EnablePixelShaderOverbright( 0, true, true ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + Draw(); + } + else + { + // NOTE: This is the DX7, Hammer version. + // FIXME: Gary - you need to write a proper non-fixed function shader for this. + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); +// pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + // Use vertex color for Hammer because it puts the blending alpha in the vertices. + unsigned int colorFlag = 0; + if( UsingEditor( params ) ) + { + colorFlag |= SHADER_DRAW_COLOR; + } + + pShaderShadow->DrawFlags( colorFlag | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | + SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + + Draw(); + } + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/worldvertextransition.cpp b/mp/src/materialsystem/stdshaders/worldvertextransition.cpp new file mode 100644 index 00000000..e7d6a9ab --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertextransition.cpp @@ -0,0 +1,157 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "worldvertextransition_dx8_helper.h" +#include "lightmappedgeneric_dx9_helper.h" + +static LightmappedGeneric_DX9_Vars_t s_info; + + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX9 ) + +BEGIN_VS_SHADER( WorldVertexTransition_DX9, "Help for WorldVertexTransition" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( BUMPMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( BUMPMASK, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $basetexture2" ) + SHADER_PARAM( BASETEXTURENOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BASETEXTURE2NOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "light munging lookup texture" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + SHADER_PARAM( MASKEDBLENDING, SHADER_PARAM_TYPE_INTEGER, "0", "blend using texture with no vertex alpha. For using texture blending on non-displacements" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + END_SHADER_PARAMS + + void SetupVars( WorldVertexTransitionEditor_DX8_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTextureTransformVar = BASETEXTURETRANSFORM; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nBaseTexture2FrameVar = FRAME2; + info.m_nBaseTexture2TransformVar = BASETEXTURETRANSFORM; // FIXME!!!! + } + + void SetupVars( LightmappedGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTint = DETAILTINT; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoDiffuseBumpLighting = NODIFFUSEBUMPLIGHTING; + info.m_nBumpmap2 = BUMPMAP2; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nBaseTexture2Frame = FRAME2; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBumpMask = BUMPMASK; + info.m_nBaseTextureNoEnvmap = BASETEXTURENOENVMAP; + info.m_nBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP; + info.m_nDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nLightWarpTexture = LIGHTWARPTEXTURE; + info.m_nBlendModulateTexture = BLENDMODULATETEXTURE; + info.m_nBlendMaskTransform = BLENDMASKTRANSFORM; + info.m_nMaskedBlending = MASKEDBLENDING; + info.m_nSelfShadowedBumpFlag = SSBUMP; + info.m_nSeamlessMappingScale = SEAMLESS_SCALE; + info.m_nAlphaTestReference = -1; + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "WorldVertexTransition_DX8"; + + return 0; + } + + SHADER_INIT_PARAMS() + { + SetupVars( s_info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); + } + + SHADER_INIT + { + SetupVars( s_info ); + InitLightmappedGeneric_DX9( this, params, s_info ); + } + + SHADER_DRAW + { + if ( UsingEditor( params ) ) + { + WorldVertexTransitionEditor_DX8_Vars_t info; + SetupVars( info ); + DrawWorldVertexTransitionEditor_DX8( this, params, pShaderAPI, pShaderShadow, info ); + return; + } + + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + } +END_SHADER + diff --git a/mp/src/materialsystem/stdshaders/worldvertextransition_dx6.cpp b/mp/src/materialsystem/stdshaders/worldvertextransition_dx6.cpp new file mode 100644 index 00000000..163291e3 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertextransition_dx6.cpp @@ -0,0 +1,52 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +#include "worldvertextransition_dx6_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX6 ) + +BEGIN_SHADER( WorldVertexTransition_DX6, + "Help for WorldVertexTransition_dx6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture2", "base texture2 help" ) + END_SHADER_PARAMS + + void SetupVars( WorldVertexTransition_DX6_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nFlashlightTextureVar = FLASHLIGHTTEXTURE; + } + + SHADER_INIT_PARAMS() + { + WorldVertexTransition_DX6_Vars_t info; + SetupVars( info ); + InitParamsWorldVertexTransition_DX6( params, info ); + } + + SHADER_INIT + { + WorldVertexTransition_DX6_Vars_t info; + SetupVars( info ); + InitWorldVertexTransition_DX6( this, params, info ); + } + + SHADER_DRAW + { + WorldVertexTransition_DX6_Vars_t info; + SetupVars( info ); + DrawWorldVertexTransition_DX6( this, params, pShaderAPI, pShaderShadow, info ); + } +END_SHADER diff --git a/mp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.cpp b/mp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.cpp new file mode 100644 index 00000000..7539ff29 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.cpp @@ -0,0 +1,206 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "shaderlib/cshader.h" +#include "worldvertextransition_dx6_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +void InitParamsWorldVertexTransition_DX6( IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + // FLASHLIGHTFIXME + params[info.m_nFlashlightTextureVar]->SetStringValue( "effects/flashlight001" ); +} + +void InitWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ) +{ + // FLASHLIGHTFIXME + if ( params[info.m_nFlashlightTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFlashlightTextureVar ); + } + + if ( params[info.m_nBaseTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTextureVar ); + } + + if ( params[info.m_nBaseTexture2Var]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2Var ); + } +} + +static void DrawFlashlightPass( CBaseShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, int nPass, WorldVertexTransition_DX6_Vars_t &info ) +{ + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->SetDiffuseMaterialSource( SHADER_MATERIALSOURCE_COLOR1 ); + if( nPass == 0 ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + } + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_COLOR | SHADER_DRAW_NORMAL; + pShaderShadow->DrawFlags( flags ); + pShader->FogToBlack(); + + pShaderShadow->EnableLighting( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // color stage 0 + // projected texture * vertex color (lighting) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + // color stage 1 + // * base texture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + // alpha stage 0 + // get alpha from constant alpha * vertex color + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_VERTEXCOLOR ); + + // alpha stage 1 + // get alpha from $basetexture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Shove the view position into texcoord 0 before the texture matrix. + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + } + DYNAMIC_STATE + { + pShader->SetFlashlightFixedFunctionTextureTransform( MATERIAL_TEXTURE0 ); + + // NOTE: This has to come after the loadmatrix since the loadmatrix screws with the + // transform flags!!!!!! + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 3, true ); + + pShader->BindTexture( SHADER_SAMPLER0, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + if( nPass == 0 ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var, -1 ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTextureVar, info.m_nBaseTextureFrameVar ); + } + } + pShader->Draw(); +} + + +void DrawWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransition_DX6_Vars_t &info ) +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if( bHasFlashlight ) + { + DrawFlashlightPass( pShader, params, pShaderAPI, pShaderShadow, 0, info ); + DrawFlashlightPass( pShader, params, pShaderAPI, pShaderShadow, 1, info ); + return; + } + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->DrawFlags( SHADER_DRAW_COLOR | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + //pShaderAPI->TexMinFilter( SHADER_TEXFILTERMODE_NEAREST ); + //pShaderAPI->TexMagFilter( SHADER_TEXFILTERMODE_NEAREST ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTextureVar ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + pShader->Draw(); + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableBlending( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // alpha and color stage 0 + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_TEXTURE ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_TEXTURE ); + + // alpha and color stage 1 + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_PREVIOUSSTAGE, + SHADER_TEXARG_TEXTURE ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + pShaderShadow->DrawFlags( SHADER_DRAW_COLOR | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + pShader->Draw(); +} diff --git a/mp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.h b/mp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.h new file mode 100644 index 00000000..16e0bfd5 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.h @@ -0,0 +1,39 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef WORLDVERTEXTRANSITION_DX6_HELPER_H +#define WORLDVERTEXTRANSITION_DX6_HELPER_H + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct WorldVertexTransition_DX6_Vars_t +{ + WorldVertexTransition_DX6_Vars_t() { memset( this, 0xFF, sizeof(WorldVertexTransition_DX6_Vars_t) ); } + + int m_nBaseTextureVar; + int m_nBaseTextureFrameVar; + int m_nBaseTexture2Var; + int m_nFlashlightTextureVar; +}; + +void InitParamsWorldVertexTransition_DX6( IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ); +void InitWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ); +void DrawWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransition_DX6_Vars_t &info ); + + +#endif // WORLDVERTEXTRANSITION_DX6_HELPER_H \ No newline at end of file diff --git a/mp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp b/mp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp new file mode 100644 index 00000000..6a49fd71 --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "worldvertextransition_dx8_helper.h" +#include "BaseVSShader.h" + +#include "WorldVertexTransition.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +void InitParamsWorldVertexTransitionEditor_DX8( IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); +} + +void InitWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + if ( params[info.m_nBaseTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTextureVar ); + } + + if ( params[info.m_nBaseTexture2Var]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2Var ); + } +} + +void DrawWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + SHADOW_STATE + { + // This is the dx8 worldcraft version (non-bumped always.. too bad) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION | VERTEX_COLOR; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "WorldVertexTransition_Editor" ); + + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTextureVar, info.m_nBaseTextureFrameVar ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var, info.m_nBaseTexture2FrameVar ); + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + + pShader->EnablePixelShaderOverbright( 0, true, true ); + + // JasonM - Gnarly hack since we're calling this legacy shader from DX9 + int nTextureTransformConst = VERTEX_SHADER_SHADER_SPECIFIC_CONST_0; + int nTextureTransformConst2 = VERTEX_SHADER_SHADER_SPECIFIC_CONST_2; + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + nTextureTransformConst -= 10; + nTextureTransformConst2 -= 10; + } + + pShader->SetVertexShaderTextureTransform( nTextureTransformConst, info.m_nBaseTextureTransformVar ); + pShader->SetVertexShaderTextureTransform( nTextureTransformConst2, info.m_nBaseTexture2TransformVar ); + + worldvertextransition_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + pShader->Draw(); +} diff --git a/mp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.h b/mp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.h new file mode 100644 index 00000000..d17d532e --- /dev/null +++ b/mp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.h @@ -0,0 +1,44 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef WORLDVERTEXTRANSITION_DX8_HELPER_H +#define WORLDVERTEXTRANSITION_DX8_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct WorldVertexTransitionEditor_DX8_Vars_t +{ + WorldVertexTransitionEditor_DX8_Vars_t() { memset( this, 0xFF, sizeof(WorldVertexTransitionEditor_DX8_Vars_t) ); } + + int m_nBaseTextureVar; + int m_nBaseTextureFrameVar; + int m_nBaseTextureTransformVar; + int m_nBaseTexture2Var; + int m_nBaseTexture2FrameVar; + int m_nBaseTexture2TransformVar; +}; + +void InitParamsWorldVertexTransitionEditor_DX8( IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ); +void InitWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ); +void DrawWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransitionEditor_DX8_Vars_t &info ); + + +#endif // WORLDVERTEXTRANSITION_DX8_HELPER_H \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/BlurFilterX.cpp b/sp/src/materialsystem/stdshaders/BlurFilterX.cpp new file mode 100644 index 00000000..f462423a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilterX.cpp @@ -0,0 +1,122 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "BlurFilter_vs20.inc" +#include "BlurFilter_ps20.inc" +#include "BlurFilter_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( BlurFilterX, "Help for BlurFilterX", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "BlurFilterX_DX80"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Render targets are pegged as sRGB on POSIX, so just force these reads and writes + bool bForceSRGBReadAndWrite = IsOSX() && g_pHardwareConfig->CanDoSRGBReadFromRTs(); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bForceSRGBReadAndWrite ); + pShaderShadow->EnableSRGBWrite( bForceSRGBReadAndWrite ); + + // Pre-cache shaders + blurfilter_vs20_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "BlurFilter_vs20", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20b ); +#ifndef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( APPROX_SRGB_ADAPTER, bForceSRGBReadAndWrite ); +#endif + SET_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + float v[4]; + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + int width = src_texture->GetActualWidth(); + float dX = 1.0f / width; + + // Tap offsets + v[0] = 1.3366f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = 3.4295f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = 5.4264f * dX; + v[1] = 0.0f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + + v[0] = 7.4359f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + v[0] = 9.4436f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 1, v, 1 ); + v[0] = 11.4401f * dX; + v[1] = 0.0f; + pShaderAPI->SetPixelShaderConstant( 2, v, 1 ); + v[0] = v[1] = v[2] = v[3] = 1.0; + pShaderAPI->SetPixelShaderConstant( 3, v, 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/BlurFilterX_dx80.cpp b/sp/src/materialsystem/stdshaders/BlurFilterX_dx80.cpp new file mode 100644 index 00000000..6eecfef2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilterX_dx80.cpp @@ -0,0 +1,86 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( BlurFilterX, BlurFilterX_DX80 ) + +BEGIN_VS_SHADER_FLAGS( BlurFilterX_DX80, "Help for BlurFilterX_DX80", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT + { + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + { + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Pre-cache shaders + pShaderShadow->SetVertexShader( "BlurFilter_vs11", 0 ); + pShaderShadow->SetPixelShader( "BlurFilter_ps11", 0 ); + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER3, BASETEXTURE, -1 ); + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture=params[BASETEXTURE]->GetTextureValue(); + int width = src_texture->GetActualWidth(); + float dX = 2.0f / width; + + // 4 Tap offsets, expected from pixel center + float v[4][4]; + v[0][0] = -1.5f * dX; + v[0][1] = 0; + v[1][0] = -0.5f * dX; + v[1][1] = 0; + v[2][0] = 0.5f * dX; + v[2][1] = 0; + v[3][0] = 1.5f * dX; + v[3][1] = 0; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &v[0][0], 4 ); + + v[0][0] = v[0][1] = v[0][2] = v[0][3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 1, v[0], 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/BlurFilterY.cpp b/sp/src/materialsystem/stdshaders/BlurFilterY.cpp new file mode 100644 index 00000000..57db29c0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilterY.cpp @@ -0,0 +1,136 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "BlurFilter_vs20.inc" +#include "BlurFilter_ps20.inc" +#include "BlurFilter_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( BlurFilterY, "Help for BlurFilterY", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( FRAMETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( !( params[BLOOMAMOUNT]->IsDefined() ) ) + { + params[BLOOMAMOUNT]->SetFloatValue( 1.0 ); + } + } + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "BlurFilterY_DX80"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Render targets are pegged as sRGB on POSIX, so just force these reads and writes + bool bForceSRGBReadAndWrite = IsOSX() && g_pHardwareConfig->CanDoSRGBReadFromRTs(); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bForceSRGBReadAndWrite ); + pShaderShadow->EnableSRGBWrite( bForceSRGBReadAndWrite ); + + // Pre-cache shaders + DECLARE_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + SET_STATIC_VERTEX_SHADER( blurfilter_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20b ); +#ifndef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( APPROX_SRGB_ADAPTER, bForceSRGBReadAndWrite ); +#endif + SET_STATIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_STATIC_PIXEL_SHADER( blurfilter_ps20 ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + + // The temp buffer is 1/4 back buffer size + ITexture *src_texture = params[BASETEXTURE]->GetTextureValue(); + int height = src_texture->GetActualWidth(); + float dY = 1.0f / height; +// dY *= 0.4; + float v[4]; + + // Tap offsets + v[0] = 0.0f; + v[1] = 1.3366f * dY; + v[2] = 0; + v[3] = 0; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, v, 1 ); + v[0] = 0.0f; + v[1] = 3.4295f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, v, 1 ); + v[0] = 0.0f; + v[1] = 5.4264f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, v, 1 ); + + v[0] = 0.0f; + v[1] = 7.4359f * dY; + pShaderAPI->SetPixelShaderConstant( 0, v, 1 ); + v[0] = 0.0f; + v[1] = 9.4436f * dY; + pShaderAPI->SetPixelShaderConstant( 1, v, 1 ); + v[0] = 0.0f; + v[1] = 11.4401f * dY; + pShaderAPI->SetPixelShaderConstant( 2, v, 1 ); + + v[0]=v[1]=v[2]=params[BLOOMAMOUNT]->GetFloatValue(); + + pShaderAPI->SetPixelShaderConstant( 3, v, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_VERTEX_SHADER( blurfilter_ps20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( blurfilter_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/BlurFilterY_dx80.cpp b/sp/src/materialsystem/stdshaders/BlurFilterY_dx80.cpp new file mode 100644 index 00000000..5e01d608 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilterY_dx80.cpp @@ -0,0 +1,91 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( BlurFilterY, BlurFilterY_DX80 ) + +BEGIN_VS_SHADER_FLAGS( BlurFilterY_DX80, "Help for BlurFilterY_DX80", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BLOOMAMOUNT, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( FRAMETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_SmallHDR0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if ( !( params[BLOOMAMOUNT]->IsDefined() ) ) + params[BLOOMAMOUNT]->SetFloatValue(1.0); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + { + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + // Pre-cache shaders + pShaderShadow->SetVertexShader( "BlurFilter_vs11", 0 ); + pShaderShadow->SetPixelShader( "BlurFilter_ps11", 0 ); + + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, -1 ); + BindTexture( SHADER_SAMPLER3, BASETEXTURE, -1 ); + + int width, height; + pShaderAPI->GetBackBufferDimensions( width, height ); + + // The temp buffer is 1/4 back buffer size + float dY = 2.0f / height; + + // 4 Tap offsets, expected from pixel center + float v[4][4]; + v[0][0] = 0; + v[0][1] = -1.5f * dY; + v[1][0] = 0; + v[1][1] = -0.5f * dY; + v[2][0] = 0; + v[2][1] = 0.5f * dY; + v[3][0] = 0; + v[3][1] = 1.5f * dY; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &v[0][0], 4 ); + + v[0][0] = v[0][1] = v[0][2] = params[BLOOMAMOUNT]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, v[0], 1 ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + pShaderAPI->SetPixelShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/BlurFilter_ps11.psh b/sp/src/materialsystem/stdshaders/BlurFilter_ps11.psh new file mode 100644 index 00000000..6bc9bc57 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilter_ps11.psh @@ -0,0 +1,18 @@ +ps.1.1 + +// 1221 filter constants +def c0, 0.1667f, 0.1667f, 0.1667f, 0.3333f + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0.rgb, t0, c0 +mad r0.rgb, t1, c0.a, r0 +mad r0.rgb, t2, c0.a, r0 +mad r0.rgb, t3, c0, r0 + +mul r0.rgb, r0, c1 + +mov r0.a, t0.a + diff --git a/sp/src/materialsystem/stdshaders/BlurFilter_ps2x.fxc b/sp/src/materialsystem/stdshaders/BlurFilter_ps2x.fxc new file mode 100644 index 00000000..bfd082b3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilter_ps2x.fxc @@ -0,0 +1,91 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "APPROX_SRGB_ADAPTER" "0..1" [ps20b] [PC] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; + float2 coordTap1Neg : TEXCOORD4; + float2 coordTap2Neg : TEXCOORD5; + float2 coordTap3Neg : TEXCOORD6; +}; + +float2 psTapOffs[3] : register( c0 ); +float3 scale_factor : register( c3 ); + +float4 SampleTexture( sampler texSampler, float2 uv ) +{ + float4 cSample = tex2D( texSampler, uv ); + + #if ( APPROX_SRGB_ADAPTER ) + { + cSample.rgb = max( cSample.rgb, float3( 0.00001f, 0.00001f, 0.00001f ) ); // rsqrt doesn't like inputs of zero + + float3 ooSQRT; // + ooSQRT.r = rsqrt( cSample.r ); // + ooSQRT.g = rsqrt( cSample.g ); // Approximate linear-to-sRGB conversion + ooSQRT.b = rsqrt( cSample.b ); // + cSample.rgb *= ooSQRT.rgb; // + } + #endif + + return cSample; +} + +float4 main( PS_INPUT i ) : COLOR +{ + float4 s0, s1, s2, s3, s4, s5, s6, color; + + // Sample taps with coordinates from VS + s0 = SampleTexture( TexSampler, i.coordTap0 ); + s1 = SampleTexture( TexSampler, i.coordTap1 ); + s2 = SampleTexture( TexSampler, i.coordTap2 ); + s3 = SampleTexture( TexSampler, i.coordTap3 ); + s4 = SampleTexture( TexSampler, i.coordTap1Neg ); + s5 = SampleTexture( TexSampler, i.coordTap2Neg ); + s6 = SampleTexture( TexSampler, i.coordTap3Neg ); + + color = s0 * 0.2013f; + color += ( s1 + s4 ) * 0.2185f; + color += ( s2 + s5 ) * 0.0821f; + color += ( s3 + s6 ) * 0.0461f; + + // Compute tex coords for other taps + float2 coordTap4 = i.coordTap0 + psTapOffs[0]; + float2 coordTap5 = i.coordTap0 + psTapOffs[1]; + float2 coordTap6 = i.coordTap0 + psTapOffs[2]; + float2 coordTap4Neg = i.coordTap0 - psTapOffs[0]; + float2 coordTap5Neg = i.coordTap0 - psTapOffs[1]; + float2 coordTap6Neg = i.coordTap0 - psTapOffs[2]; + + // Sample the taps + s1 = SampleTexture( TexSampler, coordTap4 ); + s2 = SampleTexture( TexSampler, coordTap5 ); + s3 = SampleTexture( TexSampler, coordTap6 ); + s4 = SampleTexture( TexSampler, coordTap4Neg ); + s5 = SampleTexture( TexSampler, coordTap5Neg ); + s6 = SampleTexture( TexSampler, coordTap6Neg ); + + color += ( s1 + s4 ) * 0.0262f; + color += ( s2 + s5 ) * 0.0162f; + color += ( s3 + s6 ) * 0.0102f; + color.xyz*=scale_factor.xyz; + + #if ( APPROX_SRGB_ADAPTER ) + { + color.xyz *= color.xyz; // Approximate sRGB-to-linear conversion + } + #endif + + return color; + //return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/sp/src/materialsystem/stdshaders/BlurFilter_vs11.fxc b/sp/src/materialsystem/stdshaders/BlurFilter_vs11.fxc new file mode 100644 index 00000000..0a213522 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilter_vs11.fxc @@ -0,0 +1,34 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; +}; + +float2 vsTapOffs[4] : register ( SHADER_SPECIFIC_CONST_0 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + + o.coordTap0 = v.vBaseTexCoord + vsTapOffs[0]; + o.coordTap1 = v.vBaseTexCoord + vsTapOffs[1]; + o.coordTap2 = v.vBaseTexCoord + vsTapOffs[2]; + o.coordTap3 = v.vBaseTexCoord + vsTapOffs[3]; + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/BlurFilter_vs20.fxc b/sp/src/materialsystem/stdshaders/BlurFilter_vs20.fxc new file mode 100644 index 00000000..3c37fa74 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/BlurFilter_vs20.fxc @@ -0,0 +1,39 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 coordTap0 : TEXCOORD0; + float2 coordTap1 : TEXCOORD1; + float2 coordTap2 : TEXCOORD2; + float2 coordTap3 : TEXCOORD3; + float2 coordTap1Neg : TEXCOORD4; + float2 coordTap2Neg : TEXCOORD5; + float2 coordTap3Neg : TEXCOORD6; +}; + +float2 vsTapOffs[3] : register ( SHADER_SPECIFIC_CONST_0 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = float4( v.vPos, 1.0f ); + o.coordTap0 = v.vBaseTexCoord; + o.coordTap1 = v.vBaseTexCoord + vsTapOffs[0]; + o.coordTap2 = v.vBaseTexCoord + vsTapOffs[1]; + o.coordTap3 = v.vBaseTexCoord + vsTapOffs[2]; + o.coordTap1Neg = v.vBaseTexCoord - vsTapOffs[0]; + o.coordTap2Neg = v.vBaseTexCoord - vsTapOffs[1]; + o.coordTap3Neg = v.vBaseTexCoord - vsTapOffs[2]; + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/Cable.psh b/sp/src/materialsystem/stdshaders/Cable.psh new file mode 100644 index 00000000..a73b1130 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Cable.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; See the vertex shader for info +; +; This shader takes: +; t0 = normal map +; t1 = base texture +; v0 = directional light color +; t2 = directional light direction (biased into 0-1) +; c0 = percent of dirlight to add as ambient +; +; Output: +; (t0 dot t1) * v0 +;------------------------------------------------------------------------------ + +tex t0 ; Get the 3-vector from the normal map +tex t1 ; Interpret tcoord t1 as color data. +texcoord t2 + +dp3 r1, t0_bx2, t2_bx2 ; r1 = normalMap dot dirLightDir +add r0, r1, c0 ; + 0.5 + +mul r1, v0, r0 ; scale the dot product by the dirlight's actual color +mul r0.rgb, r1, t1 + ; scale by the texture color + +mul r0.a, t1.a, v0.a diff --git a/sp/src/materialsystem/stdshaders/Cable.vsh b/sp/src/materialsystem/stdshaders/Cable.vsh new file mode 100644 index 00000000..857a2e3b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Cable.vsh @@ -0,0 +1,117 @@ +vs.1.1 + +#include "macros.vsh" + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; The cable equation is: +; [L dot N] * C * T +; +; where: +; C = directional light color +; T = baseTexture +; N = particle normal (stored in the normal map) +; L = directional light direction +; +; $SHADER_SPECIFIC_CONST_0 = Directional light direction +;------------------------------------------------------------------------------ + + +;------------------------------------------------------------------------------ +; Transform position from object to projection space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Setup the tangent space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$tmp1 ); +&AllocateRegister( \$tmp2 ); +&AllocateRegister( \$tmp3 ); +&AllocateRegister( \$r ); + +; Get S crossed with T (call it R) +mov $tmp1, $vTangentS +mov $tmp2, $vTangentT + +mul $tmp3, $vTangentS.yzxw, $tmp2.zxyw +mad $r, -$vTangentS.zxyw, $tmp2.yzxw, $tmp3 + +&FreeRegister( \$tmp2 ); +&FreeRegister( \$tmp3 ); + +&AllocateRegister( \$s ); + +; Normalize S (into $s) +dp3 $s.w, $vTangentS, $vTangentS +rsq $s.w, $s.w +mul $s.xyz, $vTangentS, $s.w + +; Normalize R (into $r) +dp3 $r.w, $r, $r +rsq $r.w, $r.w +mul $r.xyz, $r, $r.w + +&AllocateRegister( \$t ); + +; Regenerate T (into $t) +mul $t, $r.yzxw, $tmp1.zxyw +mad $t, -$r.zxyw, $tmp1.yzxw, $t + +&FreeRegister( \$tmp1 ); + +;------------------------------------------------------------------------------ +; Transform the light direction (into oD1) +;------------------------------------------------------------------------------ + +&AllocateRegister( \$lightDirection ); + +dp3 $lightDirection.x, $s, $SHADER_SPECIFIC_CONST_0 +dp3 $lightDirection.y, $t, $SHADER_SPECIFIC_CONST_0 +dp3 $lightDirection.z, $r, $SHADER_SPECIFIC_CONST_0 + +&FreeRegister( \$r ); +&FreeRegister( \$s ); +&FreeRegister( \$t ); + +; Scale into 0-1 range (we're assuming light direction was normalized prior to here) +add oT2, $lightDirection, $cHalf ; + 0.5 +&FreeRegister( \$lightDirection ); + +;------------------------------------------------------------------------------ +; Copy texcoords for the normal map and base texture +;------------------------------------------------------------------------------ + +mov oT0, $vTexCoord0 +mov oT1, $vTexCoord1 + +; Pass the dirlight color through +mov oD0.xyzw, $vColor + + diff --git a/sp/src/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc b/sp/src/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc new file mode 100644 index 00000000..c90ef086 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugDrawDepth_ps2x.fxc @@ -0,0 +1,23 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 projPos : POSITION; + float3 zValue : TEXCOORD0; +}; + +const float3 g_ZFilter : register( c1 ); +const float3 g_ModulationColor : register( c2 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float z = dot( i.zValue, g_ZFilter ); + z = saturate( z ); + float4 color = float4( z, z, z, 1.0f ); + color.rgb *= g_ModulationColor; + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/sp/src/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc b/sp/src/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc new file mode 100644 index 00000000..647acde0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugDrawDepth_vs20.fxc @@ -0,0 +1,38 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +const float2 cDepthFactor : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 zValue : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.zValue.x = (o.projPos.z - cDepthFactor.y) / cDepthFactor.x; + o.zValue.y = (o.projPos.w - cDepthFactor.y) / cDepthFactor.x; + return o; +} + + + + diff --git a/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp b/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp new file mode 100644 index 00000000..9f3c34bf --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask.cpp @@ -0,0 +1,94 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "BaseVSShader.h" +#include "debugdrawenvmapmask_vs20.inc" +#include "debugdrawenvmapmask_ps20.inc" +#include "debugdrawenvmapmask_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( DebugDrawEnvmapMask, "Help for DebugDrawEnvmapMask", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHOWALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { +// Assert( 0 ); + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + SET_STATIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + SET_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + SET_STATIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + } + } + DYNAMIC_STATE + { + int numBones = s_pShaderAPI->GetCurrentNumBones(); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugdrawenvmapmask_vs20 ); + + bool bShowAlpha = params[SHOWALPHA]->GetIntValue() ? true : false; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( SHOWALPHA, bShowAlpha ); + SET_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( SHOWALPHA, bShowAlpha ); + SET_DYNAMIC_PIXEL_SHADER( debugdrawenvmapmask_ps20 ); + } + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc b/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc new file mode 100644 index 00000000..f97589af --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_ps2x.fxc @@ -0,0 +1,26 @@ +// DYNAMIC: "SHOWALPHA" "0..1" + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); +#if SHOWALPHA + float4 result = float4( baseColor.a, baseColor.a, baseColor.a, 1.0f ); +#else + float4 result = float4( baseColor.rgb, 1.0f ); +#endif + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc b/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc new file mode 100644 index 00000000..33aa5dac --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugDrawEnvmapMask_vs20.fxc @@ -0,0 +1,39 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + return o; +} + + + + diff --git a/sp/src/materialsystem/stdshaders/DebugTextureView.cpp b/sp/src/materialsystem/stdshaders/DebugTextureView.cpp new file mode 100644 index 00000000..70d73d34 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugTextureView.cpp @@ -0,0 +1,104 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "shaderlib/cshader.h" + +#include "debugtextureview_vs20.inc" +#include "debugtextureview_ps20.inc" +#include "debugtextureview_ps20b.inc" + +DEFINE_FALLBACK_SHADER( DebugTextureView, DebugTextureView_dx9 ) +BEGIN_VS_SHADER( DebugTextureView_dx9, "Help for DebugTextureView" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SHOWALPHA, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT + { + if ( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "UnlitGeneric"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaTest( true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugtextureview_vs20 ); + SET_STATIC_VERTEX_SHADER( debugtextureview_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugtextureview_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SHOWALPHA, params[SHOWALPHA]->GetIntValue() != 0 ); + SET_STATIC_PIXEL_SHADER( debugtextureview_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugtextureview_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SHOWALPHA, params[SHOWALPHA]->GetIntValue() != 0 ); + SET_STATIC_PIXEL_SHADER( debugtextureview_ps20 ); + } + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + //pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + + float cPsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + if ( ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA16161616F ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA16161616 ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGB323232F ) || + ( pTexture->GetImageFormat() == IMAGE_FORMAT_RGBA32323232F ) ) + { + if ( pTexture->IsCubeMap() ) + cPsConst0[0] = 1.0f; + else + cPsConst0[1] = 1.0f; + } + pShaderAPI->SetPixelShaderConstant( 0, cPsConst0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugtextureview_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugtextureview_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ISCUBEMAP, pTexture->IsCubeMap() ); + SET_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ISCUBEMAP, pTexture->IsCubeMap() ); + SET_DYNAMIC_PIXEL_SHADER( debugtextureview_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/DebugTextureView_ps2x.fxc b/sp/src/materialsystem/stdshaders/DebugTextureView_ps2x.fxc new file mode 100644 index 00000000..4b22d55b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugTextureView_ps2x.fxc @@ -0,0 +1,81 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "SHOWALPHA" "0..1" +// DYNAMIC: "ISCUBEMAP" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler g_tSampler : register( s0 ); + +struct PS_INPUT +{ + float2 texCoord : TEXCOORD0; +}; + +const float3 g_vConst0 : register( c0 ); +#define g_flIsHdrCube g_vConst0.x +#define g_flIsHdr2D g_vConst0.y + +float4 main( PS_INPUT i ) : COLOR +{ + float4 sample = tex2D( g_tSampler, i.texCoord ); + float4 result = { 0.0f, 0.0f, 0.0f, 1.0f }; + + result.rgb = sample.rgb; + #if SHOWALPHA + result.rgb = sample.a; + #endif + + if ( g_flIsHdr2D ) + result.rgb *= MAX_HDR_OVERBRIGHT; + + #if ISCUBEMAP + bool bNoDataForThisPixel = false; + float3 vec = float3( 0, 0, 0 ); + float x = i.texCoord.x; + float y = i.texCoord.y; + float x2 = frac( ( i.texCoord.x ) * 3.0f ) * 2.0f - 1.0f; + float y2 = frac( ( i.texCoord.y ) * 4.0f ) * 2.0f - 1.0f; + if ( ( x >= 0.3333f ) && ( x <= 0.6666f ) ) //Center row + { + if ( y >= 0.75f ) + vec = float3( x2, 1.0, y2 ); + else if ( y >= 0.5f ) + vec = float3( x2, y2, -1.0 ); + else if ( y >= 0.25f ) + vec = float3( x2, -1.0, -y2 ); + else if ( y >= 0.0f ) + vec = float3( x2, -y2, 1.0 ); + } + else if ( ( y >= 0.25f ) && ( y <= 0.5f ) ) + { + if ( x <= 0.3333f ) + vec = float3( -1.0f, -x2, -y2 ); + else if (x >= 0.6666f) + vec = float3( 1.0f, x2, -y2 ); + else + bNoDataForThisPixel = true; + } + else + { + bNoDataForThisPixel = true; + } + + float4 cBase = texCUBE( g_tSampler, vec ); + #if SHOWALPHA + cBase.rgb = cBase.a; + #endif + + if ( g_flIsHdrCube ) + cBase.rgb *= ENV_MAP_SCALE; + + if ( bNoDataForThisPixel == true ) + cBase.rgb = float3( 0.9f, 0.4f, 0.15f ); + + result.rgb = cBase.rgb; + result.a = 1.0f; // - bNoDataForThisPixel; + #endif + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} diff --git a/sp/src/materialsystem/stdshaders/DebugTextureView_vs20.fxc b/sp/src/materialsystem/stdshaders/DebugTextureView_vs20.fxc new file mode 100644 index 00000000..48c3b7e4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/DebugTextureView_vs20.fxc @@ -0,0 +1,23 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vUv0 : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + o.vProjPos.xyzw = mul( i.vPos.xyzw, cModelViewProj ); + o.vUv0.xy = i.vTexCoord0.xy; + return o; +} diff --git a/sp/src/materialsystem/stdshaders/Eyes.psh b/sp/src/materialsystem/stdshaders/Eyes.psh new file mode 100644 index 00000000..6e5e5646 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Eyes.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw the eyes +; t0 - texture +; t1 - iris +; t2 - glint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +lrp r0, t1.a, t1, t0 ; Blend in the iris with the background +mad r0.rgb, r0, v0, t2 + ; Modulate by the illumination, add in the glint +mov r0.a, t0.a diff --git a/sp/src/materialsystem/stdshaders/Eyes_Overbright2.psh b/sp/src/materialsystem/stdshaders/Eyes_Overbright2.psh new file mode 100644 index 00000000..11119233 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Eyes_Overbright2.psh @@ -0,0 +1,18 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw the eyes +; t0 - texture +; t1 - iris +; t2 - glint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +lrp r0, t1.a, t1, t0 ; Blend in the iris with the background +mul_x2 r0, v0, r0 ; Modulate by the illumination with overbright + +add r0.rgb, r0, t2 + ; Add in the glint +mov r0.a, t0.a diff --git a/sp/src/materialsystem/stdshaders/Eyes_vs20.fxc b/sp/src/materialsystem/stdshaders/Eyes_vs20.fxc new file mode 100644 index 00000000..b055eed7 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Eyes_vs20.fxc @@ -0,0 +1,145 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== +// $SHADER_SPECIFIC_CONST_0 = eyeball origin +// $SHADER_SPECIFIC_CONST_1 = eyeball up * 0.5 +// $SHADER_SPECIFIC_CONST_2 = iris projection U +// $SHADER_SPECIFIC_CONST_3 = iris projection V +// $SHADER_SPECIFIC_CONST_4 = glint projection U +// $SHADER_SPECIFIC_CONST_5 = glint projection V +//============================================================================= + +// STATIC: "INTRO" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "vortwarp_vs20_helper.h" + +static const int g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 cEyeOrigin : register( SHADER_SPECIFIC_CONST_0 ); +const float3 cHalfEyeballUp : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cIrisProjectionU : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cIrisProjectionV : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cGlintProjectionU : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cGlintProjectionV : register( SHADER_SPECIFIC_CONST_5 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_6 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_7 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_8 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + float3 vPosFlex : POSITION1; // Delta positions for flexing +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; // Fixed-function fog factor +#endif + float2 baseTC : TEXCOORD0; // Base texture coordinate + float2 irisTC : TEXCOORD1; // Iris texture coordinates + float2 glintTC : TEXCOORD2; // Glint texture coordinates + float3 vColor : TEXCOORD3; // Vertex-lit color + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float4 vPosition = v.vPos; + float3 dummy = v.vPos.xyz; // dummy values that can't be optimized out + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, dummy, vPosition.xyz ); +#endif + + // Transform the position and dummy normal (not doing the dummy normal causes invariance issues with the flashlight!) + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, dummy, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + +#if INTRO + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, dummy, dummy, dummy ); +#endif + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, vProjPos, g_FogType ); +#endif + + // Normal = (Pos - Eye origin) - just step on dummy normal created above + worldNormal = worldPos - cEyeOrigin; + + // Normal -= 0.5f * (Normal dot Eye Up) * Eye Up + float normalDotUp = -dot( worldNormal, cHalfEyeballUp) * 0.5f; + worldNormal = normalize(normalDotUp * cHalfEyeballUp + worldNormal); + + // Vertex lighting +#if ( USE_STATIC_CONTROL_FLOW || defined ( SHADER_MODEL_VS_3_0 ) ) + o.vColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert ); +#else + o.vColor = DoLightingUnrolled( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); +#endif + + // Texture 0 is the base texture + // Texture 1 is a planar projection used for the iris + // Texture 2 is a planar projection used for the glint + o.baseTC = v.vTexCoord0; + o.irisTC.x = dot( cIrisProjectionU, float4(worldPos, 1) ); + o.irisTC.y = dot( cIrisProjectionV, float4(worldPos, 1) ); + o.glintTC.x = dot( cGlintProjectionU, float4(worldPos, 1) ); + o.glintTC.y = dot( cGlintProjectionV, float4(worldPos, 1) ); + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric.psh new file mode 100644 index 00000000..a6794e7e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddBaseAlphaMaskedEnvMap.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddBaseAlphaMaskedEnvMap.psh new file mode 100644 index 00000000..7b042e7a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddBaseAlphaMaskedEnvMap.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t2 ; cube map +tex t3 ; envmap mask + +mul r0.rgb, t2, 1-t3.a +mul r0.rgb, c2, r0 ; apply the envmaptint ++ mul r0.a, c2.a, v0.a diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapMaskNoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapMaskNoTexture.psh new file mode 100644 index 00000000..ccc2c7b1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapMaskNoTexture.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t2 ; cube map +tex t3 ; envmap mask + +mul r0.rgb, t2, t3 +mul r0.rgb, c2, r0 ++ mul r0.a, c2.a, v0.a diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapNoTexture.psh new file mode 100644 index 00000000..fd4fd7a5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_AddEnvMapNoTexture.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t2 ; cube map + +mul r0.rgb, t2, c2 ++ mul r0.a, v0.a, c2.a diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseAlphaMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseAlphaMaskedEnvMapV2.psh new file mode 100644 index 00000000..236db8e3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseAlphaMaskedEnvMapV2.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul r1, t2, 1-t3.a ; envmap * envmapmask (alpha) +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.psh new file mode 100644 index 00000000..75aab35b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.psh @@ -0,0 +1,14 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +mul r0, t0, c0 + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.vsh new file mode 100644 index 00000000..6cef1e5d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTexture.vsh @@ -0,0 +1,38 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTextureBlend.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTextureBlend.vsh new file mode 100644 index 00000000..8eea421f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BaseTextureBlend.vsh @@ -0,0 +1,43 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +mov oT2, $vTexCoord1 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.psh new file mode 100644 index 00000000..ba349187 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.psh @@ -0,0 +1,66 @@ +; STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +ps.1.1 + +;------------------------------------------------------------------------------ +; Environment mapping on a bumped surface +; t0 - Normalmap +; t3 - Cube environment map (*must* be a cube map!) +; +; c0 - color to multiply the results by +; c1 - envmap contrast +; c2 - envmap saturation +; c3 - grey weights +; c4 - fresnel amount +; Input texture coords required here are a little wonky. +; tc0.uv <- U,V into the normal map +; tc1.uvw, tc2.uvw, tc3.uvw <- 3x3 matrix transform +; from tangent space->env map space +; tc1.q, tc2.q, tc3.q <- eye vector in env map space +;------------------------------------------------------------------------------ + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +; FIXME FIXME - Need to do specialized versions of this with and without: +; - constant color +; - fresnel amount of exactly 0 or 1 or in between +; - envmap contrast of 0, 1, or in between +; - envmap saturation of 0, 1, or in between + +; r0 = constant color * result of bump into envmap +mul r0.rgb, t3, c0 + +; dot eye-vector with per-pixel normal from t0 +dp3_sat r1, v0_bx2, t0_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r1.rgb, r0, r0 ; color squared ++mul r0.a, 1-r1.a, 1-r1.a ; squared + +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color ++mul r0.a, r0.a, r0.a ; quartic + +dp3 r1.rgb, r0, c3 ; color greyscaled ++mul r0.a, r0.a, 1-r1.a ; quintic + +; FIXME - these should be able to pair (I think), but don't on nvidia for some reason. +; (I think) cannot pair due to use of >2 constants in single stage +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale +mad r0.a, r0.a, c6.a, c4.a ; Take Fresnel R(0) into consideration + +mul r0.rgb, r0, r0.a ; multiply output color by result of fresnel calc + +#if NORMALMAPALPHAENVMAPMASK ++mul r0.a, c0.a, t0.a ; Fade amount * alpha from the texture +#else ++mov r0.a, c0.a ; Just use the fade amount +#endif + + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.vsh new file mode 100644 index 00000000..73769dce --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap.vsh @@ -0,0 +1,96 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $worldEyeVect.x +mov oT2.w, $worldEyeVect.y +mov oT3.w, $worldEyeVect.z + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +&FreeRegister( \$worldEyeVect ); + +&Normalize( $tangentEyeVect ); + +; stick the tangent space eye vector into oD0 +mad oD0.xyz, $tangentEyeVect, $cHalf, $cHalf + +&FreeRegister( \$tangentEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.psh new file mode 100644 index 00000000..2a4efc7d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.psh @@ -0,0 +1,72 @@ +; STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +ps.1.4 +;------------------------------------------------------------------------------ +; Phase 1 +;------------------------------------------------------------------------------ +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! +;mov r0.rgba, r4 + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +#if NORMALMAPALPHAENVMAPMASK +; Alpha gets lost after phase marker, so store it here +mov r5, r0.a +#endif + +;------------------------------------------------------------------------------ +; Phase 2 +;------------------------------------------------------------------------------ +; What's left over from the last phase: +; r0 - normal +; r1 - free +; r2 - vector to sample in envmap +; r3 - free +; r4 - normal +; r5 - normal map alpha (rgba) + +phase + +; Sample environment map +texld r3, r2 + +; dot eye-vector with per-pixel normal from r0 +dp3_sat r1, v0_bx2, r0_bx2 + +; Result goes in output color (multiply by constant color c0) +mul r0.rgb, r3, c0 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r1.rgb, r0, r0 ++mul r0.a, 1-r1.a, 1-r1.a ; squared + +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color ++mul r0.a, r0.a, r0.a ; quartic + +dp3 r1.rgb, r0, c3 ++mul r0.a, r0.a, 1-r1.a ; quintic + +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale +mad r0.a, r0.a, c6.a, c4.a ; Take Fresnel R(0) into consideration + +mul r0.rgb, r0, r0.a ; multiply output color by result of fresnel calc + +#if NORMALMAPALPHAENVMAPMASK ++mul r0.a, c0.a, r5.r ; Fade amount * alpha from the texture +#else ++mov r0.a, c0.a ; Just use the fade amount +#endif diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.vsh new file mode 100644 index 00000000..ea0f143a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedEnvmap_ps14.vsh @@ -0,0 +1,92 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; eye vector +mov oT4.xyz, $worldEyeVect + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +&FreeRegister( \$worldEyeVect ); + +&Normalize( $tangentEyeVect ); + +; stick the tangent space eye vector into oD0 +mad oD0.xyz, $tangentEyeVect, $cHalf, $cHalf + +&FreeRegister( \$tangentEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.psh new file mode 100644 index 00000000..9e55248e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.psh @@ -0,0 +1,79 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - Axes of the lightmap coordinate system in tangent space +;------------------------------------------------------------------------------ + +; Get the 3-vector from the normal map +tex t0 + +; Sample the lightmaps +tex t1 +tex t2 +tex t3 + +; output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + +; r0 = ( N dot basis[0] ) +; don't "_sat" here so that everything adds up to one even if the normal is outside of the basis!!!!! +dp3 r0, t0_bx2, c0 + +; r1 = ( N dot basis[1] ) +dp3 r1, t0_bx2, c1 + +;---- +; r0 = ( N dot basis[0] ) +; r1 = ( N dot basis[1] ) +;---- + +; r0.rgb = ( N dot basis[0] )^2 +mul r0.rgb, r0, r0 + +; r1.a = ( N dot basis[1] )^2 ++mul r1.a, r1, r1 + +;---- +; r0.rgb = ( N dot basis[0] )^2 +; r1.a = ( N dot basis[1] )^2 +;---- + +mul t1, r0, t1 + +;---- +; r1.a = ( N dot basis[1] )^2 +; t1 = lightmapColor[0] * ( N dot basis[0] )^2 +;---- + +dp3 r0, t0_bx2, c2 + +;---- +; r1.a = ( N dot basis[1] )^2 +; t1 = lightmapColor[0] * ( N dot basis[0] )^2 +; r0 = ( N dot basis[2] ) +;---- + +mad t1.rgb, r1.a, t2, t1 ++mul r0.a, r0, r0 + +;---- +; t1.rgb = lightmapColor[0] * ( N dot basis[0] )^2 + lightmapColor[1] * ( N dot basis[1] )^2 +; r0.a = ( N dot basis[2] )^2 +;---- + +mad r0.rgba, r0.a, t3, t1 + +;---- +; r0.rgb = lightmapColor[0] * ( N dot basis[0] )^2 + +; lightmapColor[1] * ( N dot basis[1] )^2 + +; lightmapColor[2] * ( N dot basis[2] )^2 +;---- diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.vsh new file mode 100644 index 00000000..229a839a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap.vsh @@ -0,0 +1,54 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.xy, $vTexCoord2 +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +; make a 3 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three + +&FreeRegister( \$offset ); diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.psh new file mode 100644 index 00000000..39a25964 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.psh @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; t4 - Base +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - Axes of the lightmap coordinate system in tangent space +;------------------------------------------------------------------------------ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 + +; Sample the lightmaps +texld r1, t1 +texld r2, t2 +texld r3, t3 + +; Sample the base texture +texld r4, t4 + +; output = (lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) ) * base + +dp3 r5.r, r0_bx2, c0 +dp3 r5.g, r0_bx2, c1 +dp3 r5.b, r0_bx2, c2 +mul r5.rgb, r5, r5 +mul r1, r1, r5.r +mad r1, r2, r5.g, r1 +mad r1, r3, r5.g, r1 + +; assume overbright_2 !!! +mul_x2 r0, r1, r4 diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.vsh new file mode 100644 index 00000000..a78d0851 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_base_ps14.vsh @@ -0,0 +1,55 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.xy, $vTexCoord2 +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three +dp4 oT4.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT4.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +&FreeRegister( \$offset ); diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.psh new file mode 100644 index 00000000..f17f14cf --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.psh @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; t4 - Base1 +; t5 - Base2 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - Axes of the lightmap coordinate system in tangent space +;------------------------------------------------------------------------------ +ps.1.4 + +; output = (lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) ) * lerp(base1, base2, lightmapColor[0].a) + +; Get the 3-vector from the normal map +texld r0, t0 + +dp3 r5.r, r0_bx2, c0 +dp3 r5.g, r0_bx2, c1 +dp3 r5.b, r0_bx2, c2 +mul r5.rgb, r5, r5 + +phase + +; Sample the lightmaps +texld r1, t1 +texld r2, t2 +texld r3, t3 + +; Sample the base textures +texld r4, t4 +texld r5, t5 + +mul r1, r1, r5.r +mad r1, r2, r5.g, r1 +mad r1, r3, r5.g, r1 + +; blend base textures +lrp r4, r4, r5, r1.a + +; assume overbright_2 !!! +mul_x2 r0, r1, r4 diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.vsh new file mode 100644 index 00000000..7773d335 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_BumpmappedLightmap_blend_ps14.vsh @@ -0,0 +1,57 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.xy, $vTexCoord2 +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three +dp4 oT4.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT4.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 +dp4 oT5.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT5.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +&FreeRegister( \$offset ); diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.psh new file mode 100644 index 00000000..86e627e5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.psh @@ -0,0 +1,47 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - decal texture +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +; c0, c1, c2 - ( ( N dot basis[0] )^2 ), ( ( N dot basis[1] )^2 ), ( ( N dot basis[2] )^2 ) +;------------------------------------------------------------------------------ + +; Get the decal color +tex t0 + +; Sample the lightmaps +tex t1 +tex t2 +tex t3 + +; output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + +; r0 = lightmapColor[0] * ( ( N dot basis[0] )^2 ) +mul r0, t1, c0 + +; r0 = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + lightmapColor[1] * ( ( N dot basis[1] )^2 ) +mad r0, t2, c1, r0 + +; r0 = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + +; lightmapColor[1] * ( ( N dot basis[1] )^2 ) + +; lightmapColor[2] * ( ( N dot basis[2] )^2 ) +mad r0, t3, c2, r0 + +; Modulate by decal texture +mul r0.rgb, r0, t0 ++ mov r0.a, t0.a + +; Modulate by constant color +mul r0, r0, c3 + +; Modulate by per-vertex factor +mul r0, r0, v0 + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.vsh new file mode 100644 index 00000000..a9db9faa --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_Decal.vsh @@ -0,0 +1,56 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +; Compute the texture coordinates given the offset between +; each bumped lightmap +&AllocateRegister( \$offset ); +mov $offset.x, $vTexCoord2.x +mov $offset.y, $cZero +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +add oT1.xy, $offset, $vTexCoord1 +mad oT2.xy, $offset, $cTwo, $vTexCoord1 +; make a 3 +alloc $three +add $three, $cOne, $cTwo +mad oT3.xy, $offset, $three, $vTexCoord1 +free $three +mov oD0, $vColor + +&FreeRegister( \$offset ); diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_Detail.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_Detail.psh new file mode 100644 index 00000000..89b6c322 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_Detail.psh @@ -0,0 +1,18 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r1.rgb, r0, t2 ; detail texture +lrp r0.rgb, c2, r1, r0 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_DetailNoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_DetailNoTexture.psh new file mode 100644 index 00000000..a9129757 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_DetailNoTexture.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t1 +tex t2 +mul r0.rgb, t1, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a +mul_x2 r0.rgb, r0, t2 ; detail texture +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_DetailSelfIlluminated.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_DetailSelfIlluminated.psh new file mode 100644 index 00000000..a9e05150 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_DetailSelfIlluminated.psh @@ -0,0 +1,23 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r1.rgb, r0, t2 ; detail texture +lrp r0.rgb, c2, r1, r0 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, c1, t0 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lightmap diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapNoTexture.psh new file mode 100644 index 00000000..919da94c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapNoTexture.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t1 +tex t2 + +mov r0.rgb, v0 + ; vertex color +mul r0.a, v0.a, t2.a ; vertex alpha * envmap alpha + +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapV2.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapV2.psh new file mode 100644 index 00000000..f0205e86 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_EnvMapV2.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly.vsh new file mode 100644 index 00000000..5f740f86 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly.vsh @@ -0,0 +1,45 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +; $SHADER_SPECIFIC_CONST_4 = Modulation color +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +alloc $worldPos +if( $DOWATERFOG == 1 ) +{ + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 +} +&CalcFog( $worldPos, $projPos ); +free $worldPos + +&FreeRegister( \$projPos ); + +; YUCK! This is to make texcoords continuous for mat_softwaretl +mov oT0, $cZero +; Texture coordinates +mov oT1, $vTexCoord1 + +mov oD0, $cOne + + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly_Overbright2.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly_Overbright2.psh new file mode 100644 index 00000000..30bd9f76 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_LightingOnly_Overbright2.psh @@ -0,0 +1,6 @@ +ps.1.1 + +tex t1 + +mov r0.rgba, t1 + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapNoTexture.psh new file mode 100644 index 00000000..ee59d663 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapNoTexture.psh @@ -0,0 +1,24 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t1 +tex t2 +tex t3 + +mov r0.rgb, v0 ; vertex color +mul r1, t2, t3 ; envmap * envmapmask + +mad r0.rgb, r1, c2, r0 + ; + envmap * envmapmask * envmaptint (color only) +mul r0.a, v0.a, r1.a ; alpha = vertex alpha * envmap alpha * envmapmask alpha + +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapV2.psh new file mode 100644 index 00000000..398ed46a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MaskedEnvMapV2.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLighting.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLighting.psh new file mode 100644 index 00000000..7944e730 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLighting.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c2, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mul_sat r1.a, t0, v0 ; base times vertex alpha +lrp r0, r1.a, r1, c2 ; interpolate between white + color diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingNoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingNoTexture.psh new file mode 100644 index 00000000..e0fb27b7 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingNoTexture.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c2, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mov_sat r1.a, v0 ; vertex alpha +lrp r0, r1.a, r1, c2 ; interpolate between white + color diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingSelfIllum.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingSelfIllum.psh new file mode 100644 index 00000000..1282ecac --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_MultiplyByLightingSelfIllum.psh @@ -0,0 +1,23 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c2, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 + +; Blend between white and lightmap color based on total alpha +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mov_sat r1.a, v0 ; opacity == vertex opacity (no alpha in texture) + +lrp r0.rgb, t0.a, c1, r1 ; Blend between self-illum + lightmap ++ mov r0.a, c2.a + +lrp r0.rgb, r1.a, r0, c2 ; interpolate between white + color diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_NoTexture.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_NoTexture.psh new file mode 100644 index 00000000..f02de34b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_NoTexture.psh @@ -0,0 +1,14 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t1 +mul r0.rgb, t1, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_SSBumpmappedLightmap.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SSBumpmappedLightmap.psh new file mode 100644 index 00000000..bdcb7783 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SSBumpmappedLightmap.psh @@ -0,0 +1,34 @@ +ps.1.1 +def c0, 1,0,0,0 +def c1, 0,1,0,0 +def c2, 0,0,1,0 + +;------------------------------------------------------------------------------ +; Computes the diffuse component of lighting using lightmap + bumpmap +; t0 - Normalmap +; t1 - Lightmap1 +; t2 - Lightmap2 +; t3 - Lightmap3 +; +; The texture coordinates need to be defined as follows: +; tc0 - Normalmap and lightmap texture coordinates +;------------------------------------------------------------------------------ + +; Get the 3-vector from the normal map +tex t0 + +; Sample the lightmaps +tex t1 +tex t2 +tex t3 + +; output = lightmapColor[0] * n.r + lightmapColor[1] * n.g + lightmapColor[2] * n.b + + +mov r0, t0 +dp3 r1, t0, c0 +mul r0.rgb, r1, t1 +dp3 r1, t0, c1 +mad r0.rgb, r1, t2, r0 +dp3 r1, t0, c2 +mad r0.rgb, r1, t3, r0 diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminated.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminated.psh new file mode 100644 index 00000000..cf800a2e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminated.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 + +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, c1, t0 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lightmap diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedEnvMapV2.psh new file mode 100644 index 00000000..9fd0a1c5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedEnvMapV2.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r1, t0.a, t0 ; Self illum +mad r1, c1, r1, t1 ; Self illum * tint + lightmap + +mul r0.rgb, r1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2.psh new file mode 100644 index 00000000..1e62a416 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2.psh @@ -0,0 +1,28 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0.rgb, t0, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r1, c1, t0.a ; Self illum alpha * tint +mad r1, t0, r1, t1 ; Self illum * tint + lightmap +mul r0.rgb, r1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) + diff --git a/sp/src/materialsystem/stdshaders/LightmappedGeneric_VertexColor.vsh b/sp/src/materialsystem/stdshaders/LightmappedGeneric_VertexColor.vsh new file mode 100644 index 00000000..a434a941 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/LightmappedGeneric_VertexColor.vsh @@ -0,0 +1,15 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "LightmappedGeneric_inc.vsh" + +$detail = 0; +$envmap = 0; +$envmapcameraspace = 0; +$envmapsphere = 0; +$vertexcolor = 1; + +&LightmappedGeneric( $detail, $envmap, $envmapcameraspace, $envmapsphere, + $vertexcolor ); + diff --git a/sp/src/materialsystem/stdshaders/Refract_model_vs11.vsh b/sp/src/materialsystem/stdshaders/Refract_model_vs11.vsh new file mode 100644 index 00000000..a6eea2b7 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Refract_model_vs11.vsh @@ -0,0 +1,105 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $worldPos +alloc $worldNormal +alloc $worldTangentS +alloc $worldTangentT + +&SkinPositionNormalAndTangentSpace( $worldPos, $worldNormal, + $worldTangentS, $worldTangentT ); + +alloc $projPos + +; Transform position from world to projection space +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +alloc $tangentEyeVect +; transform the eye vector to tangent space +dp3 oT3.x, $worldEyeVect, $worldTangentS +dp3 oT3.y, $worldEyeVect, $worldTangentT +dp3 oT3.z, $worldEyeVect, $worldNormal + +alloc $bumpTexCoord + +dp4 $bumpTexCoord.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 $bumpTexCoord.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +; dudv map +mov oT0.xy, $bumpTexCoord + +; refract tint + alpha channel +mov oT2.xy, $bumpTexCoord +mov oT3.xy, $bumpTexCoord + +free $bumpTexCoord + +mov oPos, $projPos + +; special case perspective correct texture projection so that the texture fits exactly on the screen + +; flip Y by multiplying by -1 +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_4.w + +; transform from [-w,w] to [0,2*w] +; The reason this is w is because we are in perspective space/homogenous clip space. +add $projPos.xy, $projPos.xy, $projPos.w + +; transform from [0,2*w] to [0,w] +; We'll end up dividing by w in the pixel shader to get to [0,1] +mul $projPos.xy, $projPos.xy, $cHalf + +mov oT1.xy, $projPos.xy + +; emit w to both z and w in case the driver screws up and divides by z +mov oT1.z, $projPos.w +mov oT1.w, $projPos.w + +free $projPos +free $worldPos +free $worldEyeVect +free $tangentEyeVect +free $w +free $worldNormal +free $worldTangentS +free $worldTangentT diff --git a/sp/src/materialsystem/stdshaders/Refract_ps11.psh b/sp/src/materialsystem/stdshaders/Refract_ps11.psh new file mode 100644 index 00000000..f3fe34d2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Refract_ps11.psh @@ -0,0 +1,36 @@ +; STATIC: "REFRACTTINTTEXTURE" "0..1" +; STATIC: "NORMALMAPALPHA" "0..1" + +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: refraction render target +; texcoords: + +tex t0 ; sample dudv map +texbem t1, t0 ; refraction + +#if REFRACTTINTTEXTURE +tex t2 +#endif + +#if NORMALMAPALPHA +tex t3 +#endif + +; refracttint +#if REFRACTTINTTEXTURE +mul_x2 r0, t1, t2 +#else +mov r0, t1 +#endif + +#if NORMALMAPALPHA +mul r0.rgb, r0, c0 + +mov r0.a, t3.a +#else +mul r0.rgb, r0, c0 +#endif diff --git a/sp/src/materialsystem/stdshaders/Refract_vs20.fxc b/sp/src/materialsystem/stdshaders/Refract_vs20.fxc new file mode 100644 index 00000000..698dd192 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Refract_vs20.fxc @@ -0,0 +1,140 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "MODEL" "0..1" +// STATIC: "COLORMODULATE" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const bool g_bModel = MODEL ? true : false; + +const float4 cBumpTexCoordTransform[4] : register( SHADER_SPECIFIC_CONST_1 ); + +const float g_flTime : register( SHADER_SPECIFIC_CONST_5 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; +#if !MODEL + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +#else + float4 vUserData : TANGENT; +#endif +#if COLORMODULATE + float4 vColor : COLOR0; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; +#if !defined( _X360 ) + float vFog : FOG; +#endif + float4 vBumpTexCoord : TEXCOORD0; + float3 vTangentEyeVect : TEXCOORD1; + float3 vWorldNormal : TEXCOORD2; + float3 vWorldTangent : TEXCOORD3; + float3 vWorldBinormal : TEXCOORD4; + float3 vRefractXYW : TEXCOORD5; + float3 vWorldViewVector : TEXCOORD6; +#if COLORMODULATE + float4 vColor : COLOR0; +#endif + float4 fogFactorW : COLOR1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + +#if COLORMODULATE + o.vColor = v.vColor; +#endif + + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + + float3 vObjNormal; +#if MODEL + float4 vObjTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vObjNormal, vObjTangent ); + + SkinPositionNormalAndTangentSpace( + g_bSkinning, + v.vPos, vObjNormal, vObjTangent, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal, worldTangentS, worldTangentT ); +#else + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + worldPos = mul( v.vPos, cModel[0] ); + worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); +#endif + + // World normal + o.vWorldNormal.xyz = normalize( worldNormal.xyz ); + + // Projected position + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos_POSITION = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + //o.projNormal.xyz = mul( worldNormal, cViewProj ); + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Refraction transform + o.vRefractXYW = float3(vRefractPos.x, vRefractPos.y, vProjPos.w); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.fogFactorW = CalcFog( vWorldPos, vProjPos, FOGTYPE_RANGE ); +#if !defined( _X360 ) + o.vFog = o.fogFactorW; +#endif + + // Eye vector + float3 vWorldEyeVect = normalize( cEyePos - vWorldPos ); + o.vWorldViewVector.xyz = -vWorldEyeVect.xyz; + + // Transform to the tangent space + o.vTangentEyeVect.x = dot( vWorldEyeVect, worldTangentS ); + o.vTangentEyeVect.y = dot( vWorldEyeVect, worldTangentT ); + o.vTangentEyeVect.z = dot( vWorldEyeVect, worldNormal ); + + // Tranform bump coordinates + o.vBumpTexCoord.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoord.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + + // Tranform bump coordinates (note wz, not zw) + o.vBumpTexCoord.w = dot( v.vBaseTexCoord, cBumpTexCoordTransform[2] ); + o.vBumpTexCoord.z = dot( v.vBaseTexCoord, cBumpTexCoordTransform[3] ); + + + // Tangent space transform + o.vWorldNormal.xyz = normalize( worldNormal.xyz ); + o.vWorldTangent.xyz = worldTangentS.xyz; + o.vWorldBinormal.xyz = worldTangentT.xyz; + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/Refract_world_vs11.vsh b/sp/src/materialsystem/stdshaders/Refract_world_vs11.vsh new file mode 100644 index 00000000..90f0debe --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Refract_world_vs11.vsh @@ -0,0 +1,168 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $worldPos +alloc $worldNormal +alloc $worldTangentS +alloc $worldTangentT +alloc $projPos + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +dp3 $worldPos.x, $vPos, $cModel0 +dp3 $worldPos.y, $vPos, $cModel1 +dp3 $worldPos.z, $vPos, $cModel2 + +dp3 $worldNormal.x, $vNormal, $cModel0 +dp3 $worldNormal.y, $vNormal, $cModel1 +dp3 $worldNormal.z, $vNormal, $cModel2 + +dp3 $worldTangentS.x, $vTangentS, $cModel0 +dp3 $worldTangentS.y, $vTangentS, $cModel1 +dp3 $worldTangentS.z, $vTangentS, $cModel2 + +dp3 $worldTangentT.x, $vTangentT, $cModel0 +dp3 $worldTangentT.y, $vTangentT, $cModel1 +dp3 $worldTangentT.z, $vTangentT, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +alloc $tangentEyeVect +alloc $bumpTexCoord + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $worldTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $worldTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $worldNormal + +&Normalize( $tangentEyeVect ); + +; stick the tangent space eye vector into oD0 +mad oD0.xyz, $tangentEyeVect, $cHalf, $cHalf + +dp4 $bumpTexCoord.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 $bumpTexCoord.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +; dudv map +mov oT0.xy, $bumpTexCoord + +; refract tint +mov oT3.xy, $bumpTexCoord + +free $bumpTexCoord + +alloc $newProjPos +alloc $w + +mov oPos, $projPos + +; special case perspective correct texture projection so that the texture fits exactly on the screen +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_4.w +add $projPos.xy, $projPos.xy, $projPos.w +mul $projPos.xy, $projPos.xy, $cHalf + +; Do the perspective divide here. .yuck . . we aren't going to be perspective correct +rcp $w.w, $projPos.w +mul $projPos, $projPos, $w.w + +#max $projPos.x, $projPos.x, -$cOne +#min $projPos.x, $projPos.x, $cOne +#max $projPos.z, $projPos.z, $cZero +#min $projPos.z, $projPos.z, $cOne + +;------------------------------------------------------------------------------ +; Transform the tangentS from world to view space +;------------------------------------------------------------------------------ + +alloc $projTangentS + +; we only care about x and y +dp3 $projTangentS.x, $worldTangentS, $cViewProj0 +dp3 $projTangentS.y, $worldTangentS, $cViewProj1 + +; project tangentS +mul $projTangentS.xy, $projTangentS.xy, $w.w + +;max $projTangentS.xy, $projTangentS.xy, $cOne +;min $projTangentS.xy, $projTangentS.xy, -$cOne + +;------------------------------------------------------------------------------ +; Transform the tangentT from world to view space +;------------------------------------------------------------------------------ + +alloc $projTangentT +alloc $texCoord + +; we only care about x and y +dp3 $projTangentT.x, $worldTangentT, $cViewProj0 +dp3 $projTangentT.y, $worldTangentT, $cViewProj1 + +; project tangentT +mul $projTangentT.xy, $projTangentT.xy, $w.w + +;max $projTangentT.xy, $projTangentT.xy, $cOne +;min $projTangentT.xy, $projTangentT.xy, -$cOne + +;max $projPos.xy, $projPos.xy, $cOne +;min $projPos.xy, $projPos.xy, -$cOne + +mul oT1.x, $projTangentS.x, $SHADER_SPECIFIC_CONST_3.x +mul oT1.y, $projTangentT.x, $SHADER_SPECIFIC_CONST_3.x +mov oT1.z, $projPos.x ; huh? + +mul $texCoord.x, $projTangentS.y, -$SHADER_SPECIFIC_CONST_3.x +mul $texCoord.y, $projTangentT.y, -$SHADER_SPECIFIC_CONST_3.x +mov $texCoord.z, $projPos.y +mov oT2.xyz, $texCoord +mov oT3.xyz, $texCoord + +free $texCoord +free $projPos +free $worldPos +free $worldEyeVect +free $tangentEyeVect +free $w +free $projTangentS +free $projTangentT +free $newProjPos +free $worldNormal +free $worldTangentS +free $worldTangentT diff --git a/sp/src/materialsystem/stdshaders/ShadowModel.psh b/sp/src/materialsystem/stdshaders/ShadowModel.psh new file mode 100644 index 00000000..a7514020 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/ShadowModel.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c0,1.0f, 1.0f, 1.0f, 1.0f + +tex t0 ; shadow color +texkill t1 ; Clip +texkill t2 +texkill t3 ; backface cull + +; Darkening equation, compute a color = (shadow color * shadow alpha + 1- shadow alpha) +;sub r1, t0, v0.a ; r1 = shadow alpha +lrp r0.rgb, t0.a, v0, c0 + ; r0.rgb = (shadow color * shadow alpha + 1 - shadow alpha) +mov r0.a, c0.a ; r0.a = 1 + diff --git a/sp/src/materialsystem/stdshaders/ShadowModel.vsh b/sp/src/materialsystem/stdshaders/ShadowModel.vsh new file mode 100644 index 00000000..3e4b9eba --- /dev/null +++ b/sp/src/materialsystem/stdshaders/ShadowModel.vsh @@ -0,0 +1,85 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_2 = Shadow texture matrix +; $SHADER_SPECIFIC_CONST_3 = Tex origin +; $SHADER_SPECIFIC_CONST_4 = Tex Scale +; $SHADER_SPECIFIC_CONST_5 = [Shadow falloff offset, 1/Shadow distance, Shadow scale, 0 ] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending (whacks r1-r7, positions in r7, normals in r8) +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +; Transform the position from world to view space +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Transform position into texture space (from 0 to 1) +;------------------------------------------------------------------------------ +&AllocateRegister( \$texturePos ); +dp4 $texturePos.x, $worldPos, $SHADER_SPECIFIC_CONST_0 +dp4 $texturePos.y, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 $texturePos.z, $worldPos, $SHADER_SPECIFIC_CONST_2 +&FreeRegister( \$worldPos ); + +;------------------------------------------------------------------------------ +; Figure out the shadow fade amount +;------------------------------------------------------------------------------ +&AllocateRegister( \$shadowFade ); +sub $shadowFade, $texturePos.z, $SHADER_SPECIFIC_CONST_5.x +mul $shadowFade, $shadowFade, $SHADER_SPECIFIC_CONST_5.y + +;------------------------------------------------------------------------------ +; Offset it into the texture +;------------------------------------------------------------------------------ +&AllocateRegister( \$actualTextureCoord ); +mul $actualTextureCoord.xyz, $SHADER_SPECIFIC_CONST_4, $texturePos +add oT0.xyz, $actualTextureCoord, $SHADER_SPECIFIC_CONST_3 +;mov oT0.xyz, $texturePos +&FreeRegister( \$actualTextureCoord ); + +;------------------------------------------------------------------------------ +; We're doing clipping by using texkill +;------------------------------------------------------------------------------ +mov oT1.xyz, $texturePos ; also clips when shadow z < 0 ! +sub oT2.xyz, $cOne, $texturePos +sub oT2.z, $cOne, $shadowFade.z ; clips when shadow z > shadow distance +&FreeRegister( \$texturePos ); + +;------------------------------------------------------------------------------ +; We're doing backface culling by using texkill also (wow yucky) +;------------------------------------------------------------------------------ +; Transform z component of normal in texture space +; If it's negative, then don't draw the pixel +dp3 oT3, $worldNormal, -$SHADER_SPECIFIC_CONST_2 +&FreeRegister( \$worldNormal ); + +;------------------------------------------------------------------------------ +; Shadow color, falloff +;------------------------------------------------------------------------------ +mov oD0, $cModulationColor +mul oD0.w, $shadowFade.x, $SHADER_SPECIFIC_CONST_5.z +&FreeRegister( \$shadowFade ); + diff --git a/sp/src/materialsystem/stdshaders/Teeth.vsh b/sp/src/materialsystem/stdshaders/Teeth.vsh new file mode 100644 index 00000000..065f0703 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Teeth.vsh @@ -0,0 +1,97 @@ +vs.1.1 + +# STATIC: "INTRO" "0..1" +# STATIC: "HALF_LAMBERT" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "LIGHT_COMBO" "0..21" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0 = xyz = mouth forward direction vector, w = illum factor +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +$WARPPARAM = $SHADER_SPECIFIC_CONST_2; +$ENTITY_ORIGIN = $SHADER_SPECIFIC_CONST_3; + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +alloc $worldPos +alloc $worldNormal +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +;------------------------------------------------------------------------------ +; Optional intro warping +;------------------------------------------------------------------------------ +if ( $INTRO == 1 ) +{ + alloc $tmp + sub $tmp.xyz, $worldPos, $ENTITY_ORIGIN + mul $tmp.xy, $tmp, $WARPPARAM + add $worldPos.xyz, $tmp, $ENTITY_ORIGIN + free $tmp +} + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $projPos + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); + +free $projPos + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ +alloc $linearColor +&DoDynamicLightingToLinear( $worldPos, $worldNormal, $linearColor ); + +;------------------------------------------------------------------------------ +; Factor in teeth darkening factors +;------------------------------------------------------------------------------ + +alloc $tmp + +mul $linearColor.xyz, $SHADER_SPECIFIC_CONST_0.w, $linearColor ; FIXME Color darkened by illumination factor +dp3 $tmp, $worldNormal, $SHADER_SPECIFIC_CONST_0 ; Figure out mouth forward dot normal +max $tmp, $cZero, $tmp ; clamp from 0 to 1 +mul $linearColor.xyz, $tmp, $linearColor ; Darken by forward dot normal too + +;------------------------------------------------------------------------------ +; Output color (gamma correction) +;------------------------------------------------------------------------------ + +alloc $gammaColor +&LinearToGamma( $linearColor, $gammaColor ); +free $linearColor +mul oD0.xyz, $gammaColor.xyz, $cOverbrightFactor +mov oD0.w, $cOne ; make sure all components are defined + + +free $gammaColor +free $worldPos +free $worldNormal +free $tmp + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +mov oT0, $vTexCoord0 + + + diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric.psh new file mode 100644 index 00000000..53fab24d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric.psh @@ -0,0 +1,13 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color + +mul r0, t0, v0 \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_BaseAlphaMaskedEnvMap.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_BaseAlphaMaskedEnvMap.psh new file mode 100644 index 00000000..1ed9314e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_BaseAlphaMaskedEnvMap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0.rgb, t1, 1-t2.a ; can't use mad cause can't use 3 texture registers +mul r0.rgb, c2, r0 ; apply the envmaptint +mad r0.rgb, t0, v0, r0 ++ mul r0.a, t0, v0 diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_Detail.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_Detail.psh new file mode 100644 index 00000000..5fcb3f31 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_Detail.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t3 ; detail texture + +mul r0, t0, v0 +mul_x2 r0.rgb, r0, t3 \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailBaseAlphaMaskedEnvMap.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailBaseAlphaMaskedEnvMap.psh new file mode 100644 index 00000000..69693331 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailBaseAlphaMaskedEnvMap.psh @@ -0,0 +1,29 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +;mul r0.rgb, t1, 1-t2.a ; can't use mad cause can't use 3 texture registers +;mul r0.rgb, c2, r0 ; apply the envmaptint +;mad r0.rgb, t0, v0, r0 +;+ mul r0.a, t0, v0 +;mul_x2 r0.rgb, r0, t3 ; mod2x detail texture + +; version 2: applies the mod2x *before* environment map +mul r0, t0, v0 ; Base times modulation color +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture +mul r1, t1, 1-t2.a ; Have to invert the alpha for basealpha (feh!) +mul r1, c2, r1 ; apply the envmaptint +add r0.rgb, r0, r1 ; add in the envmap diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMap.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMap.psh new file mode 100644 index 00000000..dab6efbb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMap.psh @@ -0,0 +1,25 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +;mul r1, c2, t1 +;mad r0.rgb, t0, v0, r1 +;+ mul r0.a, t0, v0 +;mul_x2 r0.rgb, r0, t3 ; mod2x detail texture + +; version 2: applies the mod2x *before* environment map +mul r0, t0, v0 ; Base times modulation color +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture +mad r0.rgb, c2, t1, r0 ; add in tinted envmap diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMask.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMask.psh new file mode 100644 index 00000000..29411c9b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMask.psh @@ -0,0 +1,29 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +;mul r0.rgb, t1, t2 ; can't use mad cause can't use 3 texture registers +;mul r0.rgb, c2, r0 ; apply the envmaptint +;mad r0.rgb, t0, v0, r0 +;+ mul r0.a, t0, v0 +;mul_x2 r0.rgb, r0, t3 ; mod2x detail texture + +; version 2: applies the mod2x *before* environment map +mul r0, t0, v0 ; Base times modulation color +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture +mul r1, t1, t2 ; Envmap * envmapmask +mul r1, c2, r1 ; apply the envmaptint +add r0.rgb, r0, r1 ; add in the envmap diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMaskNoTexture.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMaskNoTexture.psh new file mode 100644 index 00000000..e8c6f3cb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapMaskNoTexture.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +; version 2 doesn't make sense here! +mul r0, t1, t2 +mul r0.rgb, c2, r0 +mul r0, r0, v0 +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapNoTexture.psh new file mode 100644 index 00000000..829849b9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailEnvMapNoTexture.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map +tex t3 ; detail texture + +; version 1: applies the mod2x *after* environment map +; version 2 doesn't make sense here! +mul r0, v0, t1 +mul r0.rgb, r0, c2 +mul_x2 r0.rgb, r0, t3 ; mod2x detail texture \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailNoTexture.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailNoTexture.psh new file mode 100644 index 00000000..c79dc2ce --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_DetailNoTexture.psh @@ -0,0 +1,10 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Just use the vertex color +;------------------------------------------------------------------------------ + +tex t3 + +mul_x2 r0.rgb, v0, t3 ++ mov r0.a, v0.a \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMap.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMap.psh new file mode 100644 index 00000000..9116997f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMap.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map + +mul r1, c2, t1 +mad r0.rgb, t0, v0, r1 ++ mul r0.a, t0, v0 diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMask.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMask.psh new file mode 100644 index 00000000..f8de572c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMask.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0.rgb, t1, t2 ; can't use mad cause can't use 3 texture registers +mul r0.rgb, c2, r0 ; apply the envmaptint +mad r0.rgb, t0, v0, r0 ++ mul r0.a, t0, v0 diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMaskNoTexture.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMaskNoTexture.psh new file mode 100644 index 00000000..a9bd7e46 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapMaskNoTexture.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t1, t2 +mul r0.rgb, c2, r0 +mul r0, r0, v0 diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapNoTexture.psh new file mode 100644 index 00000000..966255fd --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_EnvMapNoTexture.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c2 - envmaptint +;------------------------------------------------------------------------------ + +tex t1 ; cube map + +mul r0, v0, t1 +mul r0.rgb, r0, c2 diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_LightingOnly.vsh b/sp/src/materialsystem/stdshaders/UnlitGeneric_LightingOnly.vsh new file mode 100644 index 00000000..6361c811 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_LightingOnly.vsh @@ -0,0 +1,21 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +&AllocateRegister( \$worldPos ); +&SkinPosition( $worldPos ); + +; Transform the position from world to view space +dp4 oPos.x, $worldPos, $cViewProj0 +dp4 oPos.y, $worldPos, $cViewProj1 +dp4 oPos.z, $worldPos, $cViewProj2 +dp4 oPos.w, $worldPos, $cViewProj3 + +&FreeRegister( \$worldPos ); + +mov oD0, $cOne + + diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_MaskBaseByDetailAlpha_ps11.fxc b/sp/src/materialsystem/stdshaders/UnlitGeneric_MaskBaseByDetailAlpha_ps11.fxc new file mode 100644 index 00000000..f46a7617 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_MaskBaseByDetailAlpha_ps11.fxc @@ -0,0 +1,20 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD3; +}; + +sampler BaseTextureSampler : register( s0 ); +sampler DetailTextureSampler : register( s3 ); + +float4 main( PS_INPUT i ) : COLOR +{ + // Sample frames from texture 0 + float4 base= tex2D( BaseTextureSampler, i.texCoord0 ); + float4 detail=tex2D( DetailTextureSampler, i.texCoord1 ); + + return float4(base.rgb, base.a * detail.a); +} diff --git a/sp/src/materialsystem/stdshaders/UnlitGeneric_NoTexture.psh b/sp/src/materialsystem/stdshaders/UnlitGeneric_NoTexture.psh new file mode 100644 index 00000000..feb29ba6 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/UnlitGeneric_NoTexture.psh @@ -0,0 +1,7 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Just use the vertex color +;------------------------------------------------------------------------------ + +mov r0, v0 diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric.psh new file mode 100644 index 00000000..9824a915 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric.psh @@ -0,0 +1,13 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 + +mul r0, t0, c3 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_BaseAlphaMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_BaseAlphaMaskedEnvMapV2.psh new file mode 100644 index 00000000..1844c402 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_BaseAlphaMaskedEnvMapV2.psh @@ -0,0 +1,17 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_BlendTint.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_BlendTint.psh new file mode 100644 index 00000000..f719821b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_BlendTint.psh @@ -0,0 +1,17 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 + +mul r0, c3, t0 +lrp r0.rgb, c1, c3, r0 +lrp r0.rgb, t0.a, r0, t0 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#else ++mov r0.a, c3 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail.psh new file mode 100644 index 00000000..f42d54ac --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail.psh @@ -0,0 +1,16 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +mul r0, t0, c3 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r1.rgb, r0, t3 ; detail texture +lrp r0.rgb, c1, r1, r0 + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailBaseAlphaMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailBaseAlphaMaskedEnvMapV2.psh new file mode 100644 index 00000000..09bf59ca --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailBaseAlphaMaskedEnvMapV2.psh @@ -0,0 +1,18 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailEnvMapV2.psh new file mode 100644 index 00000000..12b2295c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailEnvMapV2.psh @@ -0,0 +1,16 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t3 ; detail texture + +mul r0, t0, c3 ; base times modulation +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailMaskedEnvMapV2.psh new file mode 100644 index 00000000..ec35a8ba --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailMaskedEnvMapV2.psh @@ -0,0 +1,18 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, t2 ; Envmap * mask +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailNoTexture.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailNoTexture.psh new file mode 100644 index 00000000..d75a2790 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailNoTexture.psh @@ -0,0 +1,12 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t3 + +mul r0, v0, c3 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mul_x2 r0.rgb, r0, t3 ; detail texture + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminated.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminated.psh new file mode 100644 index 00000000..4b80e91b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminated.psh @@ -0,0 +1,22 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +; interpolate between illuminated + non-selfilluminated +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +#if WRITEONETODESTALPHA +mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedEnvMapV2.psh new file mode 100644 index 00000000..e625791a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedEnvMapV2.psh @@ -0,0 +1,24 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t1 +tex t3 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedMaskedEnvMapV2.psh new file mode 100644 index 00000000..119633a9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_DetailSelfIlluminatedMaskedEnvMapV2.psh @@ -0,0 +1,26 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask +tex t3 ; detail + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_LerpBase.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_LerpBase.psh new file mode 100644 index 00000000..7a9ce740 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_LerpBase.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +lrp r0, c1, t3, t0 ; Lerp between textures +mul r0, r0, c3 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive.psh new file mode 100644 index 00000000..64501f74 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +mul r1, c1, t3 +mad r0, t0, c3, r1 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive_selfillum.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive_selfillum.psh new file mode 100644 index 00000000..07f9d387 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_Detail_additive_selfillum.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t3 + +mul r0, c3, t0 +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, c1, t3, r0 + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapNoTexture.psh new file mode 100644 index 00000000..4ce3caca --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapNoTexture.psh @@ -0,0 +1,14 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t1 ; cube map + +mul r0.rgb, t1, c2 + ; envmap * envmaptint (color only) + +mov r0.a, c3.a ; Use alpha from modulation... (?) + +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapV2.psh new file mode 100644 index 00000000..80ef4330 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvMapV2.psh @@ -0,0 +1,14 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map + +mul r0, t0, c3 ; base times modulation +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2.psh new file mode 100644 index 00000000..e6b0c6e4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2.psh @@ -0,0 +1,36 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Environment mapping on a bumped surface +; t0 - Normalmap +; t3 - Cube environment map (*must* be a cube map!) +; +; c0 - color to multiply the results by +; Input texture coords required here are a little wonky. +; tc0.uv <- U,V into the normal map +; tc1.uvw, tc2.uvw, tc3.uvw <- 3x3 matrix transform +; from tangent space->env map space +; tc1.q, tc2.q, tc3.q <- eye vector in env map space +;------------------------------------------------------------------------------ +; This version doesn't multiply by lighting. + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +; result goes in output color +mul r0.rgb, t3, c0 ; constant color ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha.psh new file mode 100644 index 00000000..9fa7db3e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha.psh @@ -0,0 +1,42 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Environment mapping on a bumped surface +; t0 - Normalmap +; t3 - Cube environment map (*must* be a cube map!) +; +; c0 - color to multiply the results by +; Input texture coords required here are a little wonky. +; tc0.uv <- U,V into the normal map +; tc1.uvw, tc2.uvw, tc3.uvw <- 3x3 matrix transform +; from tangent space->env map space +; tc1.q, tc2.q, tc3.q <- eye vector in env map space +;------------------------------------------------------------------------------ +; This version doesn't multiply by lighting. + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +; result goes in output color +mul r0.rgb, t3, c0 ; constant color ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + +; Multiply the output color by the alpha channel of the normal map. +mul r0.rgb, t0.a, r0 + + + + + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14.psh new file mode 100644 index 00000000..eac900c9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_MultByAlpha_ps14.psh @@ -0,0 +1,42 @@ +ps.1.4 +;------------------------------------------------------------------------------ +; Phase 1 +;------------------------------------------------------------------------------ +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! +;mov r0.rgba, r4 + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) +; Alpha gets lost after phase marker, so store it here +mov r5, r0.a +;------------------------------------------------------------------------------ +; Phase 2 +;------------------------------------------------------------------------------ +phase +; Sample environment map +texld r3, r2 +; Result goes in output color (multiply by constant color c0) +mul r0.rgb, r3, c0 ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + +; mult by alpha +mul r0.rgb, r0, r5 diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_ps14.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_ps14.psh new file mode 100644 index 00000000..7c88013f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmapV2_ps14.psh @@ -0,0 +1,39 @@ +ps.1.4 +;------------------------------------------------------------------------------ +; Phase 1 +;------------------------------------------------------------------------------ +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) +; Alpha gets lost after phase marker, so store it here +mov r5, r0.a +;------------------------------------------------------------------------------ +; Phase 2 +;------------------------------------------------------------------------------ +phase +; Sample environment map +texld r3, r2 +; Result goes in output color (multiply by constant color c0) +mul r0.rgb, r3, c0 ++mov r0.a, c0.a + +mul r1.rgb, r0, r0 +lrp r0.rgb, c1, r1, r0 ; blend between color and color * color +dp3 r1.rgb, r0, c3 +lrp r0.rgb, c2, r0, r1 ; blend between color and greyscale + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting.vsh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting.vsh new file mode 100644 index 00000000..576e31cf --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting.vsh @@ -0,0 +1,93 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$worldTangentS ); +&AllocateRegister( \$worldTangentT ); + +&SkinPositionNormalAndTangentSpace( $worldPos, $worldNormal, + $worldTangentS, $worldTangentT ); + +;------------------------------------------------------------------------------ +; Transform the position from world to proj space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +; svect +mov oT1.x, $worldTangentS.x +mov oT2.x, $worldTangentS.y +mov oT3.x, $worldTangentS.z +&FreeRegister( \$worldTangentS ); + +; tvect +mov oT1.y, $worldTangentT.x +mov oT2.y, $worldTangentT.y +mov oT3.y, $worldTangentT.z +&FreeRegister( \$worldTangentT ); + +; normal +mov oT1.z, $worldNormal.x +mov oT2.z, $worldNormal.y +mov oT3.z, $worldNormal.z + +&FreeRegister( \$worldNormal ); + +; Compute the vector from vertex to camera +&AllocateRegister( \$eyeVector ); +sub $eyeVector.xyz, $cEyePos, $worldPos + +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $eyeVector.x +mov oT2.w, $eyeVector.y +mov oT3.w, $eyeVector.z + +&FreeRegister( \$eyeVector ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.vsh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.vsh new file mode 100644 index 00000000..2ac66164 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_EnvmappedBumpmap_NoLighting_ps14.vsh @@ -0,0 +1,90 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +;------------------------------------------------------------------------------ +; Shader specific constant: +; $SHADER_SPECIFIC_CONST_5 = [sOffset, tOffset, 0, 0] +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$worldTangentS ); +&AllocateRegister( \$worldTangentT ); + +&SkinPositionNormalAndTangentSpace( $worldPos, $worldNormal, + $worldTangentS, $worldTangentT ); + +;------------------------------------------------------------------------------ +; Transform the position from world to proj space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +; svect +mov oT1.x, $worldTangentS.x +mov oT2.x, $worldTangentS.y +mov oT3.x, $worldTangentS.z +&FreeRegister( \$worldTangentS ); + +; tvect +mov oT1.y, $worldTangentT.x +mov oT2.y, $worldTangentT.y +mov oT3.y, $worldTangentT.z +&FreeRegister( \$worldTangentT ); + +; normal +mov oT1.z, $worldNormal.x +mov oT2.z, $worldNormal.y +mov oT3.z, $worldNormal.z + +&FreeRegister( \$worldNormal ); + +; Compute the vector from vertex to camera +&AllocateRegister( \$eyeVector ); +sub $eyeVector.xyz, $cEyePos, $worldPos + +&FreeRegister( \$worldPos ); + +; eye vector +mov oT4.xyz, $eyeVector + +&FreeRegister( \$eyeVector ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapNoTexture.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapNoTexture.psh new file mode 100644 index 00000000..4c65d906 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapNoTexture.psh @@ -0,0 +1,15 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t1 ; cube map +tex t2 ; envmap mask + +mul r1, t1, t2 ; Envmap * mask +mul r0.rgb, r1, c2 ; envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 + ; * 2 * (overbrightFactor/2) +mul r0.a, c3.a, t2.a ; alpha = modulation * mask alpha + +#if WRITEONETODESTALPHA +mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapV2.psh new file mode 100644 index 00000000..ffa3f1e0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_MaskedEnvMapV2.psh @@ -0,0 +1,16 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, t2 ; Envmap * mask +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) +mad r0.rgb, r1, c2, r0 ; + envmap * mask * tint + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_NoTexture.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_NoTexture.psh new file mode 100644 index 00000000..b98b9396 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_NoTexture.psh @@ -0,0 +1,9 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +mul r0, v0, c3 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.psh new file mode 100644 index 00000000..86710123 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.psh @@ -0,0 +1,5 @@ +ps.1.1 + +tex t0 + +mul r0.rgba, c0, t0 diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.vsh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.vsh new file mode 100644 index 00000000..40eb8d28 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIllumOnly.vsh @@ -0,0 +1,41 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&SkinPosition( $worldPos ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$projPos ); +&FreeRegister( \$worldPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminated.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminated.psh new file mode 100644 index 00000000..c837e9af --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminated.psh @@ -0,0 +1,19 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 + +; interpolate between illuminated + non-selfilluminated +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedEnvMapV2.psh new file mode 100644 index 00000000..2d280f5c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedEnvMapV2.psh @@ -0,0 +1,21 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 +tex t1 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedMaskedEnvMapV2.psh b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedMaskedEnvMapV2.psh new file mode 100644 index 00000000..da6b77c3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitGeneric_SelfIlluminatedMaskedEnvMapV2.psh @@ -0,0 +1,23 @@ +; DYNAMIC: "WRITEONETODESTALPHA" "0..1" +ps.1.1 + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +#if WRITEONETODESTALPHA ++mov r0.a, c4 ; make alpha 255 +#endif diff --git a/sp/src/materialsystem/stdshaders/VertexLitTexture.psh b/sp/src/materialsystem/stdshaders/VertexLitTexture.psh new file mode 100644 index 00000000..7a692c92 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitTexture.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 + +mul r0, t0, v0 + diff --git a/sp/src/materialsystem/stdshaders/VertexLitTexture_Overbright2.psh b/sp/src/materialsystem/stdshaders/VertexLitTexture_Overbright2.psh new file mode 100644 index 00000000..a69250bf --- /dev/null +++ b/sp/src/materialsystem/stdshaders/VertexLitTexture_Overbright2.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 + +mul_x2 r0.rgb, t0, v0 ++ mul r0.a, t0, v0 + diff --git a/sp/src/materialsystem/stdshaders/WaterCheapFresnelOpaque_ps14.psh b/sp/src/materialsystem/stdshaders/WaterCheapFresnelOpaque_ps14.psh new file mode 100644 index 00000000..08438dcb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapFresnelOpaque_ps14.psh @@ -0,0 +1,40 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 +texld r4, t5 ; Normalize the tangent-space eye vector + +; dot eye-vector with per-pixel normal from r0 +dp3_sat r1, r4_bx2, r0_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r0.a, 1-r1.a, 1-r1.a ; squared +mul r0.a, r0.a, r0.a ; quartic +mul_sat r1.a, r0.a, 1-r1.a ; quintic + +; multiply color by reflecttint +mul r0, r3, c1 + +; blend between reflected color and fog color based on fresnel +lrp r0.rgb, r1.a, r0, c0 \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/WaterCheapFresnel_ps14.psh b/sp/src/materialsystem/stdshaders/WaterCheapFresnel_ps14.psh new file mode 100644 index 00000000..5ebb39f4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapFresnel_ps14.psh @@ -0,0 +1,39 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 +texld r4, t5 ; Normalize the tangent-space eye vector + +; dot eye-vector with per-pixel normal from r0 +dp3_sat r1, r4_bx2, r0_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +mul r0.a, 1-r1.a, 1-r1.a ; squared +mul r0.a, r0.a, r0.a ; quartic +mul_sat r1.a, r0.a, 1-r1.a ; quintic + +; multiply color by reflecttint +mul r0.rgb, r3, c1 ++mov_sat r0.a, v0.a +add_sat r0.a, r1.a, r0.a diff --git a/sp/src/materialsystem/stdshaders/WaterCheapNoFresnelOpaque_ps11.psh b/sp/src/materialsystem/stdshaders/WaterCheapNoFresnelOpaque_ps11.psh new file mode 100644 index 00000000..60502016 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapNoFresnelOpaque_ps11.psh @@ -0,0 +1,19 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0, t3, c1 ; multiply color by reflecttint +lrp r0.rgb, c1.a, r0, c0 ; blend between reflected color and fog color based on constant factor + + + + + diff --git a/sp/src/materialsystem/stdshaders/WaterCheapNoFresnel_ps11.psh b/sp/src/materialsystem/stdshaders/WaterCheapNoFresnel_ps11.psh new file mode 100644 index 00000000..fe76d772 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapNoFresnel_ps11.psh @@ -0,0 +1,18 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0.rgb, t3, c1 ; multiply color by reflecttint ++mov_sat r0.a, v0.a ; NOTE: This is necessary since v0.a can be outside 0 - 1! +add_sat r0.a, c1.a, r0.a ; cheap water blend factor + constant blend factor + + + diff --git a/sp/src/materialsystem/stdshaders/WaterCheapOpaque_ps11.psh b/sp/src/materialsystem/stdshaders/WaterCheapOpaque_ps11.psh new file mode 100644 index 00000000..50d7f803 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapOpaque_ps11.psh @@ -0,0 +1,26 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0, t3, c1 ; envmap color * envmaptint + +dp3_sat t2, v0_bx2, t0_bx2 ; dot eye-vector with per-pixel normal from t0 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +; NOTE: This is not perspective-correct and results in strange artifacts +mul r1.a, 1-t2.a, 1-t2.a ; squared +mul r1.a, r1.a, r1.a ; quartic +mul_sat r1.a, r1.a, 1-t2.a ; quintic + +; t1.a is now the fresnel factor +lrp r0.rgb, r1.a, r0, c0 ; blend between reflected color and fog color based on fresnel + + diff --git a/sp/src/materialsystem/stdshaders/WaterCheapOpaque_ps14.psh b/sp/src/materialsystem/stdshaders/WaterCheapOpaque_ps14.psh new file mode 100644 index 00000000..bd491d58 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapOpaque_ps14.psh @@ -0,0 +1,31 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 + +; multiply color by reflecttint +mul r0, r3, c1 + +; blend between reflected color and fog color based on constant factor +lrp r0.rgb, c1.a, r0, c0 diff --git a/sp/src/materialsystem/stdshaders/WaterCheapPerVertexFresnel_vs11.vsh b/sp/src/materialsystem/stdshaders/WaterCheapPerVertexFresnel_vs11.vsh new file mode 100644 index 00000000..6ca504cf --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheapPerVertexFresnel_vs11.vsh @@ -0,0 +1,100 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $worldEyeVect.x +mov oT2.w, $worldEyeVect.y +mov oT3.w, $worldEyeVect.z + +&AllocateRegister( \$tangentEyeVect ); + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +&Normalize( $tangentEyeVect ); +mov oD0.xyz, $tangentEyeVect + +&FreeRegister( \$tangentEyeVect ); + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_2.x +mul oD0.w, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_2.y + +&FreeRegister( \$worldEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/sp/src/materialsystem/stdshaders/WaterCheap_ps11.psh b/sp/src/materialsystem/stdshaders/WaterCheap_ps11.psh new file mode 100644 index 00000000..34178d28 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheap_ps11.psh @@ -0,0 +1,26 @@ +ps.1.1 + +; Get the 3-vector from the normal map +tex t0 + +; Perform matrix multiply to get a local normal bump. Then +; reflect the eye vector through the normal and sample from +; a cubic environment map. +texm3x3pad t1, t0_bx2 +texm3x3pad t2, t0_bx2 +texm3x3vspec t3, t0_bx2 + +mul r0.rgb, t3, c1 ; envmap color * envmaptint ++mov_sat r0.a, v0.a ; Put the cheap water blend factor here + +dp3_sat t2, v0_bx2, t0_bx2 ; dot eye-vector with per-pixel normal from t0 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 in alpha channel +; NOTE: This is not perspective-correct and results in strange artifacts +mul r1.a, 1-t2.a, 1-t2.a ; squared +mul r1.a, r1.a, r1.a ; quartic +mul_sat r1.a, r1.a, 1-t2.a ; quintic + +; t1.a is now the fresnel factor +add_sat r0.a, r1.a, r0.a ; Now we have the final blend factor between cheap water + refraction + diff --git a/sp/src/materialsystem/stdshaders/WaterCheap_ps14.psh b/sp/src/materialsystem/stdshaders/WaterCheap_ps14.psh new file mode 100644 index 00000000..2c452539 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheap_ps14.psh @@ -0,0 +1,30 @@ +ps.1.4 + +; Get the 3-vector from the normal map +texld r0, t0 +; Get environment matrix +texcrd r1.rgb, t1 +texcrd r2.rgb, t2 +texcrd r3.rgb, t3 +; Normalize eye-ray vector through normalizer cube map +texld r4, t4 ; <---- CUBE MAP here!!! + +; Transform normal +dp3 r5.r, r1, r0_bx2 +dp3 r5.g, r2, r0_bx2 +dp3 r5.b, r3, r0_bx2 +; Reflection calculatiom +dp3_x2 r3.rgb, r5, r4_bx2 ; 2(N.Eye) +mul r3.rgb, r5, r3 ; 2N(N.Eye) +dp3 r2.rgb, r5, r5 ; N.N +mad r2.rgb, -r4_bx2, r2, r3 ; 2N(N.Eye) - Eye(N.N) + +phase + +; Sample environment map +texld r3, r2 + +; multiply color by reflecttint +mul r0.rgb, r3, c1 ++mov_sat r0.a, v0.a ; Necessary since v0.a may be negative +add_sat r0.a, c1.a, r0.a diff --git a/sp/src/materialsystem/stdshaders/WaterCheap_ps2x.fxc b/sp/src/materialsystem/stdshaders/WaterCheap_ps2x.fxc new file mode 100644 index 00000000..4ca66570 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheap_ps2x.fxc @@ -0,0 +1,152 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "FRESNEL" "0..1" +// STATIC: "BLEND" "0..1" +// STATIC: "REFRACTALPHA" "0..1" +// STATIC: "HDRTYPE" "0..2" +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] + +// DYNAMIC: "HDRENABLED" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +#include "common_ps_fxc.h" + +const HALF3 g_WaterFogColor : register( c0 ); +const HALF4 g_CheapWaterParams : register( c1 ); +const HALF4 g_ReflectTint : register( c2 ); +const float4 g_PixelFogParams : register( c3 ); + +#define g_CheapWaterStart g_CheapWaterParams.x +#define g_CheapWaterEnd g_CheapWaterParams.y +#define g_CheapWaterDeltaRecip g_CheapWaterParams.z +#define g_CheapWaterStartDivDelta g_CheapWaterParams.w + +sampler EnvmapSampler : register( s0 ); +sampler NormalMapSampler : register( s1 ); +#if REFRACTALPHA +sampler RefractSampler : register( s2 ); +#endif +sampler NormalizeSampler : register( s6 ); + +struct PS_INPUT +{ + float2 normalMapTexCoord : TEXCOORD0; + HALF3 worldSpaceEyeVect : TEXCOORD1; + HALF3x3 tangentSpaceTranspose : TEXCOORD2; + float4 vRefract_W_ProjZ : TEXCOORD5; + +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; +#endif + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBlend = BLEND ? true : false; + +#if MULTITEXTURE + float3 vNormal = tex2D( NormalMapSampler, i.normalMapTexCoord ); + float3 vNormal1 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.xy ); + float3 vNormal2 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.zw ); + vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 ); + +#if ( NORMAL_DECODE_MODE == NORM_DECODE_ATI2N ) + vNormal.xy = vNormal.xy * 2.0f - 1.0f; + vNormal.z = sqrt( 1.0f - dot(vNormal.xy, vNormal.xy) ); +#else + vNormal = 2.0 * vNormal - 1.0; +#endif + +#else + float3 vNormal = DecompressNormal( NormalMapSampler, i.normalMapTexCoord, NORMAL_DECODE_MODE ); +#endif + + HALF3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); + HALF3 worldSpaceEye; + + HALF flWorldSpaceDist = 1.0f; + +#ifdef NV3X + // for some reason, fxc doesn't convert length( half3 v ) into all _pp opcodes. + if (bBlend) + { + worldSpaceEye = i.worldSpaceEyeVect; + HALF worldSpaceDistSqr = dot( worldSpaceEye, worldSpaceEye ); + HALF rcpWorldSpaceDist = rsqrt( worldSpaceDistSqr ); + worldSpaceEye *= rcpWorldSpaceDist; + flWorldSpaceDist = worldSpaceDistSqr * rcpWorldSpaceDist; + } + else + { + worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect ); + } +#else // !NV3X + if (bBlend) + { + worldSpaceEye = i.worldSpaceEyeVect; + flWorldSpaceDist = length( worldSpaceEye ); + worldSpaceEye /= flWorldSpaceDist; + } + else + { + worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect ); + } +#endif + + HALF3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldSpaceEye ); + HALF3 specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= g_ReflectTint; + +#if FRESNEL + // FIXME: It's unclear that we want to do this for cheap water + // but the code did this previously and I didn't want to change it + HALF flDotResult = dot( worldSpaceEye, worldSpaceNormal ); + flDotResult = 1.0f - max( 0.0f, flDotResult ); + + HALF flFresnelFactor = flDotResult * flDotResult; + flFresnelFactor *= flFresnelFactor; + flFresnelFactor *= flDotResult; +#else + HALF flFresnelFactor = g_ReflectTint.a; +#endif + + HALF flAlpha; + if (bBlend) + { + HALF flReflectAmount = saturate( flWorldSpaceDist * g_CheapWaterDeltaRecip - g_CheapWaterStartDivDelta ); + flAlpha = saturate( flFresnelFactor + flReflectAmount ); + +#if REFRACTALPHA + // Perform division by W only once + float ooW = 1.0f / i.vRefract_W_ProjZ.z; + float2 unwarpedRefractTexCoord = i.vRefract_W_ProjZ * ooW; + float fogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a; + // Fade on the border between the water and land. + flAlpha *= saturate( ( fogDepthValue - .05f ) * 20.0f ); +#endif + } + else + { + flAlpha = 1.0f; +#if HDRTYPE == 0 || HDRENABLED == 0 + specularLighting = lerp( g_WaterFogColor, specularLighting, flFresnelFactor ); +#else + specularLighting = lerp( GammaToLinear( g_WaterFogColor ), specularLighting, flFresnelFactor ); +#endif + } + + // multiply the color by alpha.since we are using alpha blending to blend against dest alpha for borders. + + + +#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE) + float fogFactor = CalcRangeFog( i.vRefract_W_ProjZ.w, g_PixelFogParams.x, g_PixelFogParams.z, g_PixelFogParams.w ); +#else + float fogFactor = 0; +#endif + + return FinalOutput( float4( specularLighting, flAlpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/sp/src/materialsystem/stdshaders/WaterCheap_vs11.vsh b/sp/src/materialsystem/stdshaders/WaterCheap_vs11.vsh new file mode 100644 index 00000000..b1cdd61f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheap_vs11.vsh @@ -0,0 +1,88 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; Move it into the w component of the texture coords, as the wacky +; pixel shader wants it there. +mov oT1.w, $worldEyeVect.x +mov oT2.w, $worldEyeVect.y +mov oT3.w, $worldEyeVect.z + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_2.x +mul oD0, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_2.y + +&FreeRegister( \$worldEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/sp/src/materialsystem/stdshaders/WaterCheap_vs14.vsh b/sp/src/materialsystem/stdshaders/WaterCheap_vs14.vsh new file mode 100644 index 00000000..0e5a1074 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheap_vs14.vsh @@ -0,0 +1,96 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ + +&AllocateRegister( \$worldPos ); + +; Transform position from object to world +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&AllocateRegister( \$projPos ); + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ + +; Transform tangent space basis vectors to env map space (world space) +; This will produce a set of vectors mapping from tangent space to env space +; We'll use this to transform normals from the normal map from tangent space +; to environment map space. +; NOTE: use dp3 here since the basis vectors are vectors, not points + +dp3 oT1.x, $vTangentS, $cModel0 +dp3 oT2.x, $vTangentS, $cModel1 +dp3 oT3.x, $vTangentS, $cModel2 + +dp3 oT1.y, $vTangentT, $cModel0 +dp3 oT2.y, $vTangentT, $cModel1 +dp3 oT3.y, $vTangentT, $cModel2 + +dp3 oT1.z, $vNormal, $cModel0 +dp3 oT2.z, $vNormal, $cModel1 +dp3 oT3.z, $vNormal, $cModel2 + +; Compute the vector from vertex to camera +&AllocateRegister( \$worldEyeVect ); +sub $worldEyeVect.xyz, $cEyePos, $worldPos +&FreeRegister( \$worldPos ); + +; eye vector +mov oT4.xyz, $worldEyeVect + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_2.x +mul oD0, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_2.y + +; stick the tangent space eye vector into oT5.xyz +mov oT5.xyz, $tangentEyeVect + +&FreeRegister( \$worldEyeVect ); +&FreeRegister( \$tangentEyeVect ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + + diff --git a/sp/src/materialsystem/stdshaders/WaterCheap_vs20.fxc b/sp/src/materialsystem/stdshaders/WaterCheap_vs20.fxc new file mode 100644 index 00000000..bae02380 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterCheap_vs20.fxc @@ -0,0 +1,84 @@ +// STATIC: "BLEND" "0..1" +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vNormalMapCoord : TEXCOORD0; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 normalMapTexCoord : TEXCOORD0; + float3 worldVertToEyeVector : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + float4 vRefract_W_ProjZ : TEXCOORD5; + float4 vExtraBumpTexCoord : TEXCOORD6; + float4 fogFactorW : COLOR1; +}; + +const float4 cNormalMapTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 TexOffsets : register( SHADER_SPECIFIC_CONST_3 ); + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + + projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + +#if BLEND + // Map projected position to the reflection texture + o.vRefract_W_ProjZ.x = projPos.x; + o.vRefract_W_ProjZ.y = -projPos.y; // invert Y + o.vRefract_W_ProjZ.xy = (o.vRefract_W_ProjZ + projPos.w) * 0.5f; + o.vRefract_W_ProjZ.z = projPos.w; +#endif + + o.vRefract_W_ProjZ.w = projPos.z; + + worldPos = mul( v.vPos, cModel[0] ); + + float3 worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + float3 worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + o.tangentSpaceTranspose[0] = worldTangentS; + o.tangentSpaceTranspose[1] = worldTangentT; + o.tangentSpaceTranspose[2] = worldNormal; + + float3 worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + o.worldVertToEyeVector = worldVertToEyeVector; + + // FIXME: need to add a normalMapTransform to all of the water shaders. + //o.normalMapTexCoord.x = dot( v.vNormalMapCoord, cNormalMapTransform[0] ) + cNormalMapTransform[0].w; + //o.normalMapTexCoord.y = dot( v.vNormalMapCoord, cNormalMapTransform[1] ) + cNormalMapTransform[1].w; + o.normalMapTexCoord = v.vNormalMapCoord; + + float f45x=v.vNormalMapCoord.x+v.vNormalMapCoord.y; + float f45y=v.vNormalMapCoord.y-v.vNormalMapCoord.x; + o.vExtraBumpTexCoord.x=f45x*0.1+TexOffsets.x; + o.vExtraBumpTexCoord.y=f45y*0.1+TexOffsets.y; + o.vExtraBumpTexCoord.z=v.vNormalMapCoord.y*0.45+TexOffsets.z; + o.vExtraBumpTexCoord.w=v.vNormalMapCoord.x*0.45+TexOffsets.w; + + o.fogFactorW = CalcFog( worldPos, projPos, FOGTYPE_RANGE ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/WaterReflect_ps11.psh b/sp/src/materialsystem/stdshaders/WaterReflect_ps11.psh new file mode 100644 index 00000000..d31ab49c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterReflect_ps11.psh @@ -0,0 +1,27 @@ +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: reflection render target +; texcoords: +; t2: +; texture: normal map (usef for fresnel calculation) +; texcoords: +; t4: texture: normalization cube map +; texcoords: eye vect + +tex t0 ; sample dudv map +texbem t1, t0 ; reflection +tex t2 ; normal map +tex t3 ; eye vector (through normalization cubemap) + +; dot eye-vector with per-pixel normal from t2 +dp3_sat r1.rgba, t3_bx2, t2_bx2 + +; run Fresnel approx. on it: R0 + (1-R0) (1-cos(q))^5 +mul r0.a, 1-r1.a, 1-r1.a // squared +mul r0.a, r0.a, r0.a // quartic +mul r0.rgb, t1, c0 // shove color from reflection render target into r0 ++mul_sat r0.a, r0.a, 1-r1.a // quintic \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/WaterRefractFresnel_ps11.psh b/sp/src/materialsystem/stdshaders/WaterRefractFresnel_ps11.psh new file mode 100644 index 00000000..88d1f8dc --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterRefractFresnel_ps11.psh @@ -0,0 +1,24 @@ +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: refraction render target +; texcoords: + +tex t0 ; sample dudv map +texbem t1, t0 ; refraction +tex t2 ; The normal map +tex t3 ; Normalize the tangent-space vector to the eye + +; dot eye-vector with per-pixel normal from t2 +dp3_sat r1.rgba, t2_bx2, t3_bx2 + +mul r0.a, 1-r1.a, 1-r1.a ; squared +mul r0.a, r0.a, r0.a ; quartic + +mul r0.rgb, t1, c0 ++mul_sat r0.a, r0.a, 1-r1.a ; quintic + +add_sat r0.a, r0.a, v0.a ; cheap water distance diff --git a/sp/src/materialsystem/stdshaders/WaterRefract_ps11.psh b/sp/src/materialsystem/stdshaders/WaterRefract_ps11.psh new file mode 100644 index 00000000..7e3ee733 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WaterRefract_ps11.psh @@ -0,0 +1,13 @@ +ps.1.1 + +; t0: +; texture: dudv map +; texcoords: dudvmap texcoords +; t1: +; texture: refraction render target +; texcoords: + +tex t0 ; sample dudv map +texbem t1, t0 ; refraction + +mul r0, t1, c0 diff --git a/sp/src/materialsystem/stdshaders/Water_ps14.psh b/sp/src/materialsystem/stdshaders/Water_ps14.psh new file mode 100644 index 00000000..e9daecd1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Water_ps14.psh @@ -0,0 +1,96 @@ +; STATIC: "REFLECT" "0..1" +; STATIC: "REFRACT" "0..1" +ps.1.4 +; T2 - refraction +; T3 - normal map +; T4 - reflection +; TC0 - normal map coords +; TC1 - proj tex coords (reflection) +; TC2 - proj tex coords (refraction) +; TC3 - tangent space view vec +; TC4 - displacement scale + +; sample normal map +texld r3, t0 + +#if REFLECT +; reflection coords +texcrd r4.xy, t1_dw.xyw +#endif +#if REFRACT +; refraction coords +texcrd r2.xy, t2_dw.xyw +#endif +; tangent space eye vector +texld r1, t5 ; <---- Normalizing CUBE MAP here!!! +; reflection/refraction scale (x,y) +texcrd r0.xyz, t4.xyz + +; perturb coords by constant displacement +; and by normal map alpha (which has 1/(2**miplevel in it) +mul r0.rg, r0, r3.a +#if REFLECT +mad r4.rg, r3_bx2, r0.x, r4 +#endif + +#if REFRACT +mad r2.rg, r3_bx2, r0.y, r2 +#endif + +; stuff something into z so that texld will deal +#if REFLECT +mov r4.b, c5 +#endif +#if REFRACT +mov r2.b, c5 +#endif + +phase + +#if REFLECT +; reflection +texld r4, r4 +#endif +#if REFRACT +; refraction +texld r2, r2 +#endif + +#if REFLECT +; N.V +dp3_sat r1.a, r3_bx2, r1_bx2 +#endif + +#if REFRACT +; tint refraction +mul r2.rgb, r2, c1 +#endif + +#if REFLECT +; tint reflction +mul r4.rgb, r4, c4 + +; (1-N.V) ^ 5 ++mul r0.a, 1-r1.a, 1-r1.a +mul r0.a, r0.a, r0.a +mul_sat r0.a, r0.a, 1-r1.a +#endif + +#if !REFLECT && !REFRACT +; This is wrong!!!! +mov r0.rgba, c0 +#endif + +#if !REFLECT && REFRACT +mov r0.rgba, r2 +#endif + +#if REFLECT && !REFRACT +mov r0.rgba, r4 +#endif + +#if REFLECT && REFRACT +; reflection * fresnel + refraction * ( 1 - fresnel ) +lrp r0.rgba, r0.a, r4, r2 +#endif + diff --git a/sp/src/materialsystem/stdshaders/Water_ps14.vsh b/sp/src/materialsystem/stdshaders/Water_ps14.vsh new file mode 100644 index 00000000..0ec30aa7 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Water_ps14.vsh @@ -0,0 +1,95 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; $SHADER_SPECIFIC_CONST_0..$SHADER_SPECIFIC_CONST_3 - special proj matrix +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + + +alloc $projPos + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos + +; Transform position from object to world space +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +alloc $tangentEyeVect + +; transform the eye vector to tangent space +dp3 $tangentEyeVect.x, $worldEyeVect, $vTangentS +dp3 $tangentEyeVect.y, $worldEyeVect, $vTangentT +dp3 $tangentEyeVect.z, $worldEyeVect, $vNormal +mov $tangentEyeVect.w, $cZero + +mov oT5, $tangentEyeVect + +; base coordinates +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +; reflection +alloc $projPosReflect + +mov $projPosReflect, $projPos +add $projPosReflect.xy, $projPosReflect, $projPosReflect.w +mul $projPosReflect.xy, $projPosReflect, $cHalf +mov oT1, $projPosReflect + +; refraction +mov $projPos.y, -$projPos.y +add $projPos.xy, $projPos, $projPos.w +mul $projPos.xy, $projPos, $cHalf +mov oT2, $projPos + +; reflectionscale, refractionscale +mov oT4, $SHADER_SPECIFIC_CONST_4 + +free $worldEyeVect +free $tangentEyeVect +free $projPosReflect +free $worldPos +free $projPos \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/Water_vs11.vsh b/sp/src/materialsystem/stdshaders/Water_vs11.vsh new file mode 100644 index 00000000..3b0131b8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Water_vs11.vsh @@ -0,0 +1,102 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +;------------------------------------------------------------------------------ +; Constants specified by the app +; c0 = (0, 1, 2, 0.5) +; c1 = (1/2.2, 0, 0, 0) +; c2 = camera position *in world space* +; c4-c7 = modelViewProj matrix (transpose) +; c8-c11 = ViewProj matrix (transpose) +; c12-c15 = model->view matrix (transpose) +; c16 = [fogStart, fogEnd, fogRange, undefined] +; +; Vertex components (as specified in the vertex DECL) +; $vPos = Position +; $vTexCoord0.xy = TexCoord0 +;------------------------------------------------------------------------------ + +#include "macros.vsh" + +; Vertex components +; $vPos = Position +; $vNormal = normal +; $vTexCoord0.xy = TexCoord0 +; $vTangentS = S axis of Texture space +; $vTangentT = T axis of Texture space + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +alloc $projPos + +; Transform position from object to projection space +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 + +alloc $worldPos + +; Transform position from object to world space +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +alloc $worldEyeVect + +; Get the eye vector in world space +add $worldEyeVect.xyz, -$worldPos, $cEyePos + +; transform the eye vector to tangent space +dp3 oT3.x, $worldEyeVect, $vTangentS +dp3 oT3.y, $worldEyeVect, $vTangentT +dp3 oT3.z, $worldEyeVect, $vNormal + +; Get the magnitude of worldEyeVect +dp3 $worldEyeVect.w, $worldEyeVect, $worldEyeVect +rsq $worldEyeVect.w, $worldEyeVect.w +rcp $worldEyeVect.w, $worldEyeVect.w + +; calculate the cheap water blend factor and stick it into oD0.a +; NOTE: This won't be perspective correct!!!!! +; OPTIMIZE: This could turn into a mad. +add $worldEyeVect.w, $worldEyeVect.w, -$SHADER_SPECIFIC_CONST_3.x +mul oD0, $worldEyeVect.w, $SHADER_SPECIFIC_CONST_3.y + +; dudv map +alloc $bumpTexCoord + +dp4 $bumpTexCoord.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 $bumpTexCoord.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + +mov oT0.xy, $bumpTexCoord + +; normal map +mov oT2.xy, $bumpTexCoord + +free $bumpTexCoord + +alloc $newProjPos + +mov oPos, $projPos + +; special case perspective correct texture projection so that the texture fits exactly on the screen +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_4.w +add $projPos.xy, $projPos.xy, $projPos.w +mul $projPos.xy, $projPos.xy, $cHalf + +mov oT1.xy, $projPos.xy +mov oT1.z, $cZero +mov oT1.w, $projPos.w + +free $projPos +free $worldPos +free $worldEyeVect +free $projTangentS +free $projTangentT +free $newProjPos diff --git a/sp/src/materialsystem/stdshaders/Water_vs20.fxc b/sp/src/materialsystem/stdshaders/Water_vs20.fxc new file mode 100644 index 00000000..8f3a7a81 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/Water_vs20.fxc @@ -0,0 +1,117 @@ +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "MULTITEXTURE" "0..1" + +// SKIP: $MULTITEXTURE && $BASETEXTURE + +#include "common_vs_fxc.h" + +const float4 cBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); +const float4 TexOffsets : register( SHADER_SPECIFIC_CONST_3 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vNormal : NORMAL; + float4 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos_POSITION : POSITION; +#if !defined( _X360 ) + float vFog : FOG; +#endif + float2 vBumpTexCoord : TEXCOORD0; + float3 vTangentEyeVect : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float W : TEXCOORD3; + float4 vProjPos : TEXCOORD4; + float screenCoord : TEXCOORD5; +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; +#endif +#if BASETEXTURE + HALF4 lightmapTexCoord1And2 : TEXCOORD6; + HALF4 lightmapTexCoord3 : TEXCOORD7; +#endif + float4 fogFactorW : COLOR1; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + // Projected position + float4 vProjPos = mul( v.vPos, cModelViewProj ); + o.vProjPos = o.vProjPos_POSITION = vProjPos; + + // Project tangent basis + float2 vProjTangentS = mul( v.vTangentS, cViewProj ); + float2 vProjTangentT = mul( v.vTangentT, cViewProj ); + + // Map projected position to the reflection texture + float2 vReflectPos; + vReflectPos = (vProjPos.xy + vProjPos.w) * 0.5f; + + // Map projected position to the refraction texture + float2 vRefractPos; + vRefractPos.x = vProjPos.x; + vRefractPos.y = -vProjPos.y; // invert Y + vRefractPos = (vRefractPos + vProjPos.w) * 0.5f; + + // Reflection transform + o.vReflectXY_vRefractYX = float4( vReflectPos.x, vReflectPos.y, vRefractPos.y, vRefractPos.x ); + o.W = vProjPos.w; + + o.screenCoord = vProjPos.x; + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.fogFactorW = CalcFog( vWorldPos, vProjPos, FOGTYPE_RANGE ); +#if !defined( _X360 ) + o.vFog = o.fogFactorW; +#endif + + // Eye vector + float3 vWorldEyeVect = cEyePos - vWorldPos; + // Transform to the tangent space + o.vTangentEyeVect.x = dot( vWorldEyeVect, v.vTangentS ); + o.vTangentEyeVect.y = dot( vWorldEyeVect, v.vTangentT ); + o.vTangentEyeVect.z = dot( vWorldEyeVect, vObjNormal ); + + // Tranform bump coordinates + o.vBumpTexCoord.x = dot( v.vBaseTexCoord, cBumpTexCoordTransform[0] ); + o.vBumpTexCoord.y = dot( v.vBaseTexCoord, cBumpTexCoordTransform[1] ); + float f45x=v.vBaseTexCoord.x+v.vBaseTexCoord.y; + float f45y=v.vBaseTexCoord.y-v.vBaseTexCoord.x; +#if MULTITEXTURE + o.vExtraBumpTexCoord.x=f45x*0.1+TexOffsets.x; + o.vExtraBumpTexCoord.y=f45y*0.1+TexOffsets.y; + o.vExtraBumpTexCoord.z=v.vBaseTexCoord.y*0.45+TexOffsets.z; + o.vExtraBumpTexCoord.w=v.vBaseTexCoord.x*0.45+TexOffsets.w; +#endif + +#if BASETEXTURE + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; +#endif + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/WorldTexture.psh b/sp/src/materialsystem/stdshaders/WorldTexture.psh new file mode 100644 index 00000000..6144fdf2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldTexture.psh @@ -0,0 +1,14 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +mov r0, t0 + diff --git a/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend.psh b/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend.psh new file mode 100644 index 00000000..b9494b02 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mov r0.rgb, t0 + +mul r0.a, t0.a, v0.a ; Grab alpha from vertex color + +lrp r0.rgb, t2.a, t2, r0 ; Base = base * (1 - detail alpha) + detail * detail alpha +mul r0.rgb, r0, v0 ; modulate by vertex color +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend_DetailAlpha.psh b/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend_DetailAlpha.psh new file mode 100644 index 00000000..033730bb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend_DetailAlpha.psh @@ -0,0 +1,25 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +def c1, 1.0f, 1.0f, 1.0f, 1.0f + +tex t0 +tex t1 +tex t2 + +mov_x2_sat r0.rgb, t0 + ; r0 = sat( t0 * 2 ) +mul r0.a, t0.a, v0.a ; Grab alpha from vertex color + +lrp_sat r0.rgb, t2.a, r0, c1 ; r0 = B*Da + (1-Da) + +mul r0.rgb, r0, t2 ; modulate by detail color +mul r0.rgb, r0, v0 ; modulate by vertex color +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend_SelfIlluminated.psh b/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend_SelfIlluminated.psh new file mode 100644 index 00000000..2f5a8ca5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldTwoTextureBlend_SelfIlluminated.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mov r0.rgb, t0 + +mov r0.a, v0.a ; Grab alpha from vertex color + +lrp r0.rgb, t2.a, t2, r0 ; Base = base * (1 - detail alpha) + detail * detail alpha +mul r0.rgb, r0, v0 ; modulate by vertex color +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1.rgb, c1, t0 ; Self illum * tint ++ mul r1.a, t0.a, 1-t2.a ; Reduce self-illum amount based on 1 - detailalpha + +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lightmap + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexAlpha.psh b/sp/src/materialsystem/stdshaders/WorldVertexAlpha.psh new file mode 100644 index 00000000..e610452e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexAlpha.psh @@ -0,0 +1,10 @@ +ps.1.1 + +tex t0 ; basetexture +tex t1 ; lightmap + +mov r0.a, 1-t1.a +;mov r0.rgb, t0 ; * 2 * (overbrightFactor/2) +;mov_x2 r0.rgb, t0 ; * 2 * (overbrightFactor/2) +mul r0.rgb, t0, t1; +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/WorldVertexAlpha.vsh b/sp/src/materialsystem/stdshaders/WorldVertexAlpha.vsh new file mode 100644 index 00000000..ae2566a6 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexAlpha.vsh @@ -0,0 +1,37 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +mov oT0, $vTexCoord0 + +; lightmap texcoords +mov oT1, $vTexCoord1 + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc b/sp/src/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc new file mode 100644 index 00000000..7ccc584a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexAlpha_ps2x.fxc @@ -0,0 +1,43 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "PASS" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +// CENTROID: TEXCOORD1 + +sampler BaseSampler : register( s0 ); +sampler LightmapSampler: register( s1 ); +sampler LightmapAlphaSampler: register( s2 ); + +struct PS_INPUT +{ + float2 baseCoord : TEXCOORD0; + float2 lightmapCoord : TEXCOORD1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bAlphaPass = PASS ? true : false; + + float4 base = tex2D( BaseSampler, i.baseCoord ); + float4 lightmap = tex2D( LightmapSampler, i.lightmapCoord ); + float4 alpha = tex2D( LightmapAlphaSampler, i.lightmapCoord ); + + float4 color; + + base.a = dot( base, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) ); + color = 2.0f * base * lightmap; // The 2x is for an assumed overbright 2 (it's always 2 on dx9) + + if( bAlphaPass ) + { + // Don't care about color, just return pre-multiplied alpha + return FinalOutput( float4( 0.0f, 0.0f, 1.0f, (1.0f - alpha.a) * color.a ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } + else + { + return FinalOutput( float4( color.rgb, (1.0f - alpha.a) ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); + } +} + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition.psh b/sp/src/materialsystem/stdshaders/WorldVertexTransition.psh new file mode 100644 index 00000000..4fd2882b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition.psh @@ -0,0 +1,18 @@ +; STATIC: "DETAIL" "0..1" +ps.1.1 + +tex t0 ; basetexture +tex t1 ; basetexture2 +tex t2 ; lightmap +#if DETAIL +tex t3 ; detail +#endif + +mov_sat r1.a, v0.a +lrp r0, r1.a, t1, t0 + +mul r0, r0, t2 +#if DETAIL +mul_x2 r0.rgb, r0, t3 +#endif +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition.vsh b/sp/src/materialsystem/stdshaders/WorldVertexTransition.vsh new file mode 100644 index 00000000..81e56dbe --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition.vsh @@ -0,0 +1,48 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +; lightmap texcoords +mov oT2, $vTexCoord1 + +; detail +dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh b/sp/src/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh new file mode 100644 index 00000000..d4a5c623 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_BlendBase2.psh @@ -0,0 +1,16 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +mul r0.rgb, t1, t0 ; fold in lightmap (color) ++mov r0.a, v0.a ; fold in lightmap (alpha) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_Editor.psh b/sp/src/materialsystem/stdshaders/WorldVertexTransition_Editor.psh new file mode 100644 index 00000000..936edc9e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_Editor.psh @@ -0,0 +1,10 @@ +ps.1.1 + +tex t0 ; basetexture +tex t1 ; basetexture2 +tex t2 ; lightmap + +; The editor uses vertex alpha as the blend factor +lrp r0, 1-v0.a, t1, t0 +mul r0, r0, t2 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.psh b/sp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.psh new file mode 100644 index 00000000..8d4edad0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.psh @@ -0,0 +1,23 @@ +ps.1.1 + +def c0, 1.0f, 0.0f, 0.0f, 0.0f +def c1, 0.0f, 1.0f, 0.0f, 0.0f +def c2, 0.0f, 0.0f, 1.0f, 0.0f + +tex t0 ; basetexture zy +tex t1 ; basetexture xz +tex t2 ; basetexture xy +tex t3 ; lightmap + +dp3_sat r1, v0, c0 +mul r0, t0, r1 + +dp3_sat r1, v0, c1 +mad r0, t1, r1, r0 + +dp3_sat r1, v0, c2 +mad r0, t2, r1, r0 + +; multiply by lightmap +mul_x2 r0.rgb, r0, t3 ++mov r0.a, v0 ; $vColor diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.vsh b/sp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.vsh new file mode 100644 index 00000000..dd0cc99c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_Seamless.vsh @@ -0,0 +1,54 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +alloc $projPos + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +alloc $worldPos +alloc $worldNormal + +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 + +dp3 $worldNormal.x, $vNormal, $cModel0 +dp3 $worldNormal.y, $vNormal, $cModel1 +dp3 $worldNormal.z, $vNormal, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +free $projPos + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +alloc $texcoord +mul $texcoord.xyz, $worldPos, $SHADER_SPECIFIC_CONST_0 + +mov oT0.xy, $texcoord.zy; +mov oT1.xy, $texcoord.xz; +mov oT2.xy, $texcoord.xy; + +free $texcoord + +; lightmap texcoords +mov oT3, $vTexCoord1 + +mul oD0.rgb, $worldNormal, $worldNormal + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0.a, $vColor + +free $worldPos +free $worldNormal diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_dx8.cpp b/sp/src/materialsystem/stdshaders/WorldVertexTransition_dx8.cpp new file mode 100644 index 00000000..331f8f17 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_dx8.cpp @@ -0,0 +1,537 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "worldvertextransition.inc" +#include "worldvertextransition_vs14.inc" +#include "worldvertextransition_seamless.inc" +#include "lightmappedgeneric_vs11.inc" +#include "writevertexalphatodestalpha_vs11.inc" +#include "worldvertextransition_dx8_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX8 ) + +ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +BEGIN_VS_SHADER( WorldVertexTransition_DX8, + "Help for WorldVertexTransition_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture2", "base texture2 help" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $baseTexture" ) + SHADER_PARAM( BASETEXTURETRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$baseTexture texcoord transform" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map for BASETEXTURE" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( BUMPBASETEXTURE2WITHBUMPMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "0.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "WorldVertexTransition_DX6"; + return 0; + } + + void SetupVars( WorldVertexTransitionEditor_DX8_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTextureTransformVar = BASETEXTURETRANSFORM; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nBaseTexture2FrameVar = FRAME2; + info.m_nBaseTexture2TransformVar = BASETEXTURETRANSFORM2; + } + + SHADER_INIT_PARAMS() + { + // Initializes FLASHLIGHTTEXTURE + MATERIAL_VAR2_LIGHTING_LIGHTMAP + WorldVertexTransitionEditor_DX8_Vars_t info; + SetupVars( info ); + InitParamsWorldVertexTransitionEditor_DX8( params, info ); + + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( IsUsingGraphics() && params[ENVMAP]->IsDefined() && !CanUseEditorMaterials() ) + { + if( stricmp( params[ENVMAP]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + { + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + { + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + if( !params[BUMPBASETEXTURE2WITHBUMPMAP]->IsDefined() ) + { + params[BUMPBASETEXTURE2WITHBUMPMAP]->SetIntValue( 0 ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[DETAILFRAME]->IsDefined() ) + { + params[DETAILFRAME]->SetIntValue( 0 ); + } + + if( params[SEAMLESS_SCALE]->IsDefined() && params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + // seamless scale is going to be used, so kill some other features. . might implement with these features later. + params[DETAIL]->SetUndefined(); + params[BUMPMAP]->SetUndefined(); + params[ENVMAP]->SetUndefined(); + } + + if ( !params[SEAMLESS_SCALE]->IsDefined() ) + { + // zero means don't do seamless mapping. + params[SEAMLESS_SCALE]->SetFloatValue( 0.0f ); + } + + if( params[SSBUMP]->IsDefined() && params[SSBUMP]->GetIntValue() != 0 ) + { + // turn of normal mapping since we have ssbump defined, which + // means that we didn't make a dx8 fallback for this material. + params[BUMPMAP]->SetUndefined(); + } + } + SHADER_INIT + { + // Loads BASETEXTURE, BASETEXTURE2 + WorldVertexTransitionEditor_DX8_Vars_t info; + SetupVars( info ); + InitWorldVertexTransitionEditor_DX8( this, params, info ); + + // FLASHLIGHTFIXME + if ( params[FLASHLIGHTTEXTURE]->IsDefined() ) + { + LoadTexture( FLASHLIGHTTEXTURE ); + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + if ( g_pHardwareConfig->SupportsPixelShaders_1_4() && params[BLENDMODULATETEXTURE]->IsDefined() ) + { + LoadTexture( BLENDMODULATETEXTURE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( params[ENVMAP]->IsDefined() && !params[BUMPMAP]->IsDefined() ) + { + Warning( "must have $bumpmap if you have $envmap for worldvertextransition\n" ); + params[ENVMAP]->SetUndefined(); + params[BUMPMAP]->SetUndefined(); + } + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + LoadBumpMap( BUMPMAP ); + } + if( params[ENVMAP]->IsDefined() ) + { + if( !IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ) ) + { + LoadCubeMap( ENVMAP ); + } + else + { + Warning( "$envmapsphere not supported by worldvertextransition\n" ); + params[ENVMAP]->SetUndefined(); + } + } + } + + void WriteVertexAlphaToDestAlpha( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + if( pShaderShadow ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( false ); + + writevertexalphatodestalpha_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "writevertexalphatodestalpha_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "writevertexalphatodestalpha_ps11" ); + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR, 2, 0, 0 ); + } + else + { + writevertexalphatodestalpha_vs11_Dynamic_Index vshIndex; + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + void DrawFlashlightPass( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, int passID ) + { + bool bBump = ( passID == 0 ) && ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture(); + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, true, passID, BASETEXTURE2, FRAME2 ); + } + + bool ShouldUseBumpmapping( IMaterialVar **params ) + { + return g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + WriteVertexAlphaToDestAlpha( params, pShaderAPI, pShaderShadow ); + DrawFlashlightPass( params, pShaderAPI, pShaderShadow, 0 ); + DrawFlashlightPass( params, pShaderAPI, pShaderShadow, 1 ); + } + + SHADER_DRAW + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + bool bSupports14 = g_pHardwareConfig->SupportsPixelShaders_1_4(); + + // FLASHLIGHTFIXME: need to make these the same. + bool hasFlashlight = UsingFlashlight( params ); + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow ); + } + else if ( params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + // This is the seamless_scale version, which doesn't use $detail or $bumpmap + SHADOW_STATE + { + // three copies of the base texture for seamless blending + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_seamless_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_Seamless", vshIndex.GetIndex() ); + + int pshIndex = 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_Seamless", pshIndex ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + // Texture 0..2 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + float fSeamlessScale = params[SEAMLESS_SCALE]->GetFloatValue(); + float map_scale[4]= { fSeamlessScale, fSeamlessScale, fSeamlessScale, fSeamlessScale }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + + worldvertextransition_seamless_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + SHADOW_STATE + { + // inherit state from previous pass + + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + DYNAMIC_STATE + { + if( !bLightingOnly ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE2, FRAME2 ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE2, FRAME2 ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE2, FRAME2 ); + } + } + Draw(); + } + else if( !params[BUMPMAP]->IsTexture() || !g_pConfig->UseBumpmapping() ) + { + bool bDetail = params[DETAIL]->IsTexture(); + bool bBlendModulate = params[BLENDMODULATETEXTURE]->IsTexture(); + SHADOW_STATE + { + // This is the dx8, non-worldcraft version, non-bumped version + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if( bDetail ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + if ( bSupports14 && bBlendModulate ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + int fmt = VERTEX_POSITION | VERTEX_COLOR; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + if ( !bSupports14 ) + { + worldvertextransition_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition", vshIndex.GetIndex() ); + + int pshIndex = bDetail ? 1 : 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition", pshIndex ); + } + else + { + worldvertextransition_vs14_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_vs14", vshIndex.GetIndex() ); + + int pshIndex = bDetail ? 1 : 0; + pshIndex += bBlendModulate ? 2 : 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_ps14", pshIndex ); + } + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Texture 1 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE2, FRAME2 ); + } + if( bDetail ) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + } + if ( bSupports14 && bBlendModulate ) + { + BindTexture( SHADER_SAMPLER4, BLENDMODULATETEXTURE ); + } + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + // go ahead and set this even if we don't have a detail texture so the vertex shader doesn't + // barf chunks with unitialized data. + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + + if ( bSupports14 ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, BLENDMASKTRANSFORM ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM2 ); + if ( !bSupports14 ) + { + worldvertextransition_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + worldvertextransition_vs14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); + } + else + { + if( params[BUMPBASETEXTURE2WITHBUMPMAP]->GetIntValue() ) + { + DrawWorldBumpedUsingVertexShader( BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, + ENVMAPFRAME, ENVMAPTINT, COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, + FRESNELREFLECTION, true, BASETEXTURE2, BASETEXTURETRANSFORM2, FRAME2, false ); + } + else + { + // draw the base texture with everything else you normally would for + // bumped world materials + DrawWorldBumpedUsingVertexShader( + BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, ENVMAPFRAME, ENVMAPTINT, + COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, + FRESNELREFLECTION, + false, -1, -1, -1, false ); + + // blend basetexture 2 on top of everything using lightmap alpha. + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR, 2, 0, 0 ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( true ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WorldVertexTransition_BlendBase2" ); + FogToFogColor(); + } + DYNAMIC_STATE + { + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE2, FRAME2 ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + float half[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 4, half ); + EnablePixelShaderOverbright( 0, true, true ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM2 ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + } + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_ps14.psh b/sp/src/materialsystem/stdshaders/WorldVertexTransition_ps14.psh new file mode 100644 index 00000000..763a5d11 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_ps14.psh @@ -0,0 +1,32 @@ +; STATIC: "DETAIL" "0..1" +; STATIC: "BLENDMODULATETEXTURE" "0..1" +ps.1.4 + +def c1, 3.0, -2.0, 0.5, 0.5 + +texld r0, t0 +texld r1, t1 +texld r2, t2 +#if DETAIL +texld r3, t3 ; detail +#endif +#if BLENDMODULATETEXTURE +texld r4, t4 ; detail +#endif + +#if BLEND_MODULATETEXTURE +sub r5.a, v0.a, r4.g +add_sat r5.a, r5.a, c1.a +mad r6.a, c1.g, r5.a, c1.r +mul r6.a, r6.a, r5.a +mul r5.a, r6.a, r5.a +#else +mov_sat r5.a, v0.a +#endif +lrp r0, r5.a, r1, r0 + +mul r0, r0, r2 +#if DETAIL +mul_x2 r0.rgb, r0, r3 +#endif +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc b/sp/src/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc new file mode 100644 index 00000000..f27e870d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_ps2x.fxc @@ -0,0 +1,47 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "MACROS" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + + +sampler BaseSampler : register( s0 ); +// NOTE: LightmapSampler is at the same place as the lightmap sampler in lightmappedgeneric so that we have +// generally the same texture state here. +// CENTROID: TEXCOORD1 +sampler LightmapSampler: register( s1 ); +sampler BaseSampler2: register( s2 ); +sampler LightmapAlphaSampler: register( s3 ); +sampler MacrosSampler: register( s4 ); + +struct PS_INPUT +{ + float2 baseCoord : TEXCOORD0; + float2 baseCoord2 : TEXCOORD1; + float2 lightmapCoord : TEXCOORD2; + float2 macrosCoord : TEXCOORD3; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bMacros = MACROS ? true : false; + + float4 base = tex2D( BaseSampler, i.baseCoord ); + float4 base2 = tex2D( BaseSampler2, i.baseCoord2 ); + + float4 lightmap = tex2D( LightmapSampler, i.lightmapCoord ); + float blendFactor = lightmap.a; + + float4 color = 2.0f * lightmap * lerp( base2, base, blendFactor ); + if( bMacros ) + { + float4 macros = tex2D( MacrosSampler, i.macrosCoord ); + + // Not sure what to do with macro alpha + color.rgb *= 2.0f * lerp( macros.a, macros.b, blendFactor ); + } + + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_vs14.vsh b/sp/src/materialsystem/stdshaders/WorldVertexTransition_vs14.vsh new file mode 100644 index 00000000..eecc1c89 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_vs14.vsh @@ -0,0 +1,52 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); + +; garymcthack +dp4 $worldPos.z, $vPos, $cModel2 + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$worldPos ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +; base texcoords +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + +; lightmap texcoords +mov oT2, $vTexCoord1 + +; detail +dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 +dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + +; mask +dp4 oT4.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_6 +dp4 oT4.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_7 + +; Now the basetexture/basetexture2 blend uses vertex color, so send it into the psh. +mov oD0, $vColor + +&FreeRegister( \$worldPos ); # garymcthack + diff --git a/sp/src/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc b/sp/src/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc new file mode 100644 index 00000000..5f18ca81 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/WorldVertexTransition_vs20.fxc @@ -0,0 +1,64 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cBaseTexCoordTransform2[2] : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cMacrosTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseCoord : TEXCOORD0; + float2 baseCoord2 : TEXCOORD1; + float2 lightmapCoord : TEXCOORD2; + float2 macrosCoord : TEXCOORD3; + float4 color : COLOR0; + float4 fogFactorW : COLOR1; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldNormal, worldPos; + float2 texCoord; + worldPos = mul( v.vPos, cModel[0] ); + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + o.color = v.vColor; + + o.baseCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + o.baseCoord2.x = dot( v.vTexCoord0, cBaseTexCoordTransform2[0] ); + o.baseCoord2.y = dot( v.vTexCoord0, cBaseTexCoordTransform2[1] ); + + o.lightmapCoord = v.vTexCoord1; + + o.macrosCoord.x = dot( v.vTexCoord0, cMacrosTexCoordTransform[0] ); + o.macrosCoord.y = dot( v.vTexCoord0, cMacrosTexCoordTransform[1] ); + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/cable_dx6.cpp b/sp/src/materialsystem/stdshaders/cable_dx6.cpp new file mode 100644 index 00000000..9b11551f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cable_dx6.cpp @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX6 ) + +BEGIN_SHADER( Cable_DX6, + "Help for Cable_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.25", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.25", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + int GetDrawFlagsPass1(IMaterialVar** params ) + { + int flags = SHADER_DRAW_POSITION; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + flags |= SHADER_DRAW_TEXCOORD0; + return flags; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + SetNormalBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params) ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + Vector min, max; + params[MINLIGHT]->GetVecValue( &min.x, 3 ); + params[MAXLIGHT]->GetVecValue( &max.x, 3 ); + Vector avg = ( min + max ) * 0.5f; + pShaderAPI->Color3fv( &avg.x ); + } + Draw( ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/cable_dx8.cpp b/sp/src/materialsystem/stdshaders/cable_dx8.cpp new file mode 100644 index 00000000..9e3c98dd --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cable_dx8.cpp @@ -0,0 +1,132 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A wet version of base * lightmap +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "cable.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX8 ) + +BEGIN_VS_SHADER( Cable_DX8, + "Help for Cable shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "cable/cablenormalmap", "bumpmap texture" ) + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.1", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.3", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && !g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + return "UnlitGeneric_DX6"; + } + return 0; + } + + SHADER_INIT + { + LoadBumpMap( BUMPMAP ); + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Enable blending? + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + int tCoordDimensions[] = {2,2}; + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR | VERTEX_TANGENT_S | VERTEX_TANGENT_T, + 2, tCoordDimensions, 0 ); + + cable_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Cable", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "Cable" ); + + // we are writing linear values from this shader. + // This is kinda wrong. We are writing linear or gamma depending on "IsHDREnabled" below. + // The COLOR really decides if we are gamma or linear. + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBWrite( true ); + } + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BUMPMAP ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + + + // The dot product with the light is remapped from the range + // [-1,1] to [MinLight, MaxLight]. + + // Given: + // -A + B = MinLight + // A + B = MaxLight + // then A = (MaxLight - MinLight) / 2 + // and B = (MaxLight + MinLight) / 2 + + // So here, we multiply the light direction by A to scale the dot product. + // Then in the pixel shader we add by B. + float flMinLight = params[MINLIGHT]->GetFloatValue(); + float flMaxLight = params[MAXLIGHT]->GetFloatValue(); + + float A = (flMaxLight - flMinLight) * 0.5f; + float B = (flMaxLight + flMinLight) * 0.5f; + + float b4[4] = {B,B,B,B}; + if( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + SetPixelShaderConstantGammaToLinear( 0, b4 ); + } + else + { + pShaderAPI->SetPixelShaderConstant( 0, b4 ); + } + + // This is the light direction [0,1,0,0] * A * 0.5 + float lightDir[4] = {0, A*0.5, 0, 0}; + if( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + SetVertexShaderConstantGammaToLinear( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lightDir ); + } + else + { + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lightDir ); + } + + cable_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/cable_dx9.cpp b/sp/src/materialsystem/stdshaders/cable_dx9.cpp new file mode 100644 index 00000000..5b25ed61 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cable_dx9.cpp @@ -0,0 +1,141 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A wet version of base * lightmap +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "cable_vs20.inc" +#include "cable_ps20.inc" +#include "cable_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern ConVar mat_fullbright; + +DEFINE_FALLBACK_SHADER( Cable, Cable_DX9 ) + +BEGIN_VS_SHADER( Cable_DX9, + "Help for Cable shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "cable/cablenormalmap", "bumpmap texture" ) + SHADER_PARAM( MINLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.1", "Minimum amount of light (0-1 value)" ) + SHADER_PARAM( MAXLIGHT, SHADER_PARAM_TYPE_FLOAT, "0.3", "Maximum amount of light" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( !(g_pHardwareConfig->SupportsPixelShaders_2_0() && g_pHardwareConfig->SupportsVertexShaders_2_0()) || + (g_pHardwareConfig->GetDXSupportLevel() < 90) ) + { + return "Cable_DX8"; + } + return 0; + } + + SHADER_INIT + { + LoadBumpMap( BUMPMAP ); + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + } + + SHADER_DRAW + { + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + // Enable blending? + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + int tCoordDimensions[] = {2,2}; + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_COLOR | VERTEX_TANGENT_S | VERTEX_TANGENT_T, + 2, tCoordDimensions, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( cable_vs20 ); + SET_STATIC_VERTEX_SHADER( cable_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( cable_ps20b ); + SET_STATIC_PIXEL_SHADER( cable_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( cable_ps20 ); + SET_STATIC_PIXEL_SHADER( cable_ps20 ); + } + + // we are writing linear values from this shader. + // This is kinda wrong. We are writing linear or gamma depending on "IsHDREnabled" below. + // The COLOR really decides if we are gamma or linear. + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + + BindTexture( SHADER_SAMPLER0, BUMPMAP ); + if ( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + + } + else + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( cable_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER( cable_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( cable_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( cable_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( cable_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( cable_ps20 ); + } + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/cable_ps2x.fxc b/sp/src/materialsystem/stdshaders/cable_ps2x.fxc new file mode 100644 index 00000000..a3c7ff13 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cable_ps2x.fxc @@ -0,0 +1,54 @@ +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler NormalSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + + float4 directionalLightColor : COLOR0; + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 vNormalMapDir = tex2D( NormalSampler, i.vTexCoord0 ); // Get the 3-vector from the normal map + float4 textureColor = tex2D( BaseTextureSampler, i.vTexCoord1 ); // Interpret tcoord t1 as color data. + + //Expand compacted vectors + //TODO: find if there's a better way to expand a color normal to a full vector ( _bx2 was used in the assembly code ) + vNormalMapDir = (vNormalMapDir - 0.5) * 2.0; + float3 vLightDir = float3( 0.0f, 0.0f, 1.0f ); + + float lightDirDotNormalMap = dot( vNormalMapDir, vLightDir ); //normalMap dot dirLightDir + + // do half-lambert on the dot + lightDirDotNormalMap = lightDirDotNormalMap * 0.5 + 0.5; + lightDirDotNormalMap = lightDirDotNormalMap * lightDirDotNormalMap; + + float4 resultColor; + resultColor.xyz = lightDirDotNormalMap * ( textureColor.rgb * i.directionalLightColor.rgb ); + resultColor.a = textureColor.a * i.directionalLightColor.a; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/sp/src/materialsystem/stdshaders/cable_vs20.fxc b/sp/src/materialsystem/stdshaders/cable_vs20.fxc new file mode 100644 index 00000000..adb3559e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cable_vs20.fxc @@ -0,0 +1,80 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 directionalLightColor : COLOR0; + + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + + float4 directionalLightColor : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + //------------------------------------------------------------------------------ + // Setup the tangent space + //------------------------------------------------------------------------------ + + // Get S crossed with T (call it R) + float3 r = cross( v.vTangentS, v.vTangentT ); + + // Normalize S (into s) + float3 s = normalize( v.vTangentS ); + + // Normalize R (into r) + r = normalize( r ); + + // Regenerate T (into t) + float3 t = cross( r, v.vTangentS ); + + //------------------------------------------------------------------------------ + // Copy texcoords for the normal map and base texture + //------------------------------------------------------------------------------ + o.vTexCoord0 = v.vTexCoord0; + o.vTexCoord1 = v.vTexCoord1; + + // Pass the dirlight color through + o.directionalLightColor = v.directionalLightColor; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/cloud.cpp b/sp/src/materialsystem/stdshaders/cloud.cpp new file mode 100644 index 00000000..810e6c4d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud.cpp @@ -0,0 +1,76 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( Cloud, + "Help for Cloud" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + LoadTexture( CLOUDALPHATEXTURE ); + if( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + if( g_pHardwareConfig->GetSamplerCount() >= 2 ) + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | + SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_TEXCOORD1 ); + DefaultFog(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // handle scrolling of base texture + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE0, + BASETEXTURETRANSFORM, CLOUDSCALE ); + SetFixedFunctionTextureScale( MATERIAL_TEXTURE1, MASKSCALE ); + } + Draw(); + } + else + { + ShaderWarning("Cloud not supported for single-texturing boards!\n"); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/cloud_dx8.cpp b/sp/src/materialsystem/stdshaders/cloud_dx8.cpp new file mode 100644 index 00000000..d3bc2530 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud_dx8.cpp @@ -0,0 +1,77 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "cloud_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Cloud_dx8, "Help for Cloud" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( CLOUDALPHATEXTURE, TEXTUREFLAGS_SRGB ); + if ( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if ( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, 0, 0 ); + + cloud_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "cloud_vs11", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "cloud_ps11" ); + + DefaultFog(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // handle scrolling of base texture + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM, CLOUDSCALE ); + SetVertexShaderTextureScale( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, MASKSCALE ); + + pShaderAPI->SetVertexShaderIndex( 0 ); + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/cloud_dx9.cpp b/sp/src/materialsystem/stdshaders/cloud_dx9.cpp new file mode 100644 index 00000000..4b04b8b4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud_dx9.cpp @@ -0,0 +1,94 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// DirectX 9 Cloud shader +// +//=============================================================================== + +#include "BaseVSShader.h" +#include "cloud_vs20.inc" +#include "cloud_ps20.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Cloud, Cloud_dx9 ) + +BEGIN_VS_SHADER( Cloud_dx9, "Help for Cloud" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloud", "cloud texture", 0 ) + SHADER_PARAM( CLOUDALPHATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/cloudalpha", "cloud alpha texture" ) + SHADER_PARAM( CLOUDSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "cloudscale" ) + SHADER_PARAM( MASKSCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "maskscale" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "Cloud_dx8"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( CLOUDALPHATEXTURE, TEXTUREFLAGS_SRGB ); + if ( !params[CLOUDSCALE]->IsDefined() ) + { + params[CLOUDSCALE]->SetVecValue( 1.0f, 1.0f ); + } + if ( !params[MASKSCALE]->IsDefined() ) + { + params[MASKSCALE]->SetVecValue( 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + if ( IS_FLAG_SET( MATERIAL_VAR_ADDITIVE ) ) + { + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + else + { + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( cloud_vs20 ); + SET_STATIC_VERTEX_SHADER( cloud_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( cloud_ps20 ); + SET_STATIC_PIXEL_SHADER( cloud_ps20 ); + + DefaultFog(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, CLOUDALPHATEXTURE ); + + // Handle scrolling of base texture + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM, CLOUDSCALE ); + SetVertexShaderTextureScale( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, MASKSCALE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( cloud_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( cloud_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( cloud_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( cloud_ps20 ); + } + + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/cloud_ps11.psh b/sp/src/materialsystem/stdshaders/cloud_ps11.psh new file mode 100644 index 00000000..8e5627cb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud_ps11.psh @@ -0,0 +1,6 @@ +ps.1.1 + +tex t0 +tex t1 + +mul r0, t0, t1 diff --git a/sp/src/materialsystem/stdshaders/cloud_ps20.fxc b/sp/src/materialsystem/stdshaders/cloud_ps20.fxc new file mode 100644 index 00000000..31f8bbd2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud_ps20.fxc @@ -0,0 +1,26 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler CloudAlphaSampler : register( s1 ); + +struct PS_INPUT +{ + float2 baseCoords : TEXCOORD0; + float2 cloudAlphaCoords : TEXCOORD1; + float fogFactor : TEXCOORD2; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 vBase = tex2D( BaseTextureSampler, i.baseCoords ); + float4 vCloudAlpha = tex2D( CloudAlphaSampler, i.cloudAlphaCoords ); + + float fogFactor = 2.0f * smoothstep( 0.3f, 0.6f, i.fogFactor ); + + float4 result = vBase * vCloudAlpha; + result.a *= fogFactor; + + // No actual fog. Use the "fog factor" to modulate alpha (after some smoothstep mojo) + return FinalOutput( result, 1.0f, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} diff --git a/sp/src/materialsystem/stdshaders/cloud_vs11.vsh b/sp/src/materialsystem/stdshaders/cloud_vs11.vsh new file mode 100644 index 00000000..6348937e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud_vs11.vsh @@ -0,0 +1,26 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..0" + +#include "macros.vsh" + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + +&AllocateRegister( \$worldPos ); +; $worldPos unused, for above water, range fog calcs +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); +&FreeRegister( \$worldPos ); + +dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 +dp4 oT1.x, $vTexCoord1, $SHADER_SPECIFIC_CONST_2 +dp4 oT1.y, $vTexCoord1, $SHADER_SPECIFIC_CONST_3 + diff --git a/sp/src/materialsystem/stdshaders/cloud_vs20.fxc b/sp/src/materialsystem/stdshaders/cloud_vs20.fxc new file mode 100644 index 00000000..3655e9fa --- /dev/null +++ b/sp/src/materialsystem/stdshaders/cloud_vs20.fxc @@ -0,0 +1,37 @@ +#include "common_vs_fxc.h" + +const float4 g_matBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_matCloudTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseCoords : TEXCOORD0; + float2 cloudAlphaCoords : TEXCOORD1; + float fogFactor : TEXCOORD2; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + o.projPos = mul( v.vPos, cModelViewProj ); + + // Compute fog based on the position + float3 vWorldPos = mul( v.vPos, cModel[0] ); + o.fogFactor = CalcFog( vWorldPos, o.projPos, FOGTYPE_RANGE ); + + // Texture coordinate transforms + o.baseCoords.x = dot( v.vTexCoord0.xyzw, g_matBaseTexCoordTransform[0] ); + o.baseCoords.y = dot( v.vTexCoord0.xyzw, g_matBaseTexCoordTransform[1] ); + o.cloudAlphaCoords.x = dot( v.vTexCoord1.xyzw, g_matCloudTexCoordTransform[0] ); + o.cloudAlphaCoords.y = dot( v.vTexCoord1.xyzw, g_matCloudTexCoordTransform[1] ); + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/debugdepth.cpp b/sp/src/materialsystem/stdshaders/debugdepth.cpp new file mode 100644 index 00000000..65e55e0c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugdepth.cpp @@ -0,0 +1,113 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/cshader.h" +#include "convar.h" +#include "debugdrawdepth_vs20.inc" +#include "debugdrawdepth_ps20.inc" +#include "debugdrawdepth_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_debugdepthmode( "mat_debugdepthmode", "0" ); +static ConVar mat_debugdepthval( "mat_debugdepthval", "128.0f" ); +static ConVar mat_debugdepthvalmax( "mat_debugdepthvalmax", "256.0f" ); + +BEGIN_SHADER_FLAGS( DebugDepth, "Help for DebugDepth", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { +// Assert( 0 ); + return "WireFrame"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + SET_STATIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawdepth_ps20b ); + SET_STATIC_PIXEL_SHADER( debugdrawdepth_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugdrawdepth_ps20 ); + SET_STATIC_PIXEL_SHADER( debugdrawdepth_ps20 ); + } + } + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, s_pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugdrawdepth_vs20 ); + + Vector4D vecZFilter( 0, 0, 0, 1 ); + int nDepthMode = mat_debugdepthmode.GetInt(); + if ( nDepthMode > 1 ) + { + nDepthMode = 0; + } + + vecZFilter[nDepthMode] = 1; + s_pShaderAPI->SetPixelShaderConstant( 1, vecZFilter.Base() ); + + Vector4D vecModulationColor( 0, 0, 0, 1 ); + if ( IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) + { + vecModulationColor[0] = 0; + vecModulationColor[1] = 1; + vecModulationColor[2] = 1; + } + else + { + vecModulationColor[0] = 1; + vecModulationColor[1] = 1; + vecModulationColor[2] = 1; + } + s_pShaderAPI->SetPixelShaderConstant( 2, vecModulationColor.Base() ); + + float flDepthFactor = mat_debugdepthval.GetFloat(); + float flDepthFactorMax = mat_debugdepthvalmax.GetFloat(); + if ( flDepthFactor == 0 ) + { + flDepthFactor = 1.0f; + } + Vector4D vecZFactor( (flDepthFactorMax - flDepthFactor), flDepthFactor, 1, 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vecZFactor.Base() ); + } + Draw(); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/debugluxel.cpp b/sp/src/materialsystem/stdshaders/debugluxel.cpp new file mode 100644 index 00000000..b3135fcb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugluxel.cpp @@ -0,0 +1,140 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/cshader.h" + +#define USE_NEW_SHADER //Updating assembly shaders to fxc, this is for A/B testing. + +#ifdef USE_NEW_SHADER + +#include "unlitgeneric_vs20.inc" +#include "unlitgeneric_ps20.inc" +#include "unlitgeneric_ps20b.inc" + +#endif + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( DebugLuxels, "Help for DebugLuxels", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( NOSCALE, SHADER_PARAM_TYPE_BOOL, "0", "fixme" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } +#endif +} + +SHADER_INIT +{ + LoadTexture( BASETEXTURE ); +} + +SHADER_DRAW +{ + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + if (IS_FLAG_SET(MATERIAL_VAR_TRANSLUCENT)) + { + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + else + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + bool bVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bVertexColor ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } +#endif + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + int texCoordScaleX = 1, texCoordScaleY = 1; + if (!params[NOSCALE]->GetIntValue()) + { + pShaderAPI->GetLightmapDimensions( &texCoordScaleX, &texCoordScaleY ); + } + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + float vVertexColor[4] = { IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, vVertexColor, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + + //texture scale transform + Vector4D transformation[2]; + transformation[0].Init( (float)texCoordScaleX, 0.0f, 0.0f, 0.0f ); + transformation[1].Init( 0.0f, (float)texCoordScaleY, 0.0f, 0.0f ); + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, transformation[0].Base(), 2 ); + } + else +#endif + { + if (!params[NOSCALE]->GetIntValue()) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE0 ); + pShaderAPI->LoadIdentity( ); + pShaderAPI->ScaleXY( texCoordScaleX, texCoordScaleY ); + } + } + } + Draw(); +} +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/debugmodifyvertex.cpp b/sp/src/materialsystem/stdshaders/debugmodifyvertex.cpp new file mode 100644 index 00000000..c497ca95 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmodifyvertex.cpp @@ -0,0 +1,93 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This is an example of a material that modifies vertex data +// in the shader. NOTE: Every pass is given a clean set of vertex data. +// Modifications made in the first pass are *not* carried over to the next pass +// Modifications must take place during the DYNAMIC_STATE block. +// Use the function MeshBuilder() to build the mesh +// +// Also note: Using thie feature is *really expensive*! It makes a copy of +// the vertex data *per pass!* If you wish to modify vertex data to be used +// with all passes, your best bet is to construct a dynamic mesh instead. +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER_FLAGS( DebugModifyVertex, "Help for DebugModifyVertex", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( WAVE, SHADER_PARAM_TYPE_FLOAT, "1.0", "wave amplitude" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + if( g_pHardwareConfig->GetSamplerCount() >= 2 ) + { + // lightmap + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableVertexDataPreprocess( true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float amp = params[WAVE]->GetFloatValue(); + float currTime = pShaderAPI->CurrentTime(); + for (int i = 0; i < MeshBuilder()->NumVertices(); ++i) + { + float const* pPos = MeshBuilder()->Position(); + MeshBuilder()->Position3f( pPos[0] + amp * sin( currTime + pPos[2] / 4 ), + pPos[1] + amp * sin( currTime + pPos[2] / 4 + 2 * 3.14 / 3 ), + pPos[2] + amp * sin( currTime + pPos[2] / 4 + 4 * 3.14 / 3 ) ); + MeshBuilder()->AdvanceVertex(); + } + } + Draw(); + + // base * vertex color + SHADOW_STATE + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | + SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Notice here that since we didn't modify the position, and this is a second + // pass, the position has been reset to it's initial, unmodified position + float currTime = pShaderAPI->CurrentTime(); + for (int i = 0; i < MeshBuilder()->NumVertices(); ++i) + { + float const* pPos = MeshBuilder()->Position(); + MeshBuilder()->Color3f( ( sin( currTime + pPos[0] ) + 1.0F) * 0.5, + ( sin( currTime + pPos[1] ) + 1.0F) * 0.5, + ( sin( currTime + pPos[2] ) + 1.0F) * 0.5 ); + MeshBuilder()->AdvanceVertex(); + } + } + Draw(); + } + else + { + ShaderWarning( "DebugModifyVertex: not " + "implemented for single-texturing hardware\n" ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp b/sp/src/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp new file mode 100644 index 00000000..2f5c6a8e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmorphaccumulator_dx9.cpp @@ -0,0 +1,64 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "debugmorphaccumulator_ps30.inc" +#include "debugmorphaccumulator_vs30.inc" + +BEGIN_VS_SHADER_FLAGS( DebugMorphAccumulator, "Help for Debug Morph Accumulator", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableCulling( false ); + pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + SET_STATIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + SET_STATIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( debugmorphaccumulator_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + SET_DYNAMIC_PIXEL_SHADER( debugmorphaccumulator_ps30 ); + } + Draw( ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc b/sp/src/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc new file mode 100644 index 00000000..b479085c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmorphaccumulator_ps30.fxc @@ -0,0 +1,16 @@ +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 vTexCoord : TEXCOORD0; +}; + +sampler MorphAccumulator : register( s0 ); + +HALF4 main( PS_INPUT i ) : COLOR +{ + float4 vDeltas = tex2D( MorphAccumulator, i.vTexCoord ); + return float4( abs( vDeltas.x ), abs( vDeltas.z ), abs( vDeltas.y ) + abs( vDeltas.w ), 1.0f ); +} + diff --git a/sp/src/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc b/sp/src/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc new file mode 100644 index 00000000..4ff8a742 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmorphaccumulator_vs30.fxc @@ -0,0 +1,23 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos = mul( v.vPos, cModelViewProj ); + o.vTexCoord = v.vTexCoord; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/debugmrttexture.cpp b/sp/src/materialsystem/stdshaders/debugmrttexture.cpp new file mode 100644 index 00000000..04a1128e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmrttexture.cpp @@ -0,0 +1,86 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "debugmrttexture_ps20.inc" +#include "debugmrttexture_ps20b.inc" +#include "debugmrttexture_vs20.inc" + +BEGIN_VS_SHADER_FLAGS( DebugMRTTexture, "Help for DebugMRTTexture", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( MRTINDEX, SHADER_PARAM_TYPE_INTEGER, "", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { +// if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) +// { +// return "UnlitGeneric_DX8"; +// } + return 0; + } + + SHADER_INIT_PARAMS() + { + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + DECLARE_STATIC_VERTEX_SHADER( debugmrttexture_vs20 ); + SET_STATIC_VERTEX_SHADER( debugmrttexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( debugmrttexture_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( MRTINDEX, params[MRTINDEX]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( debugmrttexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( debugmrttexture_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( MRTINDEX, params[MRTINDEX]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER( debugmrttexture_ps20 ); + } + + int numTexCoords = 2; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, numTexCoords, 0, 0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + DECLARE_DYNAMIC_VERTEX_SHADER( debugmrttexture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( debugmrttexture_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( debugmrttexture_ps20 ); + } + } + Draw(); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/debugmrttexture_ps2x.fxc b/sp/src/materialsystem/stdshaders/debugmrttexture_ps2x.fxc new file mode 100644 index 00000000..7764e529 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmrttexture_ps2x.fxc @@ -0,0 +1,26 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "MRTINDEX" "0..1" + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +sampler BaseTextureSampler1 : register( s0 ); +sampler BaseTextureSampler2 : register( s1 ); + +float4 main( PS_INPUT i ) : COLOR +{ +#if MRTINDEX == 0 + float4 result = tex2D( BaseTextureSampler1, i.baseTexCoord ); +#else + float4 result = tex2D( BaseTextureSampler2, i.baseTexCoord ); +#endif + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/sp/src/materialsystem/stdshaders/debugmrttexture_vs20.fxc b/sp/src/materialsystem/stdshaders/debugmrttexture_vs20.fxc new file mode 100644 index 00000000..db5c4863 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugmrttexture_vs20.fxc @@ -0,0 +1,29 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 baseTexCoord : TEXCOORD0; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 projPos; + float3 worldPos; + + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + + o.baseTexCoord = v.vBaseTexCoord; + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/debugnormalmap.cpp b/sp/src/materialsystem/stdshaders/debugnormalmap.cpp new file mode 100644 index 00000000..0be5246a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugnormalmap.cpp @@ -0,0 +1,148 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#define USE_NEW_SHADER //Updating assembly shaders to fxc, this is for A/B testing. + + + +#ifdef USE_NEW_SHADER + +#include "unlitgeneric_vs20.inc" +#include "unlitgeneric_ps20.inc" +#include "unlitgeneric_ps20b.inc" + +#endif + +#include "unlitgeneric_vs11.inc" + + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER_FLAGS( DebugNormalMap, "Help for DebugNormalMap", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldDiffuseBumpMap_bump", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + { +// Assert( 0 ); + return "Wireframe"; + } + return 0; + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + DECLARE_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, 0 ); + SET_STATIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } + else +#endif + { + unlitgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( false ); + vshIndex.SetSEPARATEDETAILUVS( false ); + pShaderShadow->SetVertexShader( "unlitgeneric_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "unlitgeneric" ); + } + } + DYNAMIC_STATE + { + if ( params[BUMPMAP]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_NORMALMAP_FLAT ); + } + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + float vVertexColor[4] = { 0, 0, 0, 0 }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, vVertexColor, 1 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( unlitgeneric_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_ps20 ); + } + } + else +#endif + { + unlitgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/debugsoftwarevertexshader.cpp b/sp/src/materialsystem/stdshaders/debugsoftwarevertexshader.cpp new file mode 100644 index 00000000..be7cedf3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugsoftwarevertexshader.cpp @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ) +{ + float t = pShaderAPI->CurrentTime(); + for( int i = 0; i < meshBuilder.NumVertices(); i++ ) + { + const float *pPos = meshBuilder.Position(); + meshBuilder.Position3f( pPos[0], pPos[1], pPos[2] + 10.0f * sin( t + pPos[0] ) ); + meshBuilder.AdvanceVertex(); + } +} + +FORWARD_DECLARE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + +BEGIN_SHADER_FLAGS( DebugSoftwareVertexShader, "blah", SHADER_NOT_EDITABLE ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/basetexture", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( FRAME, SHADER_PARAM_TYPE_INTEGER, "0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() ) + { + USE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + } + else + { + USE_SOFTWARE_VERTEX_SHADER( myHappyLittleSoftwareVertexShader ); + } + } + SHADER_DRAW + { + SHADOW_STATE + { + } + DYNAMIC_STATE + { + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/debugtangentspace.cpp b/sp/src/materialsystem/stdshaders/debugtangentspace.cpp new file mode 100644 index 00000000..30279012 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugtangentspace.cpp @@ -0,0 +1,133 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +#define USE_NEW_SHADER //Updating assembly shaders to fxc, this is for A/B testing. + +#ifdef USE_NEW_SHADER +#include "debugtangentspace_vs11.inc" +#include "debugtangentspace_vs20.inc" +#include "unlitgeneric_notexture_ps11.inc" +#include "unlitgeneric_notexture_ps20.inc" +#include "unlitgeneric_notexture_ps20b.inc" + +#else +#include "debugtangentspace.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_SHADER( DebugTangentSpace, "Help for DebugTangentSpace" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/basetexture", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( FRAME, SHADER_PARAM_TYPE_INTEGER, "0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + if (g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 0; + int userDataSize = 4; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + DECLARE_STATIC_VERTEX_SHADER( debugtangentspace_vs20 ); + SET_STATIC_VERTEX_SHADER( debugtangentspace_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + } + } + else + { + DECLARE_STATIC_VERTEX_SHADER( debugtangentspace_vs11 ); + SET_STATIC_VERTEX_SHADER( debugtangentspace_vs11 ); + + DECLARE_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + SET_STATIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + } +#else + debugtangentspace_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "DebugTangentSpace", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "UnlitGeneric_NoTexture" ); +#endif + } + DYNAMIC_STATE + { + +#ifdef USE_NEW_SHADER + if( g_pHardwareConfig->GetDXSupportLevel() >= 90 ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps20 ); + } + } + else // legacy hardware + { + DECLARE_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs11 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( debugtangentspace_vs11 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + SET_DYNAMIC_PIXEL_SHADER( unlitgeneric_notexture_ps11 ); + } +#else + debugtangentspace_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); +#endif + } + Draw(); + } + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/debugtangentspace.vsh b/sp/src/materialsystem/stdshaders/debugtangentspace.vsh new file mode 100644 index 00000000..cb38a23b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugtangentspace.vsh @@ -0,0 +1,34 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +&FreeRegister( \$worldPos ); + +; stick the normal in the color channel +mov oD0.xyz, $worldNormal.xyz +mov oD0.w, $cOne ; make sure all components are defined + +&FreeRegister( \$projPos ); +&FreeRegister( \$worldNormal ); diff --git a/sp/src/materialsystem/stdshaders/debugtangentspace_vs11.fxc b/sp/src/materialsystem/stdshaders/debugtangentspace_vs11.fxc new file mode 100644 index 00000000..1584ef26 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugtangentspace_vs11.fxc @@ -0,0 +1,51 @@ +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float3 vNormal : NORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, v.vPos, v.vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // stick the normal in the color channel + o.vDiffuse.rgb = worldNormal; + o.vDiffuse.a = 1.0f; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/debugtangentspace_vs20.fxc b/sp/src/materialsystem/stdshaders/debugtangentspace_vs20.fxc new file mode 100644 index 00000000..f829bde9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/debugtangentspace_vs20.fxc @@ -0,0 +1,55 @@ +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, v.vPos, vObjNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // stick the normal in the color channel + o.vDiffuse.rgb = worldNormal; + o.vDiffuse.a = 1.0f; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc b/sp/src/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc new file mode 100644 index 00000000..61daa238 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/depthtodestalpha_ps20b.fxc @@ -0,0 +1,11 @@ +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float projPosZ : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( float4( 0, 0, 0, 1.0f ), 0.0f, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE, true, i.projPosZ ); +} diff --git a/sp/src/materialsystem/stdshaders/depthtodestalpha_vs20.fxc b/sp/src/materialsystem/stdshaders/depthtodestalpha_vs20.fxc new file mode 100644 index 00000000..9891502e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/depthtodestalpha_vs20.fxc @@ -0,0 +1,23 @@ +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float4 vPos : POSITION; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float projPosZ : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.vProjPos = mul( v.vPos, cModelViewProj ); + o.projPosZ = o.vProjPos.z; + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/depthwrite.cpp b/sp/src/materialsystem/stdshaders/depthwrite.cpp new file mode 100644 index 00000000..06d7690f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/depthwrite.cpp @@ -0,0 +1,207 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "depthwrite_ps20.inc" +#include "depthwrite_ps20b.inc" +#include "depthwrite_vs20.inc" + +#if !defined( _X360 ) +#include "depthwrite_ps30.inc" +#include "depthwrite_vs30.inc" +#endif + +BEGIN_VS_SHADER_FLAGS( DepthWrite, "Help for Depth Write", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "", "Alpha reference value" ) + SHADER_PARAM( COLOR_DEPTH, SHADER_PARAM_TYPE_BOOL, "0", "Write depth as color") + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Wireframe"; + } + return 0; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + bool bAlphaClip = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ); + int nColorDepth = GetIntParam( COLOR_DEPTH, params, 0 ); + + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( nColorDepth == 0 ) + { + // Bias primitives when rendering into shadow map so we get slope-scaled depth bias + // rather than having to apply a constant bias in the filtering shader later + pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_SHADOW_BIAS ); + } + + // Turn off writes to color buffer since we always sample shadows from the DEPTH texture later + // This gives us double-speed fill when rendering INTO the shadow map + pShaderShadow->EnableColorWrites( ( nColorDepth == 1 ) ); + pShaderShadow->EnableAlphaWrites( false ); + + // Don't backface cull unless alpha clipping, since this can cause artifacts when the + // geometry is clipped by the flashlight near plane + // If a material was already marked nocull, don't cull it + pShaderShadow->EnableCulling( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) && !IS_FLAG_SET(MATERIAL_VAR_NOCULL) ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( depthwrite_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ONLY_PROJECT_POSITION, !bAlphaClip && IsX360() && !nColorDepth ); //360 needs to know if it *shouldn't* output texture coordinates to avoid shader patches + SET_STATIC_VERTEX_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_VERTEX_SHADER( depthwrite_vs20 ); + + if ( bAlphaClip || g_pHardwareConfig->PlatformRequiresNonNullPixelShaders() || nColorDepth ) + { + if( bAlphaClip ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps20 ); + } + } + } +#ifndef _X360 + else + { + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( depthwrite_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( ONLY_PROJECT_POSITION, 0 ); //360 only combo, and this is a PC path + SET_STATIC_VERTEX_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_VERTEX_SHADER( depthwrite_vs30 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + DECLARE_STATIC_PIXEL_SHADER( depthwrite_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLOR_DEPTH, nColorDepth ); + SET_STATIC_PIXEL_SHADER( depthwrite_ps30 ); + } +#endif + } + DYNAMIC_STATE + { + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + depthwrite_vs20_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetCOMPRESSED_VERTS( (int)vertexCompression ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if ( bAlphaClip ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float vAlphaThreshold[4] = {0.7f, 0.7f, 0.7f, 0.7f}; + if ( ALPHATESTREFERENCE != -1 && ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) ) + { + vAlphaThreshold[0] = vAlphaThreshold[1] = vAlphaThreshold[2] = vAlphaThreshold[3] = params[ALPHATESTREFERENCE]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vAlphaThreshold, 1 ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps20 ); + } + } +#ifndef _X360 + else // 3.0 shader case (PC only) + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + depthwrite_vs30_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetMORPHING( pShaderAPI->IsHWMorphingEnabled() ); + vshIndex.SetCOMPRESSED_VERTS( (int)vertexCompression ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if ( bAlphaClip ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + float vAlphaThreshold[4] = {0.7f, 0.7f, 0.7f, 0.7f}; + if ( ALPHATESTREFERENCE != -1 && ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) ) + { + vAlphaThreshold[0] = vAlphaThreshold[1] = vAlphaThreshold[2] = vAlphaThreshold[3] = params[ALPHATESTREFERENCE]->GetFloatValue(); + } + + pShaderAPI->SetPixelShaderConstant( 0, vAlphaThreshold, 1 ); + } + + DECLARE_DYNAMIC_PIXEL_SHADER( depthwrite_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( ALPHACLIP, bAlphaClip ); + SET_DYNAMIC_PIXEL_SHADER( depthwrite_ps30 ); + } +#endif + + Vector4D vParms; + + // set up arbitrary far planes, as the real ones are too far ( 30,000 ) +// pShaderAPI->SetPSNearAndFarZ( 1 ); + vParms.x = 7.0f; // arbitrary near + vParms.y = 4000.0f; // arbitrary far + vParms.z = 0.0f; + vParms.w = 0.0f; + pShaderAPI->SetPixelShaderConstant( 1, vParms.Base(), 2 ); + + } // DYNAMIC_STATE + + Draw( ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/depthwrite_ps2x.fxc b/sp/src/materialsystem/stdshaders/depthwrite_ps2x.fxc new file mode 100644 index 00000000..1baabcf3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/depthwrite_ps2x.fxc @@ -0,0 +1,44 @@ +// STATIC: "COLOR_DEPTH" "0..1" + +// DYNAMIC: "ALPHACLIP" "0..1" + +const float g_AlphaThreshold : register( c0 ); + +const float2 g_vNearFarPlanes : register( c1 ); + #define g_flNearPlane g_vNearFarPlanes.x + #define g_flFarPlane g_vNearFarPlanes.y + +struct PS_INPUT +{ +#if ALPHACLIP + float2 texCoord0 : TEXCOORD0; +#endif + +#if COLOR_DEPTH + float4 vWorldPos_projPosZ : TEXCOORD1; +#endif +}; + +sampler BaseTextureSampler : register( s0 ); + +float4 main( PS_INPUT i ) : COLOR +{ + float4 color = float4( 1, 0, 0, 1 ); // opaque alpha....the color doesn't matter for this shader + +#if ALPHACLIP + color = tex2D( BaseTextureSampler, i.texCoord0 ); + + clip( color.a - g_AlphaThreshold ); + +#endif + +#if ( COLOR_DEPTH == 1 ) + + return float4( i.vWorldPos_projPosZ.w / g_flFarPlane, 0.0, 0.0, 1.0 ); + +#else + + return color; + +#endif +} diff --git a/sp/src/materialsystem/stdshaders/depthwrite_vs20.fxc b/sp/src/materialsystem/stdshaders/depthwrite_vs20.fxc new file mode 100644 index 00000000..f98e40e2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/depthwrite_vs20.fxc @@ -0,0 +1,83 @@ +// STATIC: "ONLY_PROJECT_POSITION" "0..1" [XBOX] +// STATIC: "ONLY_PROJECT_POSITION" "0..0" [PC] +// STATIC: "COLOR_DEPTH" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord : TEXCOORD0; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + + // Position delta stream + float3 vPosFlex : POSITION1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + +#if (ONLY_PROJECT_POSITION == 0) //360 sometimes runs without the pixel shader component, but has to patch this output if it does. + float2 texCoord : TEXCOORD0; +#endif + +#if COLOR_DEPTH + float4 vWorldPos_projPosZ : TEXCOORD1; +#endif + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + float3 vWorldPos; + float4 vPosition = v.vPos; + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, float3(0, 0, 0), vPosition.xyz ); +#endif + + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, vWorldPos ); + + float4 vProjPos = mul( float4( vWorldPos, 1.0f ), cViewProj ); + + o.vProjPos = vProjPos; + +#if (ONLY_PROJECT_POSITION == 0) + o.texCoord = v.vTexCoord; +#endif + +#if ( COLOR_DEPTH && !ONLY_PROJECT_POSITION ) + o.vWorldPos_projPosZ.z = vProjPos.z; + o.vWorldPos_projPosZ.w = vProjPos.w; +#endif + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/detail.cpp b/sp/src/materialsystem/stdshaders/detail.cpp new file mode 100644 index 00000000..956bf518 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/detail.cpp @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Detail, "Help for Detail" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_FALLBACK + { + return "UnlitGeneric"; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + } + +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/detail_ps11.psh b/sp/src/materialsystem/stdshaders/detail_ps11.psh new file mode 100644 index 00000000..fb5916ab --- /dev/null +++ b/sp/src/materialsystem/stdshaders/detail_ps11.psh @@ -0,0 +1,12 @@ +ps.1.1 + +tex t0 +tex t1 + +mul r0.rgb, t0, v0 + + +; handle distance fade +sub r0.a, t0.a, 1-v0.a + +sub r0.a, r0.a, t1_bias.a +cnd r0.a, r0.a, c0.a, c1.a diff --git a/sp/src/materialsystem/stdshaders/detail_vs11.vsh b/sp/src/materialsystem/stdshaders/detail_vs11.vsh new file mode 100644 index 00000000..28dee2fd --- /dev/null +++ b/sp/src/materialsystem/stdshaders/detail_vs11.vsh @@ -0,0 +1,56 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +dp4 $worldPos.x, $vPos, $cModel0 +dp4 $worldPos.y, $vPos, $cModel1 +dp4 $worldPos.z, $vPos, $cModel2 +mov $worldPos.w, $cOne + + +;------------------------------------------------------------------------------ +; Transform the position from world to proj space +;------------------------------------------------------------------------------ +&AllocateRegister( \$projPos ); +dp4 $projPos.x, $vPos, $cModelViewProj0 +dp4 $projPos.y, $vPos, $cModelViewProj1 +dp4 $projPos.z, $vPos, $cModelViewProj2 +dp4 $projPos.w, $vPos, $cModelViewProj3 +mov oPos, $projPos + + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); +&FreeRegister( \$worldPos ); + + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ +mov oT0.xy, $vTexCoord0.xy + +; special case perspective correct texture projection so that the texture fits exactly on the screen +mul $projPos.y, $projPos.y, $SHADER_SPECIFIC_CONST_0.w +add $projPos.xy, $projPos.xy, $projPos.w +mul $projPos.xy, $projPos.xy, $cHalf +mul $projPos.xy, $projPos.xy, $SHADER_SPECIFIC_CONST_0.xy +mad $projPos.xy, $projPos.w, $SHADER_SPECIFIC_CONST_1.xy, $projPos.xy + +mov oT1.xy, $projPos.xy +mov oT1.z, $projPos.w +mov oT1.w, $projPos.w + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Modulation color +;------------------------------------------------------------------------------ +mov oD0, $vColor diff --git a/sp/src/materialsystem/stdshaders/eye_refract.cpp b/sp/src/materialsystem/stdshaders/eye_refract.cpp new file mode 100644 index 00000000..87528028 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eye_refract.cpp @@ -0,0 +1,253 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "eye_refract_helper.h" +#include "cloak_blended_pass_helper.h" +#include "emissive_scroll_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( EyeRefract, EyeRefract_dx9 ) +BEGIN_VS_SHADER( EyeRefract_dx9, "Help for Eyes" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( CORNEATEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "cornea texture" ) + SHADER_PARAM( AMBIENTOCCLTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "reflection texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Pupil dilation (0 is none, 1 is maximal)" ) + SHADER_PARAM( GLOSSINESS, SHADER_PARAM_TYPE_FLOAT, "1", "Glossiness of eye (1 is default, 0 is not glossy at all)" ) + SHADER_PARAM( SPHERETEXKILLCOMBO, SHADER_PARAM_TYPE_BOOL, "1", "texkill pixels not on sphere" ) + SHADER_PARAM( RAYTRACESPHERE, SHADER_PARAM_TYPE_BOOL, "1", "Raytrace sphere" ) + SHADER_PARAM( PARALLAXSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Parallax strength" ) + SHADER_PARAM( CORNEABUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1", "Cornea strength" ) + + SHADER_PARAM( AMBIENTOCCLCOLOR, SHADER_PARAM_TYPE_VEC3, "[1 1 1]", "Ambient occlusion color" ) + SHADER_PARAM( EYEBALLRADIUS, SHADER_PARAM_TYPE_FLOAT, "0", "Eyeball radius for ray casting" ) + + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + END_SHADER_PARAMS + + void SetupVarsEyeRefract( Eye_Refract_Vars_t &info ) + { + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nDilation = DILATION; + info.m_nGlossiness = GLOSSINESS; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + info.m_nCorneaTexture = CORNEATEXTURE; + info.m_nAmbientOcclTexture = AMBIENTOCCLTEXTURE; + info.m_nEnvmap = ENVMAP; + info.m_nSphereTexKillCombo = SPHERETEXKILLCOMBO; + info.m_nRaytraceSphere = RAYTRACESPHERE; + info.m_nParallaxStrength = PARALLAXSTRENGTH; + info.m_nCorneaBumpStrength = CORNEABUMPSTRENGTH; + info.m_nAmbientOcclColor = AMBIENTOCCLCOLOR; + info.m_nEyeballRadius = EYEBALLRADIUS; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = IRIS; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + } + + SHADER_INIT_PARAMS() + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + InitParams_Eyes_Refract( this, params, pMaterialName, info ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Eyes_dx8"; + } + + return 0; + } + + SHADER_INIT + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Init_Eyes_Refract( this, params, info ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardEye = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardEye = false; + } + } + + // Standard rendering pass + if ( bDrawStandardEye ) + { + Eye_Refract_Vars_t info; + SetupVarsEyeRefract( info ); + Draw_Eyes_Refract( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/eye_refract_helper.cpp b/sp/src/materialsystem/stdshaders/eye_refract_helper.cpp new file mode 100644 index 00000000..af4d2c08 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eye_refract_helper.cpp @@ -0,0 +1,461 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "eye_refract_helper.h" + +#include "cpp_shader_constant_register_map.h" + +#include "eyes_flashlight_vs11.inc" +#include "eyes_flashlight_ps11.inc" + +#include "eye_refract_vs20.inc" +#include "eye_refract_ps20.inc" +#include "eye_refract_ps20b.inc" + +#ifndef _X360 +#include "eye_refract_vs30.inc" +#include "eye_refract_ps30.inc" +#endif + +#include "convar.h" + +static ConVar r_lightwarpidentity( "r_lightwarpidentity","0", FCVAR_CHEAT ); + +void InitParams_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eye_Refract_Vars_t &info ) +{ + // FLASHLIGHTFIXME + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // Set material parameter default values + if ( ( info.m_nIntro >= 0 ) && ( !params[info.m_nIntro]->IsDefined() ) ) + { + params[info.m_nIntro]->SetIntValue( kDefaultIntro ); + } + + if ( ( info.m_nDilation >= 0 ) && ( !params[info.m_nDilation]->IsDefined() ) ) + { + params[info.m_nDilation]->SetFloatValue( kDefaultDilation ); + } + + if ( ( info.m_nGlossiness >= 0 ) && ( !params[info.m_nGlossiness]->IsDefined() ) ) + { + params[info.m_nGlossiness]->SetFloatValue( kDefaultGlossiness ); + } + + if ( ( info.m_nSphereTexKillCombo >= 0 ) && ( !params[info.m_nSphereTexKillCombo]->IsDefined() ) ) + { + params[info.m_nSphereTexKillCombo]->SetIntValue( kDefaultSphereTexKillCombo ); + } + + if ( ( info.m_nRaytraceSphere >= 0 ) && ( !params[info.m_nRaytraceSphere]->IsDefined() ) ) + { + params[info.m_nRaytraceSphere]->SetIntValue( kDefaultRaytraceSphere ); + } + + if ( ( info.m_nAmbientOcclColor >= 0 ) && ( !params[info.m_nAmbientOcclColor]->IsDefined() ) ) + { + params[info.m_nAmbientOcclColor]->SetVecValue( kDefaultAmbientOcclColor, 4 ); + } + + if ( ( info.m_nEyeballRadius >= 0 ) && ( !params[info.m_nEyeballRadius]->IsDefined() ) ) + { + params[info.m_nEyeballRadius]->SetFloatValue( kDefaultEyeballRadius ); + } + + if ( ( info.m_nParallaxStrength >= 0 ) && ( !params[info.m_nParallaxStrength]->IsDefined() ) ) + { + params[info.m_nParallaxStrength]->SetFloatValue( kDefaultParallaxStrength ); + } + + if ( ( info.m_nCorneaBumpStrength >= 0 ) && ( !params[info.m_nCorneaBumpStrength]->IsDefined() ) ) + { + params[info.m_nCorneaBumpStrength]->SetFloatValue( kDefaultCorneaBumpStrength ); + } +} + +void Init_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, Eye_Refract_Vars_t &info ) +{ + pShader->LoadTexture( info.m_nCorneaTexture ); // SHADER_SAMPLER0 (this is a normal, hence not sRGB) + pShader->LoadTexture( info.m_nIris, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER1 + pShader->LoadCubeMap( info.m_nEnvmap, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER2 + pShader->LoadTexture( info.m_nAmbientOcclTexture, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER3 + + if ( IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture ) ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); // SHADER_SAMPLER4 + } + + pShader->LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); // SHADER_SAMPLER5 +} + +void Draw_Eyes_Refract_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bDrawFlashlightAdditivePass, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bDiffuseWarp = IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture ); + bool bIntro = IS_PARAM_DEFINED( info.m_nIntro ) ? ( params[info.m_nIntro]->GetIntValue() ? true : false ) : false; + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Cornea normal + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Cube reflection + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Ambient occlusion + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( bDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Light warp + } + + int nShadowFilterMode = 0; + if ( bDrawFlashlightAdditivePass == true ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + pShaderShadow->EnableDepthWrites( false ); + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Write over the eyes that were already there + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Flashlight cookie + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eye_refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false ); + bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false ); + + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps20b ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER6 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Noise map + } + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eye_refract_vs30 ); + + bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false ); + bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false ); + + DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eye_refract_ps30 ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Shadow depth map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Noise map + } + } +#endif + + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); // Cube map reflection + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Ambient occlusion + pShaderShadow->EnableSRGBWrite( true ); + + if ( bDrawFlashlightAdditivePass == true ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); // Flashlight cookie + } + + // Fog + if ( bDrawFlashlightAdditivePass == true ) + { + pShader->FogToBlack(); + } + else + { + pShader->FogToFogColor(); + } + } + DYNAMIC_STATE + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture = NULL; + FlashlightState_t flashlightState; + bool bFlashlightShadows = false; + if ( bDrawFlashlightAdditivePass == true ) + { + flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + } + + pShader->BindTexture( SHADER_SAMPLER0, info.m_nCorneaTexture ); // Cornea normal + pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nEnvmap ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nAmbientOcclTexture ); + + if ( bDiffuseWarp ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nDiffuseWarpTexture ); + } + } + + if ( bDrawFlashlightAdditivePass == true ) + pShader->BindTexture( SHADER_SAMPLER5, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + pShader->SetAmbientCubeDynamicStateVertexShader(); + + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV ); + + if ( bDrawFlashlightAdditivePass == true ) + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flashlightState.m_vecLightOrigin.Base(), 1 ); + + LightState_t lightState = { 0, false, false }; + if ( bDrawFlashlightAdditivePass == false ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 ); + } +#endif + + // Get luminance of ambient cube and saturate it + float fAverageAmbient = max(0.0f, min( pShaderAPI->GetAmbientLightCubeLuminance(), 1.0f ) ); + + // Special constant for DX9 eyes: { Dilation, Glossiness, x, x }; + float vPSConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPSConst[0] = IS_PARAM_DEFINED( info.m_nDilation ) ? params[info.m_nDilation]->GetFloatValue() : kDefaultDilation; + vPSConst[1] = IS_PARAM_DEFINED( info.m_nGlossiness ) ? params[info.m_nGlossiness]->GetFloatValue() : kDefaultGlossiness; + vPSConst[2] = fAverageAmbient; + vPSConst[3] = IS_PARAM_DEFINED( info.m_nCorneaBumpStrength ) ? params[info.m_nCorneaBumpStrength]->GetFloatValue() : kDefaultCorneaBumpStrength; + pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + pShaderAPI->SetPixelShaderConstant( 1, IS_PARAM_DEFINED( info.m_nEyeOrigin ) ? params[info.m_nEyeOrigin]->GetVecValue() : kDefaultEyeOrigin, 1 ); + pShaderAPI->SetPixelShaderConstant( 2, IS_PARAM_DEFINED( info.m_nIrisU ) ? params[info.m_nIrisU]->GetVecValue() : kDefaultIrisU, 1 ); + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_nIrisV ) ? params[info.m_nIrisV]->GetVecValue() : kDefaultIrisV, 1 ); + + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 4, vEyePos, 1 ); + pShaderAPI->SetPixelShaderConstant( 5, IS_PARAM_DEFINED( info.m_nAmbientOcclColor ) ? params[info.m_nAmbientOcclColor]->GetVecValue() : kDefaultAmbientOcclColor, 1 ); + + float vPackedConst6[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + //vPackedConst6[0] Unused + vPackedConst6[1] = IS_PARAM_DEFINED( info.m_nEyeballRadius ) ? params[info.m_nEyeballRadius]->GetFloatValue() : kDefaultEyeballRadius; + //vPackedConst6[2] = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? params[info.m_nRaytraceSphere]->GetFloatValue() : kDefaultRaytraceSphere; + vPackedConst6[3] = IS_PARAM_DEFINED( info.m_nParallaxStrength ) ? params[info.m_nParallaxStrength]->GetFloatValue() : kDefaultParallaxStrength; + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 ); + + float fPixelFogType = pShaderAPI->GetPixelFogCombo() == 1 ? 1 : 0; + + // Controls for lerp-style paths through shader code + float vShaderControls[4] = { fPixelFogType, 0, 0, 0 }; + pShaderAPI->SetPixelShaderConstant( 10, vShaderControls, 1 ); + + if ( bDrawFlashlightAdditivePass == true ) + { + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + if ( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER6, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_SHADOW_NOISE_2D ); + } + } + + // Flashlight tax +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b ); + } + else // ps.2.0 + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 ); + } +#endif + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + if ( bDrawFlashlightAdditivePass == true ) + { + float atten[4], pos[4], tweaks[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( 7, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( 8, pos, 1 ); + + //pShaderAPI->SetPixelShaderConstant( 9, worldToTexture.Base(), 4 ); + //10 + //11 + //12 + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture[0], 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, worldToTexture[1], 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, worldToTexture[2], 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, worldToTexture[3], 1 ); + + // Tweaks associated with a given flashlight + tweaks[0] = flashlightState.m_flShadowFilterSize / flashlightState.m_flShadowMapResolution; + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( 9, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + } + else // Lighting constants when not drawing flashlight + { + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + } + + // Intro tax + if ( bIntro ) + { + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + if ( IS_PARAM_DEFINED( info.m_nEntityOrigin ) ) + { + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, timeVec, 1 ); + } + } + pShader->Draw(); +} + + +extern ConVar r_flashlight_version2; +void Draw_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + Draw_Eyes_Refract_Internal( pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + Draw_Eyes_Refract_Internal( pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression ); +} diff --git a/sp/src/materialsystem/stdshaders/eye_refract_helper.h b/sp/src/materialsystem/stdshaders/eye_refract_helper.h new file mode 100644 index 00000000..ce62a33b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eye_refract_helper.h @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef EYE_REFRACT_HELPER_H +#define EYE_REFRACT_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Eye_Refract_Vars_t +{ + Eye_Refract_Vars_t() { memset( this, 0xFF, sizeof(Eye_Refract_Vars_t) ); } + + int m_nFrame; + int m_nIris; + int m_nIrisFrame; + int m_nEyeOrigin; + int m_nIrisU; + int m_nIrisV; + int m_nDilation; + int m_nGlossiness; + int m_nIntro; + int m_nEntityOrigin; // Needed for intro + int m_nWarpParam; + int m_nCorneaTexture; + int m_nAmbientOcclTexture; + int m_nEnvmap; + int m_nSphereTexKillCombo; + int m_nRaytraceSphere; + int m_nParallaxStrength; + int m_nCorneaBumpStrength; + int m_nAmbientOcclColor; + int m_nEyeballRadius; + int m_nDiffuseWarpTexture; +}; + +// Default values (Arrays should only be vec[4]) +static const int kDefaultIntro = 0; +static const float kDefaultEyeOrigin[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultIrisU[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultIrisV[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; +static const float kDefaultDilation = 0.5f; +static const float kDefaultGlossiness = 1.0f; +static const float kDefaultWarpParam = 0.0f; +static const int kDefaultSphereTexKillCombo = 0; +static const int kDefaultRaytraceSphere = 0; +static const float kDefaultParallaxStrength = 0.25f; +static const float kDefaultCorneaBumpStrength = 1.0f; +static const float kDefaultAmbientOcclColor[4] = { 0.33f, 0.33f, 0.33f, 0.0f }; +static const float kDefaultEyeballRadius = 0.5f; + +void InitParams_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eye_Refract_Vars_t &info ); +void Init_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, Eye_Refract_Vars_t &info ); +void Draw_Eyes_Refract( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EYES_DX8_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc b/sp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc new file mode 100644 index 00000000..da053d22 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eye_refract_ps2x.fxc @@ -0,0 +1,494 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =========================== + +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" + +// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps20b] +// STATIC: "SPHERETEXKILLCOMBO" "0..1" [ps30] + +// STATIC: "RAYTRACESPHERE" "0..1" [ps20b] +// STATIC: "RAYTRACESPHERE" "0..1" [ps30] + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] + +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +// We don't use other lights when doing the flashlight +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps30] +// SKIP: ( $RAYTRACESPHERE == 0 ) && ( $SPHERETEXKILLCOMBO == 1 ) [ps20b] + +// Debug 2.0 shader locally +//#ifdef SHADER_MODEL_PS_2_B +//#undef SHADER_MODEL_PS_2_B +//#define SHADER_MODEL_PS_2_0 +//#endif + + +// Includes ======================================================================================= +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +// Texture Samplers =============================================================================== +sampler g_tCorneaSampler : register( s0 ); +sampler g_tIrisSampler : register( s1 ); +sampler g_tEyeReflectionCubemapSampler : register( s2 ); +sampler g_tEyeAmbientOcclSampler : register( s3 ); +sampler g_tLightwarpSampler : register( s4 ); // 1D texture for TF NPR lighting + +sampler g_tFlashlightCookieSampler : register( s5 ); +sampler g_tFlashlightDepthSampler : register( s6 ); +sampler g_tRandomRotationSampler : register( s7 ); + +// Shaders Constants and Globals ================================================================== +const float4 g_vPackedConst0 : register( c0 ); +#define g_flDilationFactor g_vPackedConst0.x +#define g_flGlossiness g_vPackedConst0.y +#define g_flAverageAmbient g_vPackedConst0.z +#define g_flCorneaBumpStrength g_vPackedConst0.w + +const float3 g_vEyeOrigin : register( c1 ); +const float4 g_vIrisProjectionU : register( c2 ); +const float4 g_vIrisProjectionV : register( c3 ); +const float4 g_vCameraPosition : register( c4 ); +const float3 g_cAmbientOcclColor : register( c5 ); + +const float4 g_vPackedConst6 : register( c6 ); +#define g_flEyeballRadius g_vPackedConst6.y //0.51f +//#define g_bRaytraceSphere g_vPackedConst6.z //1.0f +#define g_flParallaxStrength g_vPackedConst6.w //0.25f + +// Flashlight constants +const float4 g_vFlashlightAttenuationFactors : register( c7 ); // FarZ in w +const float3 g_vFlashlightPos : register( c8 ); +const float4 g_vShadowTweaks : register( c9 ); +const float4 g_ShaderControls : register( c10 ); +#define g_fPixelFogType g_ShaderControls.x + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); + +PixelShaderLightInfo g_sLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0; + float4 cVertexLight : TEXCOORD1; // w is used for the flashlight pass + float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass) + float4 vWorldPosition_ProjPosZ : TEXCOORD3; + float3 vWorldNormal : TEXCOORD4; // World-space normal + float3 vWorldTangent : TEXCOORD5; // World-space tangent + float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights + float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights + + float3 vWorldBinormal : COLOR0; // World-space normal +}; + +// Ray sphere intersect returns distance along ray to intersection ================================ +float IntersectRaySphere ( float3 cameraPos, float3 ray, float3 sphereCenter, float sphereRadius) +{ + float3 dst = cameraPos.xyz - sphereCenter.xyz; + float B = dot(dst, ray); + float C = dot(dst, dst) - (sphereRadius * sphereRadius); + float D = B*B - C; + return (D > 0) ? (-B - sqrt(D)) : 0; +} + +// Calculate both types of Fog and lerp to get result +float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float fRangeFog = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + float fHeightFog = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + return lerp( fRangeFog, fHeightFog, fPixelFogType ); +} + +// Blend both types of Fog and lerp to get result +float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType ) +{ + pixelFogFactor = saturate( pixelFogFactor ); + float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + return lerp( fRangeResult, fHeightResult, fPixelFogType ); +} + +float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE ) +{ + float4 result = vShaderColor; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb *= LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb *= GAMMA_LIGHT_SCALE; + } + + result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType ); + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion + + return result; +} + + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Set bools to compile out code + bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + int nNumLights = FLASHLIGHT ? 1 : NUM_LIGHTS; // Flashlight is considered one light, otherwise, use numlights combo + +#if !defined( SHADER_MODEL_PS_2_0 ) + bool bRayCast = RAYTRACESPHERE ? true : false; + bool bRayCastTexKill = SPHERETEXKILLCOMBO ? true : false; +#endif + + float flFlashlightNDotL = i.vTangentViewVector.w; + float4 vFlashlightTexCoord = { 0.0f, 0.0f, 0.0f, 0.0f }; + if ( bFlashlight ) + { + vFlashlightTexCoord.xyzw = i.cVertexLight.xyzw; // This was hidden in this interpolator + i.cVertexLight.rgba = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + } + + // Interpolated vectors + float3 vWorldNormal = i.vWorldNormal.xyz; + float3 vWorldTangent = i.vWorldTangent.xyz; + float3 vWorldBinormal = ( i.vWorldBinormal.xyz * 2.0f ) - 1.0f; // normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) ); + + float3 vTangentViewVector = i.vTangentViewVector.xyz; + + // World position + float3 vWorldPosition = i.vWorldPosition_ProjPosZ.xyz; + + // World view vector to pixel + float3 vWorldViewVector = normalize( vWorldPosition.xyz - g_vCameraPosition.xyz ); + + //=================// + // TF NPR lighting // + //=================// + if ( bDoDiffuseWarp ) + { + // Replace the interpolated vertex light + if ( bFlashlight == true ) + { + // Deal with this below in the flashlight section + } + else + { + if ( nNumLights > 0 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.z ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 1 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine01.w ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 2 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.z ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ) * cWarpedLight.rgb; + } + + if ( nNumLights > 3 ) + { + float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, i.vLightFalloffCosine23.w ).rgb; + i.cVertexLight.rgb += i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ) * cWarpedLight.rgb; + } + } + } + + //==========================================================================================================// + // Ray cast against sphere representing eyeball to reduce artifacts from non-spherical morphed eye geometry // + //==========================================================================================================// +#if !defined( SHADER_MODEL_PS_2_0 ) + if ( bRayCast ) + { + float fSphereRayCastDistance = IntersectRaySphere( g_vCameraPosition.xyz, vWorldViewVector.xyz, g_vEyeOrigin.xyz, g_flEyeballRadius ); + vWorldPosition.xyz = g_vCameraPosition.xyz + ( vWorldViewVector.xyz * fSphereRayCastDistance ); + if (fSphereRayCastDistance == 0) + { + if ( bRayCastTexKill ) + clip(-1); // texkill to get a better silhouette + vWorldPosition.xyz = g_vEyeOrigin.xyz + ( vWorldNormal.xyz * g_flEyeballRadius ); + } + } +#endif + + //=================================// + // Generate sphere and cornea uv's // + //=================================// +#if !defined( SHADER_MODEL_PS_2_0 ) + float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture + vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) ); + vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) ); + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; +#else // ps_20 + float2 vCorneaUv = i.vAmbientOcclUv_fallbackCorneaUv.wz; // Note: Cornea texture is a cropped version of the iris texture + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; +#endif + + //=================================// + // Hacked parallax mapping on iris // + //=================================// + float fIrisOffset = tex2D( g_tCorneaSampler, vCorneaUv.xy ).b; + +#if !defined( SHADER_MODEL_PS_2_0 ) + float2 vParallaxVector = ( ( vTangentViewVector.xy * fIrisOffset * g_flParallaxStrength ) / ( 1.0f - vTangentViewVector.z ) ); // Note: 0.25 is a magic number + vParallaxVector.x = -vParallaxVector.x; //Need to flip x...not sure why. + //vParallaxVector.x *= -1.0; //Need to flip x...not sure why. + //vParallaxVector = 0.0f; //Disable parallax for debugging +#else // Disable parallax effect in 2.0 version + float2 vParallaxVector = { 0.0f, 0.0f }; +#endif + + float2 vIrisUv = vSphereUv.xy - vParallaxVector.xy; + + // Note: We fetch from this texture twice right now with different uv's for the color and alpha + float2 vCorneaNoiseUv = vSphereUv.xy + ( vParallaxVector.xy * 0.5 ); + float fCorneaNoise = tex2D( g_tIrisSampler, vCorneaNoiseUv.xy ).a; + + //===============// + // Cornea normal // + //===============// + // Sample 2D normal from texture + float3 vCorneaTangentNormal = { 0.0, 0.0, 1.0 }; + float4 vCorneaSample = tex2D( g_tCorneaSampler, vCorneaUv.xy ); + vCorneaTangentNormal.xy = vCorneaSample.rg - 0.5f; // Note: This scales the bump to 50% strength + + // Scale strength of normal + vCorneaTangentNormal.xy *= g_flCorneaBumpStrength; + + // Add in surface noise and imperfections (NOTE: This should be baked into the normal map!) + vCorneaTangentNormal.xy += fCorneaNoise * 0.1f; + + // Normalize tangent vector +#if !defined( SHADER_MODEL_PS_2_0 ) + // Since this isn't used later in 2.0, skip the normalize to save shader instructions + vCorneaTangentNormal.xyz = normalize( vCorneaTangentNormal.xyz ); +#endif + + // Transform into world space + float3 vCorneaWorldNormal = Vec3TangentToWorldNormalized( vCorneaTangentNormal.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + //============// + // Flashlight // + //============// + float3 vFlashlightVector = { 0.0f, 0.0f, 0.0f }; + float3 cFlashlightColorFalloff = { 0.0f, 0.0f, 0.0f }; + if ( bFlashlight == true ) + { + // Flashlight vector + vFlashlightVector.xyz = normalize( g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz ); + + // Distance attenuation for flashlight and to fade out shadow over distance + float3 vDelta = g_vFlashlightPos.xyz - i.vWorldPosition_ProjPosZ.xyz; + float flDistSquared = dot( vDelta, vDelta ); + float flDist = sqrt( flDistSquared ); + float flFlashlightAttenuation = dot( g_vFlashlightAttenuationFactors.xyz, float3( 1.0f, 1.0f/flDist, 1.0f/flDistSquared ) ); + + // Flashlight cookie +#if !defined( SHADER_MODEL_PS_2_0 ) + float3 vProjCoords = vFlashlightTexCoord.xyz / vFlashlightTexCoord.w; + float3 cFlashlightCookieColor = tex2D( g_tFlashlightCookieSampler, vProjCoords ); +#else + float3 cFlashlightCookieColor = tex2Dproj( g_tFlashlightCookieSampler, vFlashlightTexCoord.xyzw ); +#endif + + // Shadow depth map +#if FLASHLIGHTSHADOWS && !defined( SHADER_MODEL_PS_2_0 ) + int nShadowLevel = FLASHLIGHTDEPTHFILTERMODE; + float flShadow = DoFlashlightShadow( g_tFlashlightDepthSampler, g_tRandomRotationSampler, vProjCoords, float2(0,0), nShadowLevel, g_vShadowTweaks, false ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = lerp( flAttenuated, flShadow, flFlashlightAttenuation ); // Blend between shadow and above, according to light attenuation + cFlashlightCookieColor *= flShadow; // Apply shadow term to cookie color +#endif + + // Flashlight color intensity (needs to be multiplied by global flashlight color later) + cFlashlightColorFalloff.rgb = flFlashlightAttenuation * cFlashlightCookieColor.rgb; + + // Add this into the interpolated lighting + if ( bDoDiffuseWarp ) + { + //float3 cWarpedLight = 2.0f * tex1D( g_tLightwarpSampler, flFlashlightNDotL ).rgb; + //i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * cWarpedLight.rgb; + i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; // No light warp for now + } + else + { + i.cVertexLight.rgb += cFlashlightColorFalloff.rgb * cFlashlightColor.rgb * flFlashlightNDotL; + } + } + + //==============// + // Dilate pupil // + //==============// +#if !defined( SHADER_MODEL_PS_2_0 ) + vIrisUv.xy -= 0.5f; // Center around (0,0) + float fPupilCenterToBorder = saturate( length( vIrisUv.xy ) / 0.2f ); //Note: 0.2 is the uv radius of the iris + float fPupilDilateFactor = g_flDilationFactor; // This value should be between 0-1 + vIrisUv.xy *= lerp (1.0f, fPupilCenterToBorder, saturate( fPupilDilateFactor ) * 2.5f - 1.25f ); + vIrisUv.xy += 0.5f; +#endif + + //============// + // Iris color // + //============// + float4 cIrisColor = tex2D( g_tIrisSampler, vIrisUv.xy ); + + //==========================// + // Iris lighting highlights // + //==========================// + float3 cIrisLighting = float3( 0.0f, 0.0f, 0.0f ); + +#if !defined( SHADER_MODEL_PS_2_0 ) + // Mask off everything but the iris pixels + float fIrisHighlightMask = tex2D( g_tCorneaSampler, vCorneaUv.xy ).a; + + // Generate the normal + float3 vIrisTangentNormal = vCorneaTangentNormal.xyz; + vIrisTangentNormal.xy *= -2.5f; // I'm not normalizing on purpose + + for ( int j=0; j < nNumLights; j++ ) + { + // World light vector + float3 vWorldLightVector; + if ( ( j == 0 ) && ( bFlashlight == true ) ) + vWorldLightVector = vFlashlightVector.xyz; + else + vWorldLightVector = PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, j ); + + // Tangent light vector + float3 vTangentLightVector = Vec3WorldToTangent( vWorldLightVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Adjust the tangent light vector to generate the iris lighting + float3 tmpv = -vTangentLightVector.xyz; + tmpv.xy *= -0.5f; //Flatten tangent view + tmpv.z = max( tmpv.z, 0.5f ); //Clamp z of tangent view to help maintain highlight + tmpv.xyz = normalize( tmpv.xyz ); + + // Core iris lighting math + float fIrisFacing = pow( abs( dot( vIrisTangentNormal.xyz, tmpv.xyz ) ), 6.0f ) * 0.5f; // Yes, 6.0 and 0.5 are magic numbers + + // Cone of darkness to darken iris highlights when light falls behind eyeball past a certain point + float flConeOfDarkness = pow( 1.0f - saturate( ( -vTangentLightVector.z - 0.25f ) / 0.75f ), 4.0f ); + //float flConeOfDarkness = pow( 1.0f - saturate( ( -dot( vIrisTangentNormal.xyz, vTangentLightVector.xyz ) - 0.15f ) / 0.85f ), 8.0f ); + + // Tint by iris color and cone of darkness + float3 cIrisLightingTmp = fIrisFacing * fIrisHighlightMask * flConeOfDarkness; + + // Attenuate by light color and light falloff + if ( ( j == 0 ) && ( bFlashlight == true ) ) + cIrisLightingTmp.rgb *= cFlashlightColorFalloff.rgb * cFlashlightColor.rgb; + else if ( j == 0 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ); + else if ( j == 1 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ); + else if ( j == 2 ) + cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ); + else + cIrisLightingTmp.rgb *= i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ); + + // Sum into final variable + cIrisLighting.rgb += cIrisLightingTmp.rgb; + } + + // Add slight view dependent iris lighting based on ambient light intensity to enhance situations with no local lights (0.5f is to help keep it subtle) + cIrisLighting.rgb += saturate( dot( vIrisTangentNormal.xyz, -vTangentViewVector.xyz ) ) * g_flAverageAmbient * fIrisHighlightMask * 0.5f; +#else + // Else, intensify light over cornea to simulate the brightening that happens above + cIrisLighting.rgb += i.cVertexLight.rgb * vCorneaSample.a; +#endif + + //===================// + // Ambient occlusion // + //===================// + float3 cAmbientOcclFromTexture = tex2D( g_tEyeAmbientOcclSampler, i.vAmbientOcclUv_fallbackCorneaUv.xy ).rgb; + float3 cAmbientOcclColor = lerp( g_cAmbientOcclColor, 1.0f, cAmbientOcclFromTexture.rgb ); // Color the ambient occlusion + i.cVertexLight.rgb *= cAmbientOcclColor.rgb; + + //==========================// + // Reflection from cube map // + //==========================// + float3 vCorneaReflectionVector = reflect ( vWorldViewVector.xyz, vCorneaWorldNormal.xyz ); + + //float3 cReflection = ENV_MAP_SCALE * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb; + float3 cReflection = g_flGlossiness * texCUBE( g_tEyeReflectionCubemapSampler, vCorneaReflectionVector.xyz ).rgb; + + // Hack: Only add in half of the env map for the flashlight pass. This looks reasonable. + if ( bFlashlight ) + { + cReflection.rgb *= 0.5f; + } + + //===========================// + // Glint specular highlights // + //===========================// + float3 cSpecularHighlights = 0.0f; + if ( bFlashlight ) + { + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, vFlashlightVector.xyz ) ), 128.0f ) * cFlashlightColorFalloff.rgb * cFlashlightColor.rgb; + } + else // no flashlight + { + if ( nNumLights > 0 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 0 ) ) ), 128.0f ) * i.vLightFalloffCosine01.x * PixelShaderGetLightColor( g_sLightInfo, 0 ); + + if ( nNumLights > 1 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 1 ) ) ), 128.0f ) * i.vLightFalloffCosine01.y * PixelShaderGetLightColor( g_sLightInfo, 1 ); + + if ( nNumLights > 2 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 2 ) ) ), 128.0f ) * i.vLightFalloffCosine23.x * PixelShaderGetLightColor( g_sLightInfo, 2 ); + + if ( nNumLights > 3 ) + cSpecularHighlights.rgb += pow( saturate( dot( vCorneaReflectionVector.xyz, PixelShaderGetLightVector( i.vWorldPosition_ProjPosZ.xyz, g_sLightInfo, 3 ) ) ), 128.0f ) * i.vLightFalloffCosine23.y * PixelShaderGetLightColor( g_sLightInfo, 3 ); + } + + //===============// + // Combine terms // + //===============// + float4 result; + + // Unlit iris, pupil, and sclera color + result.rgb = cIrisColor.rgb; + + // Add in slight cornea noise to help define raised cornea layer for close-ups + result.rgb += fCorneaNoise * 0.1f; + + // Diffuse light (Vertex lighting + extra iris caustic lighting) + result.rgb *= i.cVertexLight.rgb + cIrisLighting.rgb; + + // Environment map + result.rgb += cReflection.rgb * i.cVertexLight.rgb; + + // Local light glints + result.rgb += cSpecularHighlights.rgb; + + // Set alpha to 1.0 by default + result.a = 1.0; + +#if !defined( SHADER_MODEL_PS_2_0 ) + float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w ); + return FinalOutputConst( result, fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR ); +#else + float fogFactor = CalcPixelFogFactor( PIXEL_FOG_TYPE_NONE, g_FogParams, g_vCameraPosition.z, i.vWorldPosition_ProjPosZ.z, i.vWorldPosition_ProjPosZ.w ); + return FinalOutput( result, fogFactor, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +#endif + +} diff --git a/sp/src/materialsystem/stdshaders/eye_refract_vs20.fxc b/sp/src/materialsystem/stdshaders/eye_refract_vs20.fxc new file mode 100644 index 00000000..af975f99 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eye_refract_vs20.fxc @@ -0,0 +1,217 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// STATIC: "INTRO" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "vortwarp_vs20_helper.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_iFogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; + +const float3 g_cEyeOrigin : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_vIrisProjectionU : register( SHADER_SPECIFIC_CONST_2 ); +const float4 g_vIrisProjectionV : register( SHADER_SPECIFIC_CONST_3 ); +const float4 g_vFlashlightPosition : register( SHADER_SPECIFIC_CONST_4 ); + +#if INTRO +const float4 g_vConst4 : register( SHADER_SPECIFIC_CONST_5 ); +#define g_vModelOrigin g_vConst4.xyz +#define g_flTime g_vConst4.w +#endif + +const float4 g_vFlashlightMatrixRow1 : register( SHADER_SPECIFIC_CONST_6 ); +const float4 g_vFlashlightMatrixRow2 : register( SHADER_SPECIFIC_CONST_7 ); +const float4 g_vFlashlightMatrixRow3 : register( SHADER_SPECIFIC_CONST_8 ); +const float4 g_vFlashlightMatrixRow4 : register( SHADER_SPECIFIC_CONST_9 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + // Position deltas + float3 vPosFlex : POSITION1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; // Fixed-function fog factor +#endif + float4 vAmbientOcclUv_fallbackCorneaUv : TEXCOORD0; // Base texture coordinate + float4 cVertexLight : TEXCOORD1; // Vertex-lit color (Note: w is used for flashlight pass) + float4 vTangentViewVector : TEXCOORD2; // Tangent view vector (Note: w is used for flashlight pass) + float4 vWorldPosition_ProjPosZ : TEXCOORD3; + float3 vWorldNormal : TEXCOORD4; // World-space normal + float3 vWorldTangent : TEXCOORD5; // World-space tangent + float4 vLightFalloffCosine01 : TEXCOORD6; // Light falloff and cosine terms for first two local lights + float4 vLightFalloffCosine23 : TEXCOORD7; // Light falloff and cosine terms for next two local lights + + float3 vWorldBinormal : COLOR0; // World-space normal +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vPosition = v.vPos; + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, vPosition.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz ); +#endif + + // Transform the position + float3 vWorldPosition; + SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, vWorldPosition ); + + // Note: I'm relying on the iris projection vector math not changing or this will break + float3 vEyeSocketUpVector = normalize( -g_vIrisProjectionV.xyz ); + float3 vEyeSocketLeftVector = normalize( -g_vIrisProjectionU.xyz ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_flTime, g_vModelOrigin, vWorldPosition, dummy, dummy, dummy ); +#endif + + o.vWorldPosition_ProjPosZ.xyz = vWorldPosition.xyz; + + // Transform into projection space + //vWorldPosition -= ( vWorldPosition - g_cEyeOrigin ) * 0.9; //Debug to visualize eye origin + float4 vProjPos = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( vWorldPosition, 1.0f ), cViewProjZ ); + + + o.vWorldPosition_ProjPosZ.w = vProjPos.z; + +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( vWorldPosition, vProjPos, g_iFogType ); +#endif + + // Normal = (Pos - Eye origin) + float3 vWorldNormal = normalize( vWorldPosition.xyz - g_cEyeOrigin.xyz ); + o.vWorldNormal.xyz = vWorldNormal.xyz; + + // Tangent & binormal + /* + float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vEyeSocketLeftVector.xyz ) ); + o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f; + + float3 vWorldTangent = normalize( cross( vWorldBinormal.xyz, vWorldNormal.xyz ) ); + o.vWorldTangent.xyz = vWorldTangent.xyz; + //*/ + + //* + float3 vWorldTangent = normalize( cross( vEyeSocketUpVector.xyz, vWorldNormal.xyz ) ); + o.vWorldTangent.xyz = vWorldTangent.xyz; + + float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) ); + o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f; + //*/ + + float3 vWorldViewVector = normalize (vWorldPosition.xyz - cEyePos.xyz); + o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized (vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz); + + // AV - I think this will effectively make the eyeball less rounded left to right to help vertext lighting quality + // AV - Note: This probably won't look good if put on an exposed eyeball + //float vNormalDotSideVec = -dot( vWorldNormal, g_vEyeballUp ) * 0.5f; + float vNormalDotSideVec = -dot( vWorldNormal, vEyeSocketLeftVector) * 0.5f; + float3 vBentWorldNormal = normalize(vNormalDotSideVec * vEyeSocketLeftVector + vWorldNormal); + + // Compute vertex lighting + o.cVertexLight.a = 0.0f; //Only used for flashlight pass + o.cVertexLight.rgb = DoLightingUnrolled( vWorldPosition, vBentWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, nNumLights ); + + // Only interpolate ambient light for TF NPR lighting + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + if ( bDoDiffuseWarp ) + { + if( bDynamicLight ) + { + o.cVertexLight.rgb = AmbientLight( vBentWorldNormal.xyz ); + } + else + { + o.cVertexLight.rgb = float3( 0.0f, 0.0f, 0.0f ); + } + } + +// NOTE: it appears that o.vLightFalloffCosine01 and o.vLightFalloffCosine23 are filled in even if +// we don't have enough lights, meaning we pass garbage to the pixel shader which then throws it away + + // Light falloff for first two local lights + o.vLightFalloffCosine01.x = VertexAttenInternal( vWorldPosition.xyz, 0 ); + o.vLightFalloffCosine01.y = VertexAttenInternal( vWorldPosition.xyz, 1 ); + o.vLightFalloffCosine01.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 0, g_bHalfLambert ); + o.vLightFalloffCosine01.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 1, g_bHalfLambert ); + + // Light falloff for next two local lights + o.vLightFalloffCosine23.x = VertexAttenInternal( vWorldPosition.xyz, 2 ); + o.vLightFalloffCosine23.y = VertexAttenInternal( vWorldPosition.xyz, 3 ); + o.vLightFalloffCosine23.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 2, g_bHalfLambert ); + o.vLightFalloffCosine23.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 3, g_bHalfLambert ); + + // Texture coordinates set by artists for ambient occlusion + o.vAmbientOcclUv_fallbackCorneaUv.xy = v.vTexCoord0.xy; + + // Cornea uv for ps.2.0 fallback + float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture + vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) ); + vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) ); + float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f; + o.vAmbientOcclUv_fallbackCorneaUv.wz = vCorneaUv.xy; // Note: wz unpacks faster than zw in ps.2.0! + + // Step on the vertex light interpolator for the flashlight tex coords + bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false; + o.vTangentViewVector.w = 0.0f; + if ( bFlashlight ) + { + o.cVertexLight.x = dot( g_vFlashlightMatrixRow1.xyzw, float4( vWorldPosition, 1.0f ) ); + o.cVertexLight.y = dot( g_vFlashlightMatrixRow2.xyzw, float4( vWorldPosition, 1.0f ) ); + o.cVertexLight.z = dot( g_vFlashlightMatrixRow3.xyzw, float4( vWorldPosition, 1.0f ) ); + o.cVertexLight.w = dot( g_vFlashlightMatrixRow4.xyzw, float4( vWorldPosition, 1.0f ) ); + + o.vTangentViewVector.w = saturate( dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ) ); // Flashlight N.L with modified normal + + // Half lambert version + //o.cVertexLight.z = dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ); // Flashlight N.L with modified normal + //o.cVertexLight.z = ( o.cVertexLight.z * 0.5f ) + 0.5f; + //o.cVertexLight.z *= o.cVertexLight.z; + } + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/eyeball.cpp b/sp/src/materialsystem/stdshaders/eyeball.cpp new file mode 100644 index 00000000..7113585d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyeball.cpp @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Eyeball shader +// +//=============================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Eyeball, "Help for EyeBall" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/pupil_l", "iris texture", 0 ) + SHADER_PARAM_OVERRIDE( BASETEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + // This should be a dead shader... + return "Wireframe"; + } + + SHADER_INIT + { + } + + SHADER_DRAW + { + } + +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/eyeglint_dx9.cpp b/sp/src/materialsystem/stdshaders/eyeglint_dx9.cpp new file mode 100644 index 00000000..d2662e6d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyeglint_dx9.cpp @@ -0,0 +1,66 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Run procedural glint generation inner loop in pixel shader +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "shaderlib/cshader.h" + +#include "eyeglint_vs20.inc" +#include "eyeglint_ps20.inc" +#include "eyeglint_ps20b.inc" + +DEFINE_FALLBACK_SHADER( EyeGlint, EyeGlint_dx9 ) +BEGIN_VS_SHADER( EyeGlint_dx9, "Help for EyeGlint" ) + +BEGIN_SHADER_PARAMS +END_SHADER_PARAMS + +SHADER_INIT +{ +} + +SHADER_FALLBACK +{ + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Wireframe"; + } + return 0; +} + +SHADER_DRAW +{ + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Additive blending + + int pTexCoords[3] = { 2, 2, 3 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 3, pTexCoords, 0 ); + + pShaderShadow->EnableCulling( false ); + + pShaderShadow->EnableSRGBWrite( false ); // linear texture + + DECLARE_STATIC_VERTEX_SHADER( eyeglint_vs20 ); + SET_STATIC_VERTEX_SHADER( eyeglint_vs20 ); + + SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( eyeglint ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyeglint_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( eyeglint_vs20 ); + + SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( eyeglint ); + } + Draw(); +} +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/eyeglint_ps2x.fxc b/sp/src/materialsystem/stdshaders/eyeglint_ps2x.fxc new file mode 100644 index 00000000..bc39f079 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyeglint_ps2x.fxc @@ -0,0 +1,32 @@ +// ======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== +// +// Run procedural glint generation inner loop in pixel shader (ps_2_0) +// +// ============================================================================= + +struct PS_INPUT +{ + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +float GlintGaussSpotCoefficient( float2 d ) +{ + return saturate( exp( -25.0f * dot(d, d) ) ); +} + +float4 main( PS_INPUT i ) : COLOR +{ + float2 uv = i.tc - i.glintCenter; // This texel relative to glint center + + float intensity = GlintGaussSpotCoefficient( uv + float2(-0.25f, -0.25f) ) + + GlintGaussSpotCoefficient( uv + float2( 0.25f, -0.25f) ) + + 5 * GlintGaussSpotCoefficient( uv ) + + GlintGaussSpotCoefficient( uv + float2(-0.25f, 0.25f) ) + + GlintGaussSpotCoefficient( uv + float2( 0.25f, 0.25f) ); + + intensity *= 4.0f/9.0f; + + return float4( intensity * i.glintColor, 1.0f ); +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/eyeglint_vs20.fxc b/sp/src/materialsystem/stdshaders/eyeglint_vs20.fxc new file mode 100644 index 00000000..cf1ccb9b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyeglint_vs20.fxc @@ -0,0 +1,38 @@ +//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// +// +// Vertex shader to pass through texcoords needed to run the +// procedural glint generation inner loop in the pixel shader +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "common_vs_fxc.h" + +struct VS_INPUT +{ + float3 vPos : POSITION; + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel in 3x3 quad + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint in local 3x3 quad + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + float2 tc : TEXCOORD0; // Interpolated coordinate of current texel in 3x3 quad + float2 glintCenter : TEXCOORD1; // Uniform value containing center of glint in local 3x3 quad + float3 glintColor : TEXCOORD2; // Uniform value of color of glint +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + o.projPos = float4( v.vPos, 1.0f ); + o.tc = v.tc; + o.glintCenter = v.glintCenter; + o.glintColor = v.glintColor; + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/eyes.cpp b/sp/src/materialsystem/stdshaders/eyes.cpp new file mode 100644 index 00000000..7aa4738f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes.cpp @@ -0,0 +1,186 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: eye renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "eyes_dx8_dx9_helper.h" +#include "cloak_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( eyes, Eyes_dx8 ) + +BEGIN_VS_SHADER( Eyes_dx8, + "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/eyeball_l", "iris texture", 0 ) + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "models/alyx/pupil_l", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "models/humans/male/glint", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Iris dilation" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + END_SHADER_PARAMS + + void SetupVars( Eyes_DX8_DX9_Vars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nGlint = GLINT; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nEyeUp = EYEUP; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nGlintU = GLINTU; + info.m_nGlintV = GLINTV; + info.m_nDilation = DILATION; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + SHADER_INIT_PARAMS() + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitParamsEyes_DX8_DX9( this, params, pMaterialName, info ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "Eyes_dx6"; + + return 0; + } + + SHADER_INIT + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitEyes_DX8_DX9( this, params, info ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + // There is some strangeness in DX8 when trying to skip the main pass, so leave this alone for now + //bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + DrawEyes_DX8_DX9( false, this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/eyes.vsh b/sp/src/materialsystem/stdshaders/eyes.vsh new file mode 100644 index 00000000..58ae021d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes.vsh @@ -0,0 +1,80 @@ +vs.1.1 +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0 = eyeball origin +; $SHADER_SPECIFIC_CONST_1 = eyeball up * 0.5 +; $SHADER_SPECIFIC_CONST_2 = iris projection U +; $SHADER_SPECIFIC_CONST_3 = iris projection V +; $SHADER_SPECIFIC_CONST_4 = glint projection U +; $SHADER_SPECIFIC_CONST_5 = glint projection V +;------------------------------------------------------------------------------ + +# STATIC: "HALF_LAMBERT" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "LIGHT_COMBO" "0..21" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending (whacks r1-r7, positions in r7) +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&SkinPosition( $worldPos ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ + +&AllocateRegister( \$projPos ); + +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Normal is based on vertex position +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$normalDotUp ); + +sub $worldNormal, $worldPos, $SHADER_SPECIFIC_CONST_0 ; Normal = (Pos - Eye origin) +dp3 $normalDotUp, $worldNormal, $SHADER_SPECIFIC_CONST_1 ; Normal -= 0.5f * (Normal dot Eye Up) * Eye Up +mul $normalDotUp, $normalDotUp, $cHalf +mad $worldNormal, -$normalDotUp, $SHADER_SPECIFIC_CONST_1, $worldNormal + +&FreeRegister( \$normalDotUp ); + +; normalize the normal +&Normalize( $worldNormal ); + +;------------------------------------------------------------------------------ +; Lighting +;------------------------------------------------------------------------------ +&DoLighting( $worldPos, $worldNormal ); + +&FreeRegister( \$worldNormal ); + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ + +&CalcFog( $worldPos, $projPos ); + +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Texture coordinates +; Texture 0 is the base texture +; Texture 1 is a planar projection used for the iris +; Texture 2 is a planar projection used for the glint +;------------------------------------------------------------------------------ + +mov oT0, $vTexCoord0 +dp4 oT1.x, $SHADER_SPECIFIC_CONST_2, $worldPos +dp4 oT1.y, $SHADER_SPECIFIC_CONST_3, $worldPos +dp4 oT2.x, $SHADER_SPECIFIC_CONST_4, $worldPos +dp4 oT2.y, $SHADER_SPECIFIC_CONST_5, $worldPos + +&FreeRegister( \$worldPos ); diff --git a/sp/src/materialsystem/stdshaders/eyes_dx6.cpp b/sp/src/materialsystem/stdshaders/eyes_dx6.cpp new file mode 100644 index 00000000..f5454595 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_dx6.cpp @@ -0,0 +1,251 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Teeth renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Eyes, Eyes_dx6 ) + +BEGIN_VS_SHADER( Eyes_dx6, + "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + LoadTexture( IRIS ); + } + + void SetTextureTransform( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + MaterialMatrixMode_t textureTransform, int uparam, int vparam ) + { + Vector4D u, v; + params[uparam]->GetVecValue( u.Base(), 4 ); + params[vparam]->GetVecValue( v.Base(), 4 ); + + // Need to transform these puppies into camera space + // they are defined in world space + VMatrix mat, invTrans; + pShaderAPI->GetMatrix( MATERIAL_VIEW, mat.m[0] ); + mat = mat.Transpose(); + + // Compute the inverse transpose of the matrix + // NOTE: I only have to invert it here because VMatrix is transposed + // with respect to what gets returned from GetMatrix. + mat.InverseGeneral( invTrans ); + invTrans = invTrans.Transpose(); + + // Transform the u and v planes into view space + Vector4D uview, vview; + uview.AsVector3D() = invTrans.VMul3x3( u.AsVector3D() ); + vview.AsVector3D() = invTrans.VMul3x3( v.AsVector3D() ); + uview[3] = u[3] - DotProduct( mat.GetTranslation(), uview.AsVector3D() ); + vview[3] = v[3] - DotProduct( mat.GetTranslation(), vview.AsVector3D() ); + + float m[16]; + m[0] = uview[0]; m[1] = vview[0]; m[2] = 0.0f; m[3] = 0.0f; + m[4] = uview[1]; m[5] = vview[1]; m[6] = 0.0f; m[7] = 0.0f; + m[8] = uview[2]; m[9] = vview[2]; m[10] = 1.0f; m[11] = 0.0f; + m[12] = uview[3]; m[13] = vview[3]; m[14] = 0.0f; m[15] = 1.0f; + + pShaderAPI->MatrixMode( textureTransform ); + pShaderAPI->LoadMatrix( m ); + } + + void DrawFlashlight_Iris( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + + // Alpha blend + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_NORMAL; + pShaderShadow->DrawFlags( flags ); + FogToBlack(); + + pShaderShadow->EnableLighting( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + // alpha stage 0 + // get alpha from constant alpha + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + + // alpha stage 1 + // get alpha from $basetexture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Shove the view position into texcoord 0 before the texture matrix. + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + + // iris transform + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, true ); + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE1, SHADER_TEXGENPARAM_EYE_LINEAR ); + + } + DYNAMIC_STATE + { + SetFlashlightFixedFunctionTextureTransform( MATERIAL_TEXTURE0 ); + + // NOTE: This has to come after the loadmatrix since the loadmatrix screws with the + // transform flags!!!!!! + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 3, true ); + + BindTexture( SHADER_SAMPLER0, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + + BindTexture( SHADER_SAMPLER1, IRIS, IRISFRAME ); + SetTextureTransform( params, pShaderAPI, MATERIAL_TEXTURE1, IRISU, IRISV ); + } + Draw(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // whites + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true ); + + // iris + DrawFlashlight_Iris( params, pShaderAPI, pShaderShadow ); + } + + void DrawUsingSoftwareLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // whites + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + + // iris + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, IRIS, IRISFRAME ); + SetTextureTransform( params, pShaderAPI, MATERIAL_TEXTURE0, IRISU, IRISV ); + } + Draw(); + + // Glint + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, 1.0f ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, GLINT ); + SetTextureTransform( params, pShaderAPI, MATERIAL_TEXTURE0, GLINTU, GLINTV ); + } + Draw( ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawUsingSoftwareLighting( params, pShaderAPI, pShaderShadow ); + } + + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp new file mode 100644 index 00000000..97e6ed32 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.cpp @@ -0,0 +1,550 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "BaseVSShader.h" +#include "tier1/convar.h" +#include "mathlib/vmatrix.h" +#include "eyes_dx8_dx9_helper.h" +#include "cpp_shader_constant_register_map.h" +#include "Eyes.inc" +#include "eyes_flashlight_vs11.inc" +#include "eyes_flashlight_ps11.inc" + +#ifdef STDSHADER_DX9_DLL_EXPORT + +#include "eyes_vs20.inc" +#include "eyes_ps20.inc" +#include "eyes_ps20b.inc" +#include "eyes_flashlight_vs20.inc" +#include "eyes_flashlight_ps20.inc" +#include "eyes_flashlight_ps20b.inc" + +#ifndef _X360 +#include "eyes_vs30.inc" +#include "eyes_ps30.inc" +#include "eyes_flashlight_vs30.inc" +#include "eyes_flashlight_ps30.inc" +#endif + +#endif + +ConVar r_flashlight_version2( "r_flashlight_version2", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ); + +void InitParamsEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Eyes_DX8_DX9_Vars_t &info ) +{ + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + Assert( info.m_nIntro != -1 ); + if( info.m_nIntro != -1 && !params[info.m_nIntro]->IsDefined() ) + { + params[info.m_nIntro]->SetIntValue( 0 ); + } +} + +void InitEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, Eyes_DX8_DX9_Vars_t &info ) +{ + pShader->LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nIris, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nGlint ); + + // Be sure dilation is zeroed if undefined + if( !params[info.m_nDilation]->IsDefined() ) + { + params[info.m_nDilation]->SetFloatValue( 0.0f ); + } +} + +static void SetDepthFlashlightParams( CBaseVSShader *pShader, IShaderDynamicAPI *pShaderAPI, const VMatrix& worldToTexture, const FlashlightState_t& flashlightState ) +{ + float atten[4], pos[4], tweaks[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } +} + + +static void DrawFlashlight( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + if( pShaderShadow ) + { + pShaderShadow->EnableDepthWrites( false ); + + pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Write over the eyes that were already there + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Spot + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Base + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Normalizing cubemap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Iris + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( bDX9 ) + { + int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + } +#endif + + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Spot + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); // Iris + pShaderShadow->EnableSRGBWrite( true ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Shadow noise rotation map + } + } + else +#endif + { + // DX8 uses old asm shaders + eyes_flashlight_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "eyes_flashlight_vs11", vshIndex.GetIndex() ); + + eyes_flashlight_ps11_Static_Index pshIndex; + pShaderShadow->SetPixelShader( "eyes_flashlight_ps11", pshIndex.GetIndex() ); + } + + pShader->FogToBlack(); + } + else + { + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + if ( !bDX9 ) + { + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 0, true ); + } + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + pShader->BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture, info.m_nFrame ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nIris, info.m_nIrisFrame ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( bDX9 ) + { + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_flashlight_vs30 ); + } +#endif + +// float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), 0.0f, 0.0f, 0.0f}; +// pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20b ); + + SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) ); + SET_DYNAMIC_PIXEL_SHADER( eyes_flashlight_ps30 ); + + SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState ); + } +#endif + } + else // older asm shaders for DX8 +#endif + { + eyes_flashlight_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + eyes_flashlight_ps11_Dynamic_Index pshIndex; + pShaderAPI->SetPixelShaderIndex( pshIndex.GetIndex() ); + } + + // This uses from VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 to VERTEX_SHADER_SHADER_SPECIFIC_CONST_5 + pShader->SetFlashlightVertexShaderConstants( false, -1, false, -1, false ); + + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, info.m_nEyeUp ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, info.m_nIrisV ); + } + pShader->Draw(); +} + +static void DrawUsingVertexShader( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Iris + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Glint + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + pShaderShadow->EnableAlphaWrites( true ); //we end up hijacking destination alpha for opaques most of the time. + +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( bDX9 ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( eyes_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[info.m_nIntro]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( eyes_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( eyes_ps20b ); + SET_STATIC_PIXEL_SHADER( eyes_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( eyes_ps20 ); + SET_STATIC_PIXEL_SHADER( eyes_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( eyes_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[info.m_nIntro]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( eyes_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( eyes_ps30 ); + SET_STATIC_PIXEL_SHADER( eyes_ps30 ); + } +#endif + // On DX9, get the gamma read and write correct + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); // Base + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); // White + pShaderShadow->EnableSRGBWrite( true ); + } + else +#endif + { + eyes_Static_Index vshIndex; + vshIndex.SetHALF_LAMBERT( IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + pShaderShadow->SetVertexShader( "Eyes", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "Eyes_Overbright2" ); + } + + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nFrame ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nGlint ); + pShader->SetAmbientCubeDynamicStateVertexShader(); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nEyeUp ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nGlintU ); + pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, info.m_nGlintV ); + +#ifdef STDSHADER_DX9_DLL_EXPORT + if( bDX9 ) + { + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( eyes_vs20 ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( eyes_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( eyes_vs30 ); + } +#endif + + // Get luminance of ambient cube and saturate it + float fGlintDamping = max(0.0f, min( pShaderAPI->GetAmbientLightCubeLuminance(), 1.0f ) ); + const float fDimGlint = 0.01f; + + // Remap so that glint damping smooth steps to zero for low luminances + if ( fGlintDamping > fDimGlint ) + fGlintDamping = 1.0f; + else + fGlintDamping *= SimpleSplineRemapVal( fGlintDamping, 0.0f, fDimGlint, 0.0f, 1.0f ); + + // Special constant for DX9 eyes: { Dilation, ambient, x, x }; + float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), fGlintDamping, 0.0f, 0.0f}; + pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps20 ); + } + } +#ifndef _X360 + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( eyes_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( eyes_ps30 ); + } +#endif + + Assert( info.m_nIntro != -1 ); + if( params[info.m_nIntro]->GetIntValue() ) + { + float curTime = params[info.m_nWarpParam]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[info.m_nEntityOrigin]->IsDefined() ); + params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, timeVec, 1 ); + } + } + else +#endif + { + eyes_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetLIGHT_COMBO( pShaderAPI->GetCurrentLightCombo() ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + pShader->Draw(); +} + +static void DrawEyes_DX8_DX9_Internal( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool bHasFlashlight, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + if( !bHasFlashlight ) + { + DrawUsingVertexShader( bDX9, pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + DrawFlashlight( bDX9, pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +} + +extern ConVar r_flashlight_version2; +void DrawEyes_DX8_DX9( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawEyes_DX8_DX9_Internal( bDX9, pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawEyes_DX8_DX9_Internal( bDX9, pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression ); +} + + diff --git a/sp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.h b/sp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.h new file mode 100644 index 00000000..daf7c124 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_dx8_dx9_helper.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef EYES_DX8_DX9_HELPER_H +#define EYES_DX8_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Eyes_DX8_DX9_Vars_t +{ + Eyes_DX8_DX9_Vars_t() { memset( this, 0xFF, sizeof(Eyes_DX8_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nFrame; + int m_nIris; + int m_nIrisFrame; + int m_nGlint; + int m_nEyeOrigin; + int m_nEyeUp; + int m_nIrisU; + int m_nIrisV; + int m_nGlintU; + int m_nGlintV; + int m_nDilation; + int m_nIntro; + int m_nEntityOrigin; + int m_nWarpParam; +}; + +void InitParamsEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Eyes_DX8_DX9_Vars_t &info ); +void InitEyes_DX8_DX9( CBaseVSShader *pShader, IMaterialVar** params, Eyes_DX8_DX9_Vars_t &info ); +void DrawEyes_DX8_DX9( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // EYES_DX8_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/eyes_dx9.cpp b/sp/src/materialsystem/stdshaders/eyes_dx9.cpp new file mode 100644 index 00000000..b33ec804 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_dx9.cpp @@ -0,0 +1,84 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: eye renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "eyes_dx8_dx9_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( eyes, Eyes_dx9 ) + +BEGIN_VS_SHADER( Eyes_dx9, "Help for Eyes" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( IRIS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "iris texture" ) + SHADER_PARAM( IRISFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame for the iris texture" ) + SHADER_PARAM( GLINT, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "glint texture" ) + SHADER_PARAM( EYEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "origin for the eyes" ) + SHADER_PARAM( EYEUP, SHADER_PARAM_TYPE_VEC3, "[0 0 1]", "up vector for the eyes" ) + SHADER_PARAM( IRISU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0 ]", "U projection vector for the iris" ) + SHADER_PARAM( IRISV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the iris" ) + SHADER_PARAM( GLINTU, SHADER_PARAM_TYPE_VEC4, "[0 1 0 0]", "U projection vector for the glint" ) + SHADER_PARAM( GLINTV, SHADER_PARAM_TYPE_VEC4, "[0 0 1 0]", "V projection vector for the glint" ) + SHADER_PARAM( DILATION, SHADER_PARAM_TYPE_FLOAT, "0", "Pupil dilation (0 is none, 1 is maximal)" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is eyes in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + void SetupVars( Eyes_DX8_DX9_Vars_t &info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nIris = IRIS; + info.m_nIrisFrame = IRISFRAME; + info.m_nGlint = GLINT; + info.m_nEyeOrigin = EYEORIGIN; + info.m_nEyeUp = EYEUP; + info.m_nIrisU = IRISU; + info.m_nIrisV = IRISV; + info.m_nGlintU = GLINTU; + info.m_nGlintV = GLINTV; + info.m_nDilation = DILATION; + info.m_nIntro = INTRO; + info.m_nEntityOrigin = ENTITYORIGIN; + info.m_nWarpParam = WARPPARAM; + } + + SHADER_INIT_PARAMS() + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitParamsEyes_DX8_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "Eyes_dx8"; + + return 0; + } + + SHADER_INIT + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + InitEyes_DX8_DX9( this, params, info ); + } + + + SHADER_DRAW + { + Eyes_DX8_DX9_Vars_t info; + SetupVars( info ); + DrawEyes_DX8_DX9( true, this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/eyes_flashlight2_ps11.psh b/sp/src/materialsystem/stdshaders/eyes_flashlight2_ps11.psh new file mode 100644 index 00000000..3b02fbb3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_flashlight2_ps11.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw stuff +;------------------------------------------------------------------------------ + +tex t0 ; Contains spotlight +tex t1 ; Contains base texture +tex t2 ; Normalize world pos to light +tex t3 ; Sample iris + +dp3 r0, t2_bx2, v0_bx2 ; r0 = N dot L +lrp r1.rgb, t3.a, t3, t1 ; r1 = lerp( baseColor, irisSample.xyz, irisSample.a ) +mul r0.rgb, r0_sat, r1 ; Saturate ( N dot L )* lerp +mul r0.rgb, r0, v0.a ; *= attenuation +mul_x2 r0.rgb, r0, t0 + ; *= 2 * spotlight +mov r0.a, t1.a diff --git a/sp/src/materialsystem/stdshaders/eyes_flashlight_inc.fxc b/sp/src/materialsystem/stdshaders/eyes_flashlight_inc.fxc new file mode 100644 index 00000000..7629f72f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_flashlight_inc.fxc @@ -0,0 +1,92 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + + +const float4 g_vShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +sampler SpotSampler : register( s0 ); +sampler BaseTextureSampler : register( s1 ); +sampler IrisSampler : register( s3 ); + +#if FLASHLIGHTSHADOWS && (!SHADER_MODEL_PS_1_1) && (!SHADER_MODEL_PS_1_4) && (!SHADER_MODEL_PS_2_0) +sampler FlashlightDepthSampler : register( s4 ); +sampler RandomRotationSampler : register( s5 ); +#endif + +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + +#else + const float4 g_FogParams : register( PSREG_FOG_PARAMS ); + const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +#endif + +struct PS_INPUT +{ + float4 spotTexCoord : TEXCOORD0; + float2 baseTexCoord : TEXCOORD1; + float2 irisTexCoord : TEXCOORD3; +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + float3 vertAtten : COLOR0; +#else + float3 vertAtten : TEXCOORD4; + float3 worldPos : TEXCOORD5; + float3 projPos : TEXCOORD7; +#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if defined(SHADER_MODEL_PS_2_0) + float3 spotColor = tex2Dproj( SpotSampler, i.spotTexCoord.xyzw ) * cFlashlightColor; +#elif ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + float3 spotColor = tex2D( SpotSampler, vProjCoords ) * cFlashlightColor; +#else + float3 spotColor = tex2D( SpotSampler, i.spotTexCoord ); +#endif + + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + float4 irisSample = tex2D( IrisSampler, i.irisTexCoord ); + + float3 outcolor = float3(1,1,1); + +#if !defined( SHADER_MODEL_PS_1_1 ) && !defined( SHADER_MODEL_PS_1_4 ) + if( i.spotTexCoord.w <= 0.0f ) + { + outcolor = float3(0,0,0); + } +#endif + + // Composite the iris and sclera together +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + float3 albedo = lerp( baseSample.xyz, irisSample.xyz, irisSample.a ); +#else + float3 albedo = lerp( baseSample.xyz, irisSample.xyz * 0.5f, irisSample.a ); // dim down the iris in HDR +#endif + + // Do shadow depth mapping... +#if FLASHLIGHTSHADOWS && ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos.xy / i.projPos.z, FLASHLIGHTDEPTHFILTERMODE, g_vShadowTweaks, true ); + float flAttenuated = lerp( flShadow, 1.0f, g_vShadowTweaks.y ); // Blend between fully attenuated and not attenuated + flShadow = lerp( flAttenuated, flShadow, dot(i.vertAtten, float3(0.30f, 0.59f, 0.11f) ) ); // Blend between shadow and above, according to light attenuation + outcolor *= flShadow * spotColor * albedo; +#else + outcolor *= spotColor * albedo; +#endif + + // NOTE!! This has to be last to avoid loss of range. + outcolor *= i.vertAtten; +#if defined( SHADER_MODEL_PS_1_1 ) || defined ( SHADER_MODEL_PS_1_4 ) + return float4( outcolor, baseSample.a ); +#else + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos.z, i.projPos.z ); + return FinalOutput( float4( outcolor, 1.0f ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +#endif + +} diff --git a/sp/src/materialsystem/stdshaders/eyes_flashlight_ps11.fxc b/sp/src/materialsystem/stdshaders/eyes_flashlight_ps11.fxc new file mode 100644 index 00000000..25e0702e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_flashlight_ps11.fxc @@ -0,0 +1,9 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#define HDRTYPE HDR_TYPE_NONE + +#include "eyes_flashlight_inc.fxc" diff --git a/sp/src/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc b/sp/src/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc new file mode 100644 index 00000000..eb00fc04 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_flashlight_ps2x.fxc @@ -0,0 +1,15 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +#include "eyes_flashlight_inc.fxc" diff --git a/sp/src/materialsystem/stdshaders/eyes_flashlight_vs11.vsh b/sp/src/materialsystem/stdshaders/eyes_flashlight_vs11.vsh new file mode 100644 index 00000000..48c4cd57 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_flashlight_vs11.vsh @@ -0,0 +1,115 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos ); + +alloc $worldPos +alloc $projPos + + +&SkinPosition( $worldPos ); + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 + +;------------------------------------------------------------------------------ +; Normal is based on vertex position +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$normalDotUp ); + +sub $worldNormal, $worldPos, $SHADER_SPECIFIC_CONST_6 ; Normal = (Pos - Eye origin) +dp3 $normalDotUp, $worldNormal, $SHADER_SPECIFIC_CONST_7 ; Normal -= 0.5f * (Normal dot Eye Up) * Eye Up +mul $normalDotUp, $normalDotUp, $cHalf +mad $worldNormal, -$normalDotUp, $SHADER_SPECIFIC_CONST_7, $worldNormal + +&FreeRegister( \$normalDotUp ); + +; normalize the normal +&Normalize( $worldNormal ); + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +; base tex coords +mov oT1.xy, $vTexCoord0 + +; spotlight texcoords +dp4 oT0.x, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp4 oT0.z, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp4 oT0.w, $worldPos, $SHADER_SPECIFIC_CONST_4 + +local( $worldPosToLightVector, $distFactors ); + +alloc $worldPosToLightVector + +sub $worldPosToLightVector, $SHADER_SPECIFIC_CONST_0.xyz, $worldPos + +local( $distatten ); +alloc $distatten +; $distatten = [ 1, 1/dist, 1/distsquared ] + +; dist squared +dp3 $distatten.z, $worldPosToLightVector, $worldPosToLightVector + +; oodist +rsq $distatten.y, $distatten.z + +mov $distatten.x, $cOne + +local( $dist ); +alloc $dist +mul $dist.x, $distatten.z, $distatten.y + +rcp $distatten.z, $distatten.z ; 1/distsquared + +local( $endFalloffFactor ); +alloc $endFalloffFactor + +; ( dist - farZ ) +sub $endFalloffFactor.x, $dist.x, $SHADER_SPECIFIC_CONST_5.w +; 1 / ( (0.6f * farZ) - farZ) +mul $endFalloffFactor, $endFalloffFactor.x, $SHADER_SPECIFIC_CONST_0.w +max $endFalloffFactor, $endFalloffFactor, $cZero +min $endFalloffFactor, $endFalloffFactor, $cOne + +local( $vertAtten ); +alloc $vertAtten +dp3 $vertAtten, $distatten, $SHADER_SPECIFIC_CONST_5 +mul $vertAtten, $vertAtten, $endFalloffFactor + +; Normalize L +&Normalize( $worldPosToLightVector ); + +; N.L +dp3 $worldNormal, $worldNormal, $worldPosToLightVector + +; Modulate distance attenuation with N.L +mul oD0, $vertAtten, $worldNormal + +; iris +dp4 oT3.x, $SHADER_SPECIFIC_CONST_8, $worldPos +dp4 oT3.y, $SHADER_SPECIFIC_CONST_9, $worldPos + +free $dist +free $endFalloffFactor +free $worldPos +free $worldNormal +free $projPos +free $worldPosToLightVector +free $distatten +free $vertAtten diff --git a/sp/src/materialsystem/stdshaders/eyes_flashlight_vs20.fxc b/sp/src/materialsystem/stdshaders/eyes_flashlight_vs20.fxc new file mode 100644 index 00000000..e2e37dc1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_flashlight_vs20.fxc @@ -0,0 +1,145 @@ +// ------------------------------------------------------------------------------ +// $cLight0Pos = world space light position +// $SHADER_SPECIFIC_CONST_1 = spotlight projection +// $SHADER_SPECIFIC_CONST_2 = spotlight projection +// $SHADER_SPECIFIC_CONST_3 = spotlight projection +// $SHADER_SPECIFIC_CONST_4 = spotlight projection +// $SHADER_SPECIFIC_CONST_5 = far z +// $SHADER_SPECIFIC_CONST_6 = eyeball origin +// $SHADER_SPECIFIC_CONST_7 = eyeball up * 0.5 +// $SHADER_SPECIFIC_CONST_8 = iris projection U +// $SHADER_SPECIFIC_CONST_9 = iris projection V +// ------------------------------------------------------------------------------ + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cLightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cSpotlightProj1 : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cSpotlightProj2 : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cSpotlightProj3 : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cSpotlightProj4 : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cFlashlighAtten : register( SHADER_SPECIFIC_CONST_5 ); // const, linear, quadratic & farZ +const float4 cIrisProjectionU : register( SHADER_SPECIFIC_CONST_8 ); +const float4 cIrisProjectionV : register( SHADER_SPECIFIC_CONST_9 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vNormal : NORMAL; + float4 vTexCoord0 : TEXCOORD0; // Base (sclera) texture coordinates + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; // Fixed-function fog factor +#endif + float4 spotTexCoord : TEXCOORD0; // Spotlight texture coordinates + float2 baseTexCoord : TEXCOORD1; // Base texture coordinates + float2 irisTexCoord : TEXCOORD3; // Iris texture coordinates + float3 vertAtten : TEXCOORD4; // vertex attenuation + float3 worldPos : TEXCOORD5; + float3 projPosXYZ : TEXCOORD7; +}; + + +float RemapValClamped_01( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + worldNormal = normalize( worldNormal ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + o.projPosXYZ = projPos.xyz; + o.worldPos = worldPos.xyz; + +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, o.projPos, g_FogType ); +#endif + + // Base texture coordinates + o.baseTexCoord = v.vTexCoord0; + + // Spotlight texture coordinates + o.spotTexCoord.x = dot( cSpotlightProj1, float4(worldPos, 1) ); + o.spotTexCoord.y = dot( cSpotlightProj2, float4(worldPos, 1) ); + o.spotTexCoord.z = dot( cSpotlightProj3, float4(worldPos, 1) ); + o.spotTexCoord.w = dot( cSpotlightProj4, float4(worldPos, 1) ); + + // Compute vector to light + float3 vWorldPosToLightVector = cLightPosition.xyz - worldPos; + + float3 vDistAtten = float3(1, 1, 1); + vDistAtten.z = dot( vWorldPosToLightVector, vWorldPosToLightVector ); // distsquared + vDistAtten.y = rsqrt( vDistAtten.z ); // 1 / dist + + float flDist = vDistAtten.z * vDistAtten.y; // dist + vDistAtten.z = 1.0f / vDistAtten.z; // 1 / distsquared + + float fFarZ = cFlashlighAtten.w; + + float endFalloffFactor = RemapValClamped_01( flDist, fFarZ, 0.6 * fFarZ ); + o.vertAtten.xyz = endFalloffFactor * dot( vDistAtten, cFlashlighAtten.xyz ); + + o.vertAtten *= dot( normalize( vWorldPosToLightVector ), worldNormal ); + + o.irisTexCoord.x = dot( cIrisProjectionU, float4(worldPos, 1) ); + o.irisTexCoord.y = dot( cIrisProjectionV, float4(worldPos, 1) ); + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/eyes_ps2x.fxc b/sp/src/materialsystem/stdshaders/eyes_ps2x.fxc new file mode 100644 index 00000000..d71d813f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/eyes_ps2x.fxc @@ -0,0 +1,68 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler IrisSampler : register( s1 ); +sampler GlintSampler : register( s2 ); +const float4 cEyeScalars : register( c0 ); // { Dilation, ambient, x, x } + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float2 irisTexCoord : TEXCOORD1; + float2 glintTexCoord : TEXCOORD2; + float3 vertAtten : TEXCOORD3; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +#define fDilationFactor cEyeScalars.x +#define fGlintDamping cEyeScalars.y + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + float4 glintSample = tex2D( GlintSampler, i.glintTexCoord ); +/* + // Dilate the pupil/iris texture (1 is max dilation, 0 is none) + float2 biasedCoords = i.irisTexCoord * 2.0f - 1.0f; // -1 to +1 range + float fDilatability = saturate(0.8f - sqrt(dot(biasedCoords, biasedCoords) )); // 1 in the center, fading out to 0 at 0.8 from center, since irises are inset into maps + float2 scaledCoords = biasedCoords * (1 + fDilatability); // Maximal dilation + + // Blend undilated and maximally dilated based upon dilation factor + float2 dilatedCoords = lerp( scaledCoords, biasedCoords, 1.0f-saturate(cDilationFactor.x)); + dilatedCoords = dilatedCoords * 0.5f + 0.5f; // Back to 0..1 range +*/ + + float4 irisSample = tex2D( IrisSampler, i.irisTexCoord ); // Sample the iris map using dilated coordinates + + float4 result; + result.rgb = lerp( baseSample.rgb, irisSample.rgb, irisSample.a ); + result.rgb *= i.vertAtten; + result.rgb += glintSample.rgb * fGlintDamping; + result.a = baseSample.a; + + bool bWriteDepthToAlpha = false; + + // ps_2_b and beyond +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) + bWriteDepthToAlpha = WRITE_DEPTH_TO_DESTALPHA != 0; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w ); +} diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_helper.cpp b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_helper.cpp new file mode 100644 index 00000000..9b02330a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_helper.cpp @@ -0,0 +1,271 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Flesh Interior Pass + "$FleshInteriorEnabled" "1" // Enables effect + "$FleshInteriorTexture" "models/Alyx/alyx_flesh_color" // Mask in alpha + "$FleshNormalTexture" "models/Alyx/alyx_flesh_normal" + "$FleshBorderTexture1D" "models/Alyx/alyx_flesh_border" + "$FleshInteriorNoiseTexture" "Engine/noise-blur-256x256" + "$FleshSubsurfaceTexture" "models/Alyx/alyx_flesh_subsurface" + "$FleshBorderNoiseScale" "1.5" // Flesh Noise UV scalar for border + "$FleshBorderWidth" "0.3" // Width of flesh border + "$FleshBorderSoftness" "0.42" // Border softness must be greater than 0.0 and up tp 0.5 + "$FleshBorderTint" "[1 1 1]" // Tint / brighten the border 1D texture + "$FleshGlossBrightness" "0.66" // Change the brightness of the glossy layer + "$FleshDebugForceFleshOn" "0" // DEBUG: This will force on full flesh for testing + "$FleshScrollSpeed" "1.0" + "Proxies" + { + "FleshInterior" + { + } + } + + #include "flesh_interior_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + Add this above SHADER_INIT_PARAMS() + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + } + + In SHADER_INIT_PARAMS() + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + + At the very end of SHADER_DRAW + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "convar.h" +#include "flesh_interior_blended_pass_helper.h" + +// Auto generated inc files +#include "flesh_interior_blended_pass_dx8_vs11.inc" + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + SET_PARAM_STRING_IF_NOT_DEFINED( info.m_nFleshCubeTexture, "env_cubemap" ); // Default to in-game env map + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderNoiseScale, kDefaultBorderNoiseScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflDebugForceFleshOn, kDefaultDebugForceFleshOn ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius1, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius2, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius3, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius4, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncSubsurfaceTint, kDefaultSubsurfaceTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderWidth, kDefaultBorderWidth ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderSoftness, kDefaultBorderSoftness ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncBorderTint, kDefaultBorderTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlobalOpacity, kDefaultGlobalOpacity ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlossBrightness, kDefaultGlossBrightness ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflScrollSpeed, kDefaultScrollSpeed ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ) +{ + // Load textures + pShader->LoadTexture( info.m_nFleshTexture ); + //pShader->LoadTexture( info.m_nFleshNoiseTexture ); + //pShader->LoadTexture( info.m_nFleshBorderTexture1D ); + //pShader->LoadTexture( info.m_nFleshNormalTexture ); + //pShader->LoadTexture( info.m_nFleshSubsurfaceTexture ); + //pShader->LoadCubeMap( info.m_nFleshCubeTexture ); +} + +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState(); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + flesh_interior_blended_pass_dx8_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "flesh_interior_blended_pass_dx8_vs11", vshIndex.GetIndex() ); + + // Pixel Shader + pShaderShadow->SetPixelShader( "flesh_interior_blended_pass_dx8_ps11", 0 ); + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + + // Set Vertex Shader Combos + flesh_interior_blended_pass_dx8_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + // Set Vertex Shader Constants + + // Time % 1000 + float flCurrentTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + flCurrentTime *= IS_PARAM_DEFINED( info.m_nflScrollSpeed ) ? params[info.m_nflScrollSpeed]->GetFloatValue() : kDefaultScrollSpeed; // This is a dirty hack, but it works well enough + + float vVsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vVsConst0[0] = flCurrentTime; + vVsConst0[0] -= (float)( (int)( vVsConst0[0] / 1000.0f ) ) * 1000.0f; + + // Flesh effect centers and radii + float vVsConst1[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius1 ) ) + { + params[info.m_nvEffectCenterRadius1]->GetVecValue( vVsConst1, 4 ); + if ( vVsConst1[3] < 0.001f ) + vVsConst1[3] = 0.001f; + vVsConst1[3] = 1.0f / vVsConst1[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vVsConst1, 1 ); + + float vVsConst2[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius2 ) ) + { + params[info.m_nvEffectCenterRadius2]->GetVecValue( vVsConst2, 4 ); + if ( vVsConst2[3] < 0.001f ) + vVsConst2[3] = 0.001f; + vVsConst2[3] = 1.0f / vVsConst2[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vVsConst2, 2 ); + + float vVsConst3[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius3 ) ) + { + params[info.m_nvEffectCenterRadius3]->GetVecValue( vVsConst3, 4 ); + if ( vVsConst3[3] < 0.001f ) + vVsConst3[3] = 0.001f; + vVsConst3[3] = 1.0f / vVsConst3[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vVsConst3, 3 ); + + float vVsConst4[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius4 ) ) + { + params[info.m_nvEffectCenterRadius4]->GetVecValue( vVsConst4, 4 ); + if ( vVsConst4[3] < 0.001f ) + vVsConst4[3] = 0.001f; + vVsConst4[3] = 1.0f / vVsConst4[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, vVsConst4, 4 ); + + // Set Pixel Shader Combos + /* None */ + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nFleshTexture ); + + // Set Pixel Shader Constants + + // Border color tint + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_ncBorderTint ) ? params[info.m_ncBorderTint]->GetVecValue() : kDefaultBorderTint, 1 ); + + // Global opacity + float vPsConst4[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst4[0] = IS_PARAM_DEFINED( info.m_nflGlobalOpacity ) ? params[info.m_nflGlobalOpacity]->GetFloatValue() : kDefaultGlobalOpacity; + pShaderAPI->SetPixelShaderConstant( 4, vPsConst4, 1 ); + + float vPsConst5[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + pShaderAPI->SetPixelShaderConstant( 5, vPsConst5, 1 ); + } + pShader->Draw(); +} diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_ps11.psh b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_ps11.psh new file mode 100644 index 00000000..fc7e32a9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_ps11.psh @@ -0,0 +1,15 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; c5 1, 1, 1, 1 +;------------------------------------------------------------------------------ + +tex t0 ; Base color + +mul r0, v0, v0 ; // Mask^2 +mul r0, r0, r0 ; // Mask^4 +sub r0, c5, r0 ; // 1.0 - Mask^4 + +mul r0.rgb, r0, t0 ; // * Flesh texture color +mul r0.a, r0.a, t0.a ; // * Flesh X-rated mask +mul r0.a, r0.a, v1.a ; // * Fresnel mask diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_vs11.vsh b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_vs11.vsh new file mode 100644 index 00000000..53b6d87d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_dx8_vs11.vsh @@ -0,0 +1,114 @@ +# DYNAMIC: "SKINNING" "0..1" + +vs.1.1 +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; Vertex blending +;------------------------------------------------------------------------------ +&AllocateRegister( \$worldPos ); +&AllocateRegister( \$worldNormal ); +&AllocateRegister( \$projPos ); + +&SkinPositionAndNormal( $worldPos, $worldNormal ); + +if( $SKINNING == 1 ) +{ + &Normalize( $worldNormal ); +} + +;------------------------------------------------------------------------------ +; Transform the position from world to view space +;------------------------------------------------------------------------------ +dp4 $projPos.x, $worldPos, $cViewProj0 +dp4 $projPos.y, $worldPos, $cViewProj1 +dp4 $projPos.z, $worldPos, $cViewProj2 +dp4 $projPos.w, $worldPos, $cViewProj3 + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog - don't bother with water fog for intro effects +;------------------------------------------------------------------------------ +&DepthFog( $projPos, "oFog" ); +&FreeRegister( \$projPos ); + +;------------------------------------------------------------------------------ +; Flesh area +;------------------------------------------------------------------------------ +; // Store the closest effect intensity +; o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius1.xyz ) * g_vEffectCenterOoRadius1.w ); +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius2.xyz ) * g_vEffectCenterOoRadius2.w ); +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius3.xyz ) * g_vEffectCenterOoRadius3.w ); +; o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius4.xyz ) * g_vEffectCenterOoRadius4.w ); + +alloc $tmp1 +alloc $flEffect + +mov $flEffect, $cTwo +mad $flEffect, $flEffect, $cTwo, $cTwo + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_1.w +min $flEffect, $flEffect, $tmp1.w + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_2.w +min $flEffect, $flEffect, $tmp1.w + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_3.w +min $flEffect, $flEffect, $tmp1.w + +sub $tmp1.xyz, $worldPos, $SHADER_SPECIFIC_CONST_4 +dp3 $tmp1.w, $tmp1, $tmp1 +rsq $tmp1.w, $tmp1.w +rcp $tmp1.w, $tmp1.w +mul $tmp1.w, $tmp1.w, $SHADER_SPECIFIC_CONST_4.w +min $flEffect, $flEffect, $tmp1.w + +mov oD0, $flEffect + +; float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); +; o.flDistanceToEffectCenter_flFresnelEffect.y = pow( saturate( dot( -vWorldViewVector.xyz, vWorldNormal.xyz ) ), 1.5f ); + +sub $tmp1, $worldPos, $cEyePos +&Normalize( $tmp1 ); +dp3 $tmp1, -$tmp1, $worldNormal +max $tmp1, $tmp1, $cZero +mul $tmp1, $tmp1, $tmp1 +mov oD1, $tmp1 + +free $tmp1 +free $flEffect + +;------------------------------------------------------------------------------ +; Texture coordinates +;------------------------------------------------------------------------------ + +mov oT0.xy, $vTexCoord0 + +alloc $tmp2 + +dp4 $tmp2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 +dp4 $tmp2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + +add oT1.xy, $tmp2, $SHADER_SPECIFIC_CONST_4 + +free $tmp2 + +; YUCK! This is to make texcoords continuous for mat_softwaretl +mov oT2, $cZero + +&FreeRegister( \$worldPos ); +&FreeRegister( \$worldNormal ); diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp new file mode 100644 index 00000000..03ae509d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.cpp @@ -0,0 +1,355 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +/* Example how to plug this into an existing shader: + + In the VMT: + // Flesh Interior Pass + "$FleshInteriorEnabled" "1" // Enables effect + "$FleshInteriorTexture" "models/Alyx/alyx_flesh_color" // Mask in alpha + "$FleshNormalTexture" "models/Alyx/alyx_flesh_normal" + "$FleshBorderTexture1D" "models/Alyx/alyx_flesh_border" + "$FleshInteriorNoiseTexture" "Engine/noise-blur-256x256" + "$FleshSubsurfaceTexture" "models/Alyx/alyx_flesh_subsurface" + "$FleshBorderNoiseScale" "1.5" // Flesh Noise UV scalar for border + "$FleshBorderWidth" "0.3" // Width of flesh border + "$FleshBorderSoftness" "0.42" // Border softness must be greater than 0.0 and up tp 0.5 + "$FleshBorderTint" "[1 1 1]" // Tint / brighten the border 1D texture + "$FleshGlossBrightness" "0.66" // Change the brightness of the glossy layer + "$FleshDebugForceFleshOn" "0" // DEBUG: This will force on full flesh for testing + "$FleshScrollSpeed" "1.0" + "Proxies" + { + "FleshInterior" + { + } + } + + #include "flesh_interior_blended_pass_helper.h" + + In BEGIN_SHADER_PARAMS: + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + Add this above SHADER_INIT_PARAMS() + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + } + + In SHADER_INIT_PARAMS() + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + In SHADER_INIT + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + + At the very end of SHADER_DRAW + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + +==================================================================================================== */ + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "convar.h" +#include "flesh_interior_blended_pass_helper.h" + +// Auto generated inc files +#include "flesh_interior_blended_pass_vs20.inc" +#include "flesh_interior_blended_pass_ps20.inc" +#include "flesh_interior_blended_pass_ps20b.inc" + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + SET_PARAM_STRING_IF_NOT_DEFINED( info.m_nFleshCubeTexture, "env_cubemap" ); // Default to in-game env map + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderNoiseScale, kDefaultBorderNoiseScale ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflDebugForceFleshOn, kDefaultDebugForceFleshOn ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius1, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius2, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius3, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_nvEffectCenterRadius4, kDefaultEffectCenterRadius, 4 ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncSubsurfaceTint, kDefaultSubsurfaceTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderWidth, kDefaultBorderWidth ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflBorderSoftness, kDefaultBorderSoftness ); + SET_PARAM_VEC_IF_NOT_DEFINED( info.m_ncBorderTint, kDefaultBorderTint, 4 ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlobalOpacity, kDefaultGlobalOpacity ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflGlossBrightness, kDefaultGlossBrightness ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nflScrollSpeed, kDefaultScrollSpeed ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); +} + +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ) +{ + // Load textures + pShader->LoadTexture( info.m_nFleshTexture, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nFleshNoiseTexture ); + pShader->LoadTexture( info.m_nFleshBorderTexture1D, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nFleshNormalTexture ); + pShader->LoadTexture( info.m_nFleshSubsurfaceTexture, TEXTUREFLAGS_SRGB ); + pShader->LoadCubeMap( info.m_nFleshCubeTexture, TEXTUREFLAGS_SRGB ); +} + +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Reset shadow state manually since we're drawing from two materials + pShader->SetInitialShadowState(); + + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + SET_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + SET_STATIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); // Noise texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); // Normal texture not sRGB + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + } + DYNAMIC_STATE + { + // Reset render state manually since we're drawing from two materials + pShaderAPI->SetDefaultState(); + + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + // Set Vertex Shader Combos + LightState_t lightState = { 0, false, false }; + pShaderAPI->GetDX9LightState( &lightState ); + DECLARE_DYNAMIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( flesh_interior_blended_pass_vs20 ); + + // Set Vertex Shader Constants + pShader->SetAmbientCubeDynamicStateVertexShader(); + + // Time % 1000 + float flCurrentTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + flCurrentTime *= IS_PARAM_DEFINED( info.m_nflScrollSpeed ) ? params[info.m_nflScrollSpeed]->GetFloatValue() : kDefaultScrollSpeed; // This is a dirty hack, but it works well enough + + float vVsConst0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vVsConst0[0] = flCurrentTime; + vVsConst0[0] -= (float)( (int)( vVsConst0[0] / 1000.0f ) ) * 1000.0f; + + // Noise UV scroll + vVsConst0[1] = flCurrentTime / 100.0f; + vVsConst0[1] -= (float)( (int)( vVsConst0[1] ) ); + + // Border noise scale + vVsConst0[2] = IS_PARAM_DEFINED( info.m_nflBorderNoiseScale ) ? params[info.m_nflBorderNoiseScale]->GetFloatValue() : kDefaultBorderNoiseScale; + + // Debug force flesh on + vVsConst0[3] = IS_PARAM_DEFINED( info.m_nflDebugForceFleshOn ) ? params[info.m_nflDebugForceFleshOn]->GetFloatValue() : kDefaultDebugForceFleshOn; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vVsConst0, 1 ); + + // Flesh effect centers and radii + float vVsConst1[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius1 ) ) + { + params[info.m_nvEffectCenterRadius1]->GetVecValue( vVsConst1, 4 ); + if ( vVsConst1[3] < 0.001f ) + vVsConst1[3] = 0.001f; + vVsConst1[3] = 1.0f / vVsConst1[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vVsConst1, 1 ); + + float vVsConst2[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius2 ) ) + { + params[info.m_nvEffectCenterRadius2]->GetVecValue( vVsConst2, 4 ); + if ( vVsConst2[3] < 0.001f ) + vVsConst2[3] = 0.001f; + vVsConst2[3] = 1.0f / vVsConst2[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, vVsConst2, 2 ); + + float vVsConst3[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius3 ) ) + { + params[info.m_nvEffectCenterRadius3]->GetVecValue( vVsConst3, 4 ); + if ( vVsConst3[3] < 0.001f ) + vVsConst3[3] = 0.001f; + vVsConst3[3] = 1.0f / vVsConst3[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vVsConst3, 3 ); + + float vVsConst4[4] = { kDefaultEffectCenterRadius[0], kDefaultEffectCenterRadius[1], kDefaultEffectCenterRadius[2], kDefaultEffectCenterRadius[3] }; + if ( IS_PARAM_DEFINED( info.m_nvEffectCenterRadius4 ) ) + { + params[info.m_nvEffectCenterRadius4]->GetVecValue( vVsConst4, 4 ); + if ( vVsConst4[3] < 0.001f ) + vVsConst4[3] = 0.001f; + vVsConst4[3] = 1.0f / vVsConst4[3]; // Pass 1.0/radius so we do a mul instead of a divide in the shader + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, vVsConst4, 4 ); + + // Set Pixel Shader Combos + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( flesh_interior_blended_pass_ps20 ); + } + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nFleshTexture ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nFleshNoiseTexture ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nFleshBorderTexture1D ); + pShader->BindTexture( SHADER_SAMPLER3, info.m_nFleshNormalTexture ); + pShader->BindTexture( SHADER_SAMPLER4, info.m_nFleshSubsurfaceTexture ); + pShader->BindTexture( SHADER_SAMPLER5, info.m_nFleshCubeTexture ); + + // Set Pixel Shader Constants + + // Subsurface tint + pShaderAPI->SetPixelShaderConstant( 0, IS_PARAM_DEFINED( info.m_ncSubsurfaceTint ) ? params[info.m_ncSubsurfaceTint]->GetVecValue() : kDefaultSubsurfaceTint, 1 ); + + // Border width + float vPsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst1[0] = IS_PARAM_DEFINED( info.m_nflBorderWidth ) ? params[info.m_nflBorderWidth]->GetFloatValue() : kDefaultBorderWidth; + vPsConst1[0] = 1.0f / vPsConst1[0]; // ( 1.0f / g_flBorderWidthFromVmt ) + vPsConst1[1] = vPsConst1[0] - 1.0f; // ( 1.0f / g_flBorderWidthFromVmt ) - 1.0f + pShaderAPI->SetPixelShaderConstant( 1, vPsConst1, 1 ); + + // Border softness + float vPsConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst2[0] = IS_PARAM_DEFINED( info.m_nflBorderSoftness ) ? params[info.m_nflBorderSoftness]->GetFloatValue() : kDefaultBorderSoftness; + if ( vPsConst2[0] < 0.01f ) + vPsConst2[0] = 0.01f; + else if ( vPsConst2[0] > 0.5f ) + vPsConst2[0] = 0.5f; + pShaderAPI->SetPixelShaderConstant( 2, vPsConst2, 1 ); + + // Border color tint + pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_ncBorderTint ) ? params[info.m_ncBorderTint]->GetVecValue() : kDefaultBorderTint, 1 ); + + // Global opacity + float vPsConst4[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst4[0] = IS_PARAM_DEFINED( info.m_nflGlobalOpacity ) ? params[info.m_nflGlobalOpacity]->GetFloatValue() : kDefaultGlobalOpacity; + pShaderAPI->SetPixelShaderConstant( 4, vPsConst4, 1 ); + + // Gloss brightness + float vPsConst5[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPsConst5[0] = IS_PARAM_DEFINED( info.m_nflGlossBrightness ) ? params[info.m_nflGlossBrightness]->GetFloatValue() : kDefaultGlossBrightness; + pShaderAPI->SetPixelShaderConstant( 5, vPsConst5, 1 ); + } + pShader->Draw(); +} diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h new file mode 100644 index 00000000..92b8d57a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_helper.h @@ -0,0 +1,68 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef FLESH_INTERIOR_BLENDED_PASS_HELPER_H +#define FLESH_INTERIOR_BLENDED_PASS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct FleshInteriorBlendedPassVars_t +{ + FleshInteriorBlendedPassVars_t() { memset( this, 0xFF, sizeof(FleshInteriorBlendedPassVars_t) ); } + + int m_nFleshTexture; + int m_nFleshNoiseTexture; + int m_nFleshBorderTexture1D; + int m_nFleshNormalTexture; + int m_nFleshSubsurfaceTexture; + int m_nFleshCubeTexture; + + int m_nflBorderNoiseScale; + int m_nflDebugForceFleshOn; + int m_nvEffectCenterRadius1; + int m_nvEffectCenterRadius2; + int m_nvEffectCenterRadius3; + int m_nvEffectCenterRadius4; + + int m_ncSubsurfaceTint; + int m_nflBorderWidth; + int m_nflBorderSoftness; // > 0.0f && < 0.5f ! + int m_ncBorderTint; + int m_nflGlobalOpacity; + int m_nflGlossBrightness; + int m_nflScrollSpeed; + + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultBorderNoiseScale = 1.5f; +static const float kDefaultDebugForceFleshOn = 0.0f; +static const float kDefaultEffectCenterRadius[4] = { 0.0f, 0.0f, 0.0f, 0.0001f }; // Disabled by default +static const float kDefaultSubsurfaceTint[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Disabled by default +static const float kDefaultBorderWidth = 0.3f; +static const float kDefaultBorderSoftness = 0.42f; // > 0.0f && < 0.5f ! +static const float kDefaultBorderTint[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; +static const float kDefaultGlobalOpacity = 1.0f; +static const float kDefaultGlossBrightness = 0.66f; +static const float kDefaultScrollSpeed = 1.0f; + +void InitParamsFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, FleshInteriorBlendedPassVars_t &info ); +void InitFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, FleshInteriorBlendedPassVars_t &info ); +void DrawFleshInteriorBlendedPass( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, FleshInteriorBlendedPassVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // FLESH_INTERIOR_BLENDED_PASS_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc new file mode 100644 index 00000000..3e288e56 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_ps2x.fxc @@ -0,0 +1,127 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// +// Includes ======================================================================================= +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tBaseSampler : register( s0 ); +sampler g_tNoiseSampler : register( s1 ); +sampler g_tBorder1DSampler : register( s2 ); +sampler g_tNormalSampler : register( s3 ); +sampler g_tSubsurfaceSampler: register( s4 ); +sampler g_tCubeSampler : register( s5 ); + +// Shaders Constants and Globals ================================================================== +const float3 g_cSubsurfaceTint : register( c0 ); +const float2 g_flBorderWidth : register( c1 ); //{ 1.0f / g_flBorderWidthFromVmt, ( 1.0f / g_flBorderWidthFromVmt ) - 1.0f }; +const float g_flBorderSoftness : register( c2 ); +const float3 g_cBorderTint : register( c3 ); +const float g_flGlobalOpacity : register( c4 ); +const float g_flGlossBrightness : register( c5 ); + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float2 vTexCoord0 : TEXCOORD0; + float2 flDistanceToEffectCenter_flFresnelEffect : TEXCOORD1; + float4 vNoiseTexCoord : TEXCOORD2; + float3 vTangentViewVector : TEXCOORD3; + float3 cVertexLight : TEXCOORD4; + float3x3 mTangentSpaceTranspose : TEXCOORD5; + // second row : TEXCOORD6; + // third row : TEXCOORD7; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + // Color texture + float4 cBaseColor = tex2D( g_tBaseSampler, i.vTexCoord0.xy ); + float flFleshMaskFromTexture = cBaseColor.a; + + // Subsurface colors + float4 cSubsurfaceColor = tex2D( g_tSubsurfaceSampler, i.vTexCoord0.xy ); + cBaseColor.rgb += cBaseColor.rgb * cSubsurfaceColor.rgb * g_cSubsurfaceTint.rgb; + + // Scroll noise textures to ripple border of opening + float flNoise0 = tex2D( g_tNoiseSampler, i.vNoiseTexCoord.xy ).g; // Use green so we can DXT1 if we want + float flNoise1 = tex2D( g_tNoiseSampler, i.vNoiseTexCoord.wz ).g; // Use green so we can DXT1 if we want + float flNoise = ( flNoise0 + flNoise1 ) * 0.5f; + + // Generate 0-1 mask from distance computed in the VS + float flClampedInputMask = 0.0f; + flClampedInputMask = 1.0f - saturate( i.flDistanceToEffectCenter_flFresnelEffect.x ); + flClampedInputMask *= i.flDistanceToEffectCenter_flFresnelEffect.y; + flClampedInputMask *= flFleshMaskFromTexture; + + // Noise mask - Only apply noise around border of sphere + float flBorderMask = saturate( ( 1.0f - flClampedInputMask ) * g_flBorderWidth.x - g_flBorderWidth.y ); + float flNoiseMask = 1.0f - abs( ( flBorderMask * 2.0f ) - 1.0f ); + + // This is used to lerp in the 1D border texture over the flesh color + float flBorderMaskWithNoise = ( 1.0f - smoothstep( flNoiseMask - g_flBorderSoftness, flNoiseMask + g_flBorderSoftness, flNoise.r ) ) * flNoiseMask; + + // Border color + float vBorderUv = ( sign( flBorderMask - 0.5 ) * (1.0f - pow( flBorderMaskWithNoise, 4.0f )) * 0.5f ) + 0.5f; + float4 cBorderColor = 2.0f * tex2D( g_tBorder1DSampler, vBorderUv ); + cBorderColor.rgb *= g_cBorderTint; + cBorderColor.rgb *= flNoise; + + // Normal map + float4 vNormalMapValue = tex2D( g_tNormalSampler, i.vTexCoord0.xy ); + float3 vTangentNormal = ( vNormalMapValue.xyz * 2.0f ) - 1.0f; + vTangentNormal.xy += ( flNoise * 1.5f ) - 0.75f; // NOTE: This will denormalize the normal. + //float3 vWorldNormal = mul( i.mTangentSpaceTranspose, vTangentNormal.xyz ); + + // Specular gloss layer + float3 vTangentReflectionVector = reflect( i.vTangentViewVector.xyz, vTangentNormal.xyz ); + //vTangentReflectionVector.xy += ( flNoise * 1.5f ) - 0.75f; + float3 vWorldReflectionVector = mul( i.mTangentSpaceTranspose, vTangentReflectionVector.xyz ); + float3 cGlossLayer = ENV_MAP_SCALE * texCUBE( g_tCubeSampler, vWorldReflectionVector.xyz ).rgb; + cGlossLayer.rgb *= g_flGlossBrightness; + + // Gloss mask is just hard-coded fresnel for now + float flGlossMask = pow( saturate( dot( vTangentNormal.xyz, -i.vTangentViewVector.xyz ) ), 8.0f ); + + // Opacity + float flOpacity = 1.0f; + flOpacity = max( flBorderMaskWithNoise, step( flBorderMask, 0.5f ) ); + + // Apply global opacity + flOpacity *= g_flGlobalOpacity; + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = cBaseColor.rgb * i.cVertexLight.rgb; + result.rgb += cGlossLayer.rgb * flGlossMask; + result.rgb *= pow( 1.0f - flBorderMaskWithNoise, 2.0f ); // Darken near border + result.rgb = lerp( result.rgb, cBorderColor.rgb, saturate( vBorderUv * 2.0f ) ); // bring in transition 1D texture + + //result.rgb = flClampedInputMask; + //result.rgb = flBorderMask; + //result.rgb = saturate( flClampedInputMask * 2.0f ); + //result.rgb = i.flDistanceToEffectCenter_flFresnelEffect.x;// * i.flDistanceToEffectCenter_flFresnelEffect.y; + //result.rgb = i.flDistanceToEffectCenter_flFresnelEffect.y * g_flBorderWidth.x - g_flBorderWidth.y; + //result.rgb = flNoiseMask; + //result.rgb = flBorderMaskWithNoise; + //result.rgb = flOpacity; + //result.rgb = flBorderUv; + //result.rgb = cBorderColor; + //result.rgb = -i.vTangentViewVector.z; + //result.rgb = vNormalMapValue.xyz; + //result.rgb = vTangentNormal.xyz; + //result.rgb = flGlossLayer; + //result.rgb = i.cVertexLight.rgb; + //result.rgb = texCUBE( g_tCubeSampler, vTangentNormal.xyz ).rgb; + //result.rgb = i.vTangentViewVector.x; + //result.rgb = cGlossLayer.rgb; + + // Set alpha for blending + result.a = flOpacity; + //result.a = 1.0f; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} diff --git a/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc new file mode 100644 index 00000000..2a361b01 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/flesh_interior_blended_pass_vs20.fxc @@ -0,0 +1,155 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const int g_iFogType = DOWATERFOG; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 g_vConst0 : register( SHADER_SPECIFIC_CONST_0 ); +#define g_flTime g_vConst0.x +#define g_flNoiseUvScroll g_vConst0.y +#define g_flBorderNoiseScale g_vConst0.z +#define g_flDebugForceFleshOn g_vConst0.w + +const float4 g_vEffectCenterOoRadius1 : register( SHADER_SPECIFIC_CONST_1 ); //= { -295.0f, -5.0f, 40.0f, 1.0f/20.0f }; +const float4 g_vEffectCenterOoRadius2 : register( SHADER_SPECIFIC_CONST_2 ); //= { -295.0f, 15.0f, 40.0f, 1.0f/10.0f }; +const float4 g_vEffectCenterOoRadius3 : register( SHADER_SPECIFIC_CONST_3 ); //= { -295.0f, 35.0f, 40.0f, 1.0f/10.0f }; +const float4 g_vEffectCenterOoRadius4 : register( SHADER_SPECIFIC_CONST_4 ); //= { -295.0f, 55.0f, 40.0f, 1.0f/10.0f }; + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float3 vPosFlex : POSITION1; // Delta positions for flexing + float4 vTangent : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float2 vTexCoord0 : TEXCOORD0; + float2 flDistanceToEffectCenter_flFresnelEffect : TEXCOORD1; + float4 vNoiseTexCoord : TEXCOORD2; + float3 vTangentViewVector : TEXCOORD3; + float3 cVertexLight : TEXCOORD4; + float3x3 mTangentSpaceTranspose : TEXCOORD5; + // second row : TEXCOORD6; + // third row : TEXCOORD7; + +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Flexes coming in from a separate stream (contribution masked by cFlexScale.x) + float4 vObjPosition = i.vPos; + vObjPosition.xyz += i.vPosFlex.xyz * cFlexScale.x; + + float3 vObjNormal; + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vTangent, vObjNormal, vObjTangent ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal, vObjTangent, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // Pass through tex coords + o.vTexCoord0.xy = i.vTexCoord0.xy; + + // Store the closest effect intensity + o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius1.xyz ) * g_vEffectCenterOoRadius1.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius2.xyz ) * g_vEffectCenterOoRadius2.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius3.xyz ) * g_vEffectCenterOoRadius3.w ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - g_vEffectCenterOoRadius4.xyz ) * g_vEffectCenterOoRadius4.w ); + + /* + // Test values for development in Alyx_interior map + o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + float3 vTestPosition = { -295.0f, -5.0f, 40.0f }; + float flMinY = -5.0f; + float flMaxY = 66.0f; + vTestPosition.y = lerp( flMinY, flMaxY, ( abs( frac( g_flTime / 20.0f ) * 2.0 - 1.0 ) ) ); + //vTestPosition.y = lerp( flMinY, flMaxY, 0.65f ); + + //1.0f - saturate( i.flDistanceToEffectCenter_flFresnelEffect.x * 4.0f - 3.0f ) + + //o.flDistanceToEffectCenter_flFresnelEffect.x = 9999.0f; // A very large distance + + const float g_flInteriorRadius = 20.0f; + if ( g_flInteriorRadius ) + { + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - vTestPosition.xyz ) / g_flInteriorRadius ); + } + + const float g_flInteriorRadius2 = 14.0f; + if ( g_flInteriorRadius2 ) + { + vTestPosition.y = lerp( flMinY, flMaxY, 0.65f ); + //vTestPosition.z = lerp( 37, 45, ( abs( frac( g_flTime / 4.0f ) * 2.0 - 1.0 ) ) ); + o.flDistanceToEffectCenter_flFresnelEffect.x = min( o.flDistanceToEffectCenter_flFresnelEffect.x, length( vWorldPosition.xyz - vTestPosition.xyz ) / g_flInteriorRadius2 ); + } + //*/ + + if ( g_flDebugForceFleshOn ) + { + o.flDistanceToEffectCenter_flFresnelEffect.x = 0.0f; + } + + // Fresnel mask + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + o.flDistanceToEffectCenter_flFresnelEffect.y = pow( saturate( dot( -vWorldViewVector.xyz, vWorldNormal.xyz ) ), 1.5f ); + + // Noise UV + o.vNoiseTexCoord.xy = o.vTexCoord0.xy * g_flBorderNoiseScale + g_flNoiseUvScroll; + o.vNoiseTexCoord.zw = o.vTexCoord0.xy * g_flBorderNoiseScale - g_flNoiseUvScroll; // Will fetch as wz to avoid matching layers + + // Tangent view vector + o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized( vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Compute vertex lighting + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + +#if ( USE_STATIC_CONTROL_FLOW ) || defined ( SHADER_MODEL_VS_3_0 ) + o.cVertexLight.rgb = DoLighting( vWorldPosition, vWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert ); +#else + o.cVertexLight.rgb = DoLightingUnrolled( vWorldPosition, vWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); +#endif + + // Tangent space transform + o.mTangentSpaceTranspose[0] = float3( vWorldTangent.x, vWorldBinormal.x, vWorldNormal.x ); + o.mTangentSpaceTranspose[1] = float3( vWorldTangent.y, vWorldBinormal.y, vWorldNormal.y ); + o.mTangentSpaceTranspose[2] = float3( vWorldTangent.z, vWorldBinormal.z, vWorldNormal.z ); + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_basealphamaskedenvmap.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_basealphamaskedenvmap.psh new file mode 100644 index 00000000..fbb4393f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_basealphamaskedenvmap.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r1, t2, 1-t3.a ; envmap * envmapmask alpha +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_basetextureblend.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_basetextureblend.psh new file mode 100644 index 00000000..9380ec63 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_basetextureblend.psh @@ -0,0 +1,9 @@ +ps.1.1 + +tex t0 ; base 1 +tex t1 ; base 2 + +mov r1, t1 +lrp r0, 1-v0.a, t0, r1 +mul r0, r0, c0 + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal.cpp new file mode 100644 index 00000000..9e74b5cf --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal.cpp @@ -0,0 +1,135 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "lightmappedgeneric_decal.inc" +#include "mathlib/bumpvects.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +BEGIN_VS_SHADER( LightmappedGeneric_Decal, + "Help for LightmappedGeneric_Decal" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + SET_FLAGS( MATERIAL_VAR_DECAL ); + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if ( !params[BASETEXTURE]->GetTextureValue()->IsTranslucent() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + } + + void DrawDecal( IMaterialVar **params, IShaderDynamicAPI *pShaderAPI, IShaderShadow *pShaderShadow ) + { + if( IsSnapshotting() ) + { + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + SetNormalBlendingShadowState( BASETEXTURE, true ); + + int pTexCoords[3] = { 2, 2, 1 }; + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION | VERTEX_COLOR, 3, pTexCoords, 0 ); + + lightmappedgeneric_decal_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "LightmappedGeneric_Decal", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "LightmappedGeneric_Decal" ); + FogToFogColor(); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // Load the z^2 components of the lightmap coordinate axes only + // This is (N dot basis)^2 + Vector vecZValues( g_localBumpBasis[0].z, g_localBumpBasis[1].z, g_localBumpBasis[2].z ); + vecZValues *= vecZValues; + + Vector4D basis[3]; + basis[0].Init( vecZValues.x, vecZValues.x, vecZValues.x, 0.0f ); + basis[1].Init( vecZValues.y, vecZValues.y, vecZValues.y, 0.0f ); + basis[2].Init( vecZValues.z, vecZValues.z, vecZValues.z, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 0, (float*)basis, 3 ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP_BUMPED ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + SetModulationPixelShaderDynamicState( 3 ); + + lightmappedgeneric_decal_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + if( UsingFlashlight( params ) ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + } + else + { + DrawDecal( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc new file mode 100644 index 00000000..fd457be8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal_ps2x.fxc @@ -0,0 +1,59 @@ +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler LightMap0Sampler : register( s1 ); +sampler LightMap1Sampler : register( s2 ); +sampler LightMap2Sampler : register( s3 ); + +const float4 g_LightMap0Color : register( c0 ); +const float4 g_LightMap1Color : register( c1 ); +const float4 g_LightMap2Color : register( c2 ); +const float4 g_ModulationColor : register( c3 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + + +struct PS_INPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + float4 worldPos_projPosZ : TEXCOORD4; // Necessary for pixel fog + + float4 vColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 resultColor; + + // output = lightmapColor[0] * ( ( N dot basis[0] )^2 ) + + // lightmapColor[1] * ( ( N dot basis[1] )^2 ) + + // lightmapColor[2] * ( ( N dot basis[2] )^2 ) + + resultColor = tex2D( LightMap0Sampler, i.vTexCoord1 ) * g_LightMap0Color; + resultColor = (tex2D( LightMap1Sampler, i.vTexCoord2 ) * g_LightMap1Color) + resultColor; + resultColor = (tex2D( LightMap2Sampler, i.vTexCoord3 ) * g_LightMap2Color) + resultColor; + + // Modulate by decal texture + float4 decalColor = tex2D( BaseTextureSampler, i.vTexCoord0 ); + resultColor.rgb = resultColor * decalColor; + resultColor.a = decalColor.a; + + // Modulate by constant color + resultColor = resultColor * g_ModulationColor; + + // Modulate by per-vertex factor + resultColor = resultColor * i.vColor; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( resultColor, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc new file mode 100644 index 00000000..0b7db284 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_decal_vs20.fxc @@ -0,0 +1,74 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +const float4 cShaderConst0 : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cShaderConst1 : register( SHADER_SPECIFIC_CONST_1 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + + float4 worldPos_projPosZ : TEXCOORD4; // Necessary for pixel fog + + float4 vColor : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul( v.vPos, cModel[0] ); + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + + // Compute the texture coordinates given the offset between + // each bumped lightmap + float2 offset; + offset.x = v.vTexCoord2.x; + offset.y = 0.0f; + + o.vTexCoord0.x = dot( v.vTexCoord0, cShaderConst0 ); + o.vTexCoord0.y = dot( v.vTexCoord0, cShaderConst1 ); + + o.vTexCoord1 = offset + v.vTexCoord1.xy; + o.vTexCoord2 = (offset * 2.0) + v.vTexCoord1.xy; + o.vTexCoord3 = (offset * 3.0) + v.vTexCoord1.xy; + + o.vColor = v.vColor; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx6.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx6.cpp new file mode 100644 index 00000000..f55f8883 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx6.cpp @@ -0,0 +1,288 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( LightmappedGeneric, LightmappedGeneric_DX6 ) + +BEGIN_SHADER( LightmappedGeneric_DX6, + "Help for LightmappedGeneric_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "90", "Do specular pass only on dxlevel or higher (ie.80, 81, 90)" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( params[BASETEXTURE]->IsDefined() ) + { + if( !IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) + { + params[ENVMAP]->SetUndefined(); + params[ENVMAPMASK]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + LoadCubeMap( ENVMAP ); + } + else + { + LoadTexture( ENVMAP ); + } + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + { + LoadTexture( ENVMAPMASK ); + } + } + } + + SHADER_FALLBACK + { + return 0; + } + + int GetDrawFlagsPass1(IMaterialVar** params) + { + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD0; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + if (params[BASETEXTURE]->IsTexture()) + flags |= SHADER_DRAW_TEXCOORD1; + return flags; + } + + void DrawLightmapOnly( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + + SetModulationShadowState(); + SetDefaultBlendingShadowState( ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) ); + DefaultFog(); + } + DYNAMIC_STATE + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + SetModulationDynamicState(); + } + Draw(); + } + + void DrawBaseTimesLightmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Base times lightmap + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Alpha blending + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + // Independenly configure alpha and color + pShaderShadow->EnableAlphaPipe( true ); + + // color channel + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->EnableConstantColor( IsColorModulating() ); + + // alpha channel + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + if ((! IsColorModulating()) && ( ! IsAlphaModulating())) + pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) ); + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, TextureIsTranslucent(BASETEXTURE, true) ); + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, false ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD1; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + { + if ( (! IsColorModulating()) && ( ! IsAlphaModulating())) + flags |= SHADER_DRAW_COLOR; + + } + if (params[BASETEXTURE]->IsTexture()) + { + flags |= SHADER_DRAW_TEXCOORD0; + } + + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + SetModulationDynamicState(); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableAlphaPipe( false ); + } + } + + void DrawMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Pass 1 : Base * lightmap or just lightmap + if ( params[BASETEXTURE]->IsTexture() ) + { + DrawBaseTimesLightmap( params, pShaderAPI, pShaderShadow ); + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Draw the selfillum pass + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + else + { + DrawLightmapOnly( params, pShaderAPI, pShaderShadow ); + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + + // Pass 2 : Masked environment map + if (params[ENVMAP]->IsTexture()) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + } + else + { + // Base * Lightmap + env + DrawMode1( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// This allows us to use a block labelled 'Water_DX60' in the water materials +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( Water_DX60, LightmappedGeneric_DX6, "Help for Water_DX60" ) +END_INHERITED_SHADER + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp new file mode 100644 index 00000000..8464f94f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp @@ -0,0 +1,802 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + + +#include "lightmappedgeneric_vs11.inc" +#include "unlitgeneric_vs11.inc" +#include "worldvertextransition_seamless.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +DEFINE_FALLBACK_SHADER( LightmappedGeneric, LightmappedGeneric_DX8 ) + +BEGIN_VS_SHADER( LightmappedGeneric_DX8, + "Help for LightmappedGeneric_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "amount of detail texture to apply" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_INTEGER, "90", "Do specular pass only on dxlevel or higher (ie.80, 81, 90)" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_BOOL, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( FORCEBUMP, SHADER_PARAM_TYPE_BOOL, "0", "0 == Do bumpmapping if the card says it can handle it. 1 == Always do bumpmapping." ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + END_SHADER_PARAMS + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + return g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined(); + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( ShouldUseBumpmapping( params ) && params[ALBEDO]->IsDefined() && + params[BASETEXTURE]->IsDefined() && + !( params[NODIFFUSEBUMPLIGHTING]->IsDefined() && params[NODIFFUSEBUMPLIGHTING]->GetIntValue() ) ) + { + params[BASETEXTURE]->SetStringValue( params[ALBEDO]->GetStringValue() ); + } + + if( IsUsingGraphics() && params[ENVMAP]->IsDefined() && !CanUseEditorMaterials() ) + { + if( stricmp( params[ENVMAP]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + { + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[DETAILBLENDFACTOR]->IsDefined() ) + { + params[DETAILBLENDFACTOR]->SetFloatValue( 1.0f ); + } + + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + { + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + + if( !params[ALPHATESTREFERENCE]->IsDefined() ) + { + params[ALPHATESTREFERENCE]->SetFloatValue( 0.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( ShouldUseBumpmapping( params ) && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && (params[ENVMAPOPTIONAL]->GetIntValue() > g_pHardwareConfig->GetDXSupportLevel()) ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + if( params[SEAMLESS_SCALE]->IsDefined() && params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + if( params[BUMPMAP]->IsDefined() ) + { + Warning( "Can't use $bumpmap with $seamless_scale for lightmappedgeneric_dx8. Implicitly disabling $bumpmap: %s\n", pMaterialName ); + params[BUMPMAP]->SetUndefined(); + } + if( params[ENVMAP]->IsDefined() ) + { + Warning( "Can't use $envmap with $seamless_scale for lightmappedgeneric_dx8. Implicitly disabling $envmap: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if ( !params[SEAMLESS_SCALE]->IsDefined() ) + { + // zero means don't do seamless mapping. + params[SEAMLESS_SCALE]->SetFloatValue( 0.0f ); + } + + // Get rid of envmap if we aren't using bumpmapping + // *and* we have normalmapalphaenvmapmask *and* we don't have envmapmask elsewhere + if ( params[ENVMAP]->IsDefined() && params[BUMPMAP]->IsDefined() && IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) && !ShouldUseBumpmapping( params ) ) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) && !params[ENVMAPMASK]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + } + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80) + return "LightmappedGeneric_DX6"; + + if ( IsPC() && g_pHardwareConfig->PreferReducedFillrate() ) + return "LightmappedGeneric_NoBump_DX8"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + + if( ShouldUseBumpmapping( params ) ) + { + LoadBumpMap( BUMPMAP ); + } + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + + if( ShouldUseBumpmapping( params ) ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + } + +#ifndef USE_HLSL_PIXEL_SHADERS + inline const char *GetPixelShaderName( IMaterialVar** params, bool bBumpedEnvMap ) + { + static char const* s_pPixelShaders[] = + { + // Unmasked + "LightmappedGeneric_EnvMapV2", + "LightmappedGeneric_SelfIlluminatedEnvMapV2", + + "LightmappedGeneric_BaseAlphaMaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedEnvMapV2", + + // Env map mask + "LightmappedGeneric_MaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2", + + "LightmappedGeneric_MaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2", + }; + + if (!params[BASETEXTURE]->IsTexture()) + { + if (params[ENVMAP]->IsTexture() && !bBumpedEnvMap ) + { + if (!params[ENVMAPMASK]->IsDefined() ) + { + return "LightmappedGeneric_EnvmapNoTexture"; + } + else + { + return "LightmappedGeneric_MaskedEnvmapNoTexture"; + } + } + else + { + return "LightmappedGeneric_NoTexture"; + } + } + else + { + if (params[ENVMAP]->IsTexture() && !bBumpedEnvMap ) + { + int pshIndex = 0; + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + pshIndex |= 0x1; + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pshIndex |= 0x2; + if (params[ENVMAPMASK]->IsTexture()) + pshIndex |= 0x4; + return s_pPixelShaders[pshIndex]; + } + else + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + return "LightmappedGeneric_SelfIlluminated"; + else + return "LightmappedGeneric"; + } + } + } +#endif + + void DrawUnbumpedUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + bool hasEnvmap = params[ENVMAP]->IsTexture() && !bBumpedEnvMap; + bool hasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasEnvmapCameraSpace = IS_FLAG_SET( MATERIAL_VAR_ENVMAPCAMERASPACE ); + bool hasEnvmapSphere = IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ); + + if ( hasEnvmap || hasBaseTexture || hasVertexColor || !bBumpedEnvMap ) + { + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + if ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + + // Base texture on stage 0 + if (params[BASETEXTURE]->IsTexture()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + + // Lightmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + + if ( hasEnvmap ) + { + fmt |= VERTEX_NORMAL; + + // envmap on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // envmapmask on stage 3 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + } + + if (params[BASETEXTURE]->IsTexture() || bBumpedEnvMap) + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetDefaultBlendingShadowState( ENVMAPMASK, false ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + { + fmt |= VERTEX_COLOR; + } + + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( hasEnvmap ); + vshIndex.SetENVMAPCAMERASPACE( hasEnvmap && hasEnvmapCameraSpace ); + vshIndex.SetENVMAPSPHERE( hasEnvmap && hasEnvmapSphere ); + vshIndex.SetVERTEXCOLOR( hasVertexColor ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetPixelShaderName( params, bBumpedEnvMap ); + pShaderShadow->SetPixelShader( pshName ); + DefaultFog(); + } + DYNAMIC_STATE + { + if (hasBaseTexture) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( hasEnvmap ) + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + if (params[ENVMAPMASK]->IsTexture() ) + BindTexture( SHADER_SAMPLER3, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || + IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + SetEnvMapTintPixelShaderDynamicState( 2, ENVMAPTINT, -1 ); + } + + if ( !hasEnvmap || hasBaseTexture || hasVertexColor ) + { + SetModulationVertexShaderDynamicState(); + } + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + if ( bBumpedEnvMap ) + { + DrawWorldBumpedSpecularLighting( + BUMPMAP, ENVMAP, BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + hasEnvmap || hasBaseTexture || hasVertexColor ); + } + } + + void DrawDetailNoEnvmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doSelfIllum ) + { + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Base texture on stage 0 + if (params[BASETEXTURE]->IsTexture()) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Lightmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Detail on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + fmt |= VERTEX_COLOR; + + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( true ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + if (!params[BASETEXTURE]->IsTexture()) + { + pShaderShadow->SetPixelShader("LightmappedGeneric_DetailNoTexture"); + } + else + { + if (!IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || (!doSelfIllum)) + { + pShaderShadow->SetPixelShader("LightmappedGeneric_Detail"); + } + else + { + pShaderShadow->SetPixelShader("LightmappedGeneric_DetailSelfIlluminated"); + } + } + DefaultFog(); + } + DYNAMIC_STATE + { + if (params[BASETEXTURE]->IsTexture()) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + BindTexture( SHADER_SAMPLER2, DETAIL, FRAME ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + + SetModulationVertexShaderDynamicState(); + EnablePixelShaderOverbright( 0, true, true ); + + if (doSelfIllum) + { + SetPixelShaderConstant( 1, SELFILLUMTINT ); + } + float c2[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c2[0] = c2[1] = c2[2] = c2[3] = params[DETAILBLENDFACTOR]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline const char *GetAdditiveEnvmapPixelShaderName( bool usingMask, + bool usingBaseTexture, bool usingBaseAlphaEnvmapMask ) + { + static char const* s_pPixelShaders[] = + { + "LightmappedGeneric_AddEnvmapNoTexture", + "LightmappedGeneric_AddEnvmapMaskNoTexture", + }; + + if ( !usingMask && usingBaseTexture && usingBaseAlphaEnvmapMask ) + return "LightmappedGeneric_AddBaseAlphaMaskedEnvMap"; + + int pshIndex = 0; + if (usingMask) + pshIndex |= 0x1; + return s_pPixelShaders[pshIndex]; + } + + void DrawAdditiveEnvmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + bool usingBaseTexture = params[BASETEXTURE]->IsTexture(); + bool usingMask = params[ENVMAPMASK]->IsTexture(); + bool usingBaseAlphaEnvmapMask = IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK); + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + + // envmap on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // envmapmask on stage 3 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + if (params[BASETEXTURE]->IsTexture()) + { + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetAdditiveBlendingShadowState( ENVMAPMASK, false ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // Compute the vertex shader index. + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( true ); + vshIndex.SetENVMAPCAMERASPACE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ); + vshIndex.SetENVMAPSPHERE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ); + vshIndex.SetVERTEXCOLOR( false ); + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetAdditiveEnvmapPixelShaderName( usingMask, + usingBaseTexture, usingBaseAlphaEnvmapMask ); + pShaderShadow->SetPixelShader( pshName ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + + if (usingMask || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + { + if (usingMask) + BindTexture( SHADER_SAMPLER3, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + SetPixelShaderConstant( 2, ENVMAPTINT ); + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + + SetModulationVertexShaderDynamicState(); + + // Compute the vertex shader index. + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + void DrawDetailMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + // Mode 1 : + // Pass 1 : B * L * D + Self Illum + // Pass 2 : Add E * M + + // Draw the detail w/ no envmap + DrawDetailNoEnvmap( params, pShaderAPI, pShaderShadow, true ); + + if ( !bBumpedEnvMap ) + { + DrawAdditiveEnvmap( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawWorldBumpedSpecularLighting( + BUMPMAP, ENVMAP, BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + true ); + } + } + + void DrawDetailUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + // We don't have enough textures; gotta do this in two passes if there's envmapping + if (!params[ENVMAP]->IsTexture()) + { + DrawDetailNoEnvmap( params, pShaderAPI, pShaderShadow, IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) ); + } + else + { + if (!params[BASETEXTURE]->IsTexture()) + { + // If there's an envmap but no base texture, ignore detail + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + else + { + DrawDetailMode1( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + } + + void DrawUnbumpedSeamlessUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // This is the seamless_scale version, which doesn't use $detail or $bumpmap + SHADOW_STATE + { + // three copies of the base texture for seamless blending + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_seamless_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_Seamless", vshIndex.GetIndex() ); + + int pshIndex = 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_Seamless", pshIndex ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + // Texture 0..2 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + float fSeamlessScale = params[SEAMLESS_SCALE]->GetFloatValue(); + float map_scale[4]= { fSeamlessScale, fSeamlessScale, fSeamlessScale, fSeamlessScale }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + + worldvertextransition_seamless_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + bool bBump = ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture() && + (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0); + bool bSSBump = bBump && ( params[SSBUMP]->GetIntValue() != 0 ); + + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + } + else if( bBump ) + { + DrawWorldBumpedUsingVertexShader( + BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, + ENVMAPFRAME, ENVMAPTINT, COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, FRESNELREFLECTION, + false, -1, -1, -1, bSSBump ); + } + else + { + bool bBumpedEnvMap = ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture() && params[ENVMAP]->IsTexture(); + if (!params[DETAIL]->IsTexture()) + { + if( params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + DrawUnbumpedSeamlessUsingVertexShader( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + else + { + DrawDetailUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// Version that doesn't do bumpmapping +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( LightmappedGeneric_NoBump_DX8, LightmappedGeneric_DX8, + "Help for LightmappedGeneric_NoBump_DX8" ) + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 80) + return "LightmappedGeneric_DX6"; + + return 0; + } + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + if ( !g_pConfig->UseBumpmapping() ) + return false; + + if ( !params[BUMPMAP]->IsDefined() ) + return false; + + return ( params[FORCEBUMP]->GetIntValue() != 0 ); + } + +END_INHERITED_SHADER diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp new file mode 100644 index 00000000..bac124a8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9.cpp @@ -0,0 +1,164 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "lightmappedgeneric_dx9_helper.h" + +static LightmappedGeneric_DX9_Vars_t s_info; + + +BEGIN_VS_SHADER( LightmappedGeneric, + "Help for LightmappedGeneric" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + + SHADER_PARAM( ALPHA2, SHADER_PARAM_TYPE_FLOAT, "1", "" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( BUMPMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( BUMPMASK, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/lightmappedtexture", "Blended texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $basetexture2" ) + SHADER_PARAM( BASETEXTURENOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BASETEXTURE2NOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "light munging lookup texture" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( MASKEDBLENDING, SHADER_PARAM_TYPE_INTEGER, "0", "blend using texture with no vertex alpha. For using texture blending on non-displacements" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") +END_SHADER_PARAMS + + void SetupVars( LightmappedGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + + info.m_nAlpha2 = ALPHA2; + + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTint = DETAILTINT; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoDiffuseBumpLighting = NODIFFUSEBUMPLIGHTING; + info.m_nBumpmap2 = BUMPMAP2; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBumpMask = BUMPMASK; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nBaseTexture2Frame = FRAME2; + info.m_nBaseTextureNoEnvmap = BASETEXTURENOENVMAP; + info.m_nBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP; + info.m_nDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nLightWarpTexture = LIGHTWARPTEXTURE; + info.m_nBlendModulateTexture = BLENDMODULATETEXTURE; + info.m_nMaskedBlending = MASKEDBLENDING; + info.m_nBlendMaskTransform = BLENDMASKTRANSFORM; + info.m_nSelfShadowedBumpFlag = SSBUMP; + info.m_nSeamlessMappingScale = SEAMLESS_SCALE; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + + info.m_nSoftEdges = SOFTEDGES; + info.m_nEdgeSoftnessStart = EDGESOFTNESSSTART; + info.m_nEdgeSoftnessEnd = EDGESOFTNESSEND; + info.m_nOutline = OUTLINE; + info.m_nOutlineColor = OUTLINECOLOR; + info.m_nOutlineAlpha = OUTLINEALPHA; + info.m_nOutlineStart0 = OUTLINESTART0; + info.m_nOutlineStart1 = OUTLINESTART1; + info.m_nOutlineEnd0 = OUTLINEEND0; + info.m_nOutlineEnd1 = OUTLINEEND1; + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "LightmappedGeneric_DX8"; + + return 0; + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + SetupVars( s_info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); + } + + SHADER_INIT + { + SetupVars( s_info ); + InitLightmappedGeneric_DX9( this, params, s_info ); + } + + SHADER_DRAW + { + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp new file mode 100644 index 00000000..9da6716d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp @@ -0,0 +1,1085 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//============================================================================= + +#include "lightmappedgeneric_dx9_helper.h" +#include "BaseVSShader.h" +#include "commandbuilder.h" +#include "convar.h" +#include "lightmappedgeneric_ps20.inc" +#include "lightmappedgeneric_vs20.inc" +#include "lightmappedgeneric_ps20b.inc" + +#include "tier0/memdbgon.h" + +ConVar mat_disable_lightwarp( "mat_disable_lightwarp", "0" ); +ConVar mat_disable_fancy_blending( "mat_disable_fancy_blending", "0" ); +ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +ConVar my_mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +extern ConVar r_flashlight_version2; + +class CLightmappedGeneric_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > m_SemiStaticCmdsOut; + + bool m_bVertexShaderFastPath; + bool m_bPixelShaderFastPath; + bool m_bPixelShaderForceFastPathBecauseOutline; + bool m_bFullyOpaque; + bool m_bFullyOpaqueWithoutAlphaTest; + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CLightmappedGeneric_DX9_Context( void ) + { + m_pStaticCmds = NULL; + } + + ~CLightmappedGeneric_DX9_Context( void ) + { + ResetStaticCmds(); + } + +}; + + +void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightmappedGeneric_DX9_Vars_t &info ) +{ + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() && + !( params[info.m_nNoDiffuseBumpLighting]->IsDefined() && params[info.m_nNoDiffuseBumpLighting]->GetIntValue() ) ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + if( pShader->IsUsingGraphics() && params[info.m_nEnvmap]->IsDefined() && !pShader->CanUseEditorMaterials() ) + { + if( stricmp( params[info.m_nEnvmap]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + } + + if ( (mat_disable_lightwarp.GetBool() ) && + (info.m_nLightWarpTexture != -1) ) + { + params[info.m_nLightWarpTexture]->SetUndefined(); + } + if ( (mat_disable_fancy_blending.GetBool() ) && + (info.m_nBlendModulateTexture != -1) ) + { + params[info.m_nBlendModulateTexture]->SetUndefined(); + } + + if( !params[info.m_nEnvmapTint]->IsDefined() ) + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[info.m_nNoDiffuseBumpLighting]->IsDefined() ) + params[info.m_nNoDiffuseBumpLighting]->SetIntValue( 0 ); + + if( !params[info.m_nSelfIllumTint]->IsDefined() ) + params[info.m_nSelfIllumTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[info.m_nDetailScale]->IsDefined() ) + params[info.m_nDetailScale]->SetFloatValue( 4.0f ); + + if ( !params[info.m_nDetailTint]->IsDefined() ) + params[info.m_nDetailTint]->SetVecValue( 1.0f, 1.0f, 1.0f, 1.0f ); + + InitFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + InitIntParam( info.m_nDetailTextureCombineMode, params, 0 ); + + if( !params[info.m_nFresnelReflection]->IsDefined() ) + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + + if( !params[info.m_nEnvmapMaskFrame]->IsDefined() ) + params[info.m_nEnvmapMaskFrame]->SetIntValue( 0 ); + + if( !params[info.m_nEnvmapFrame]->IsDefined() ) + params[info.m_nEnvmapFrame]->SetIntValue( 0 ); + + if( !params[info.m_nBumpFrame]->IsDefined() ) + params[info.m_nBumpFrame]->SetIntValue( 0 ); + + if( !params[info.m_nDetailFrame]->IsDefined() ) + params[info.m_nDetailFrame]->SetIntValue( 0 ); + + if( !params[info.m_nEnvmapContrast]->IsDefined() ) + params[info.m_nEnvmapContrast]->SetFloatValue( 0.0f ); + + if( !params[info.m_nEnvmapSaturation]->IsDefined() ) + params[info.m_nEnvmapSaturation]->SetFloatValue( 1.0f ); + + InitFloatParam( info.m_nAlphaTestReference, params, 0.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if( params[info.m_nBumpmap]->IsDefined() ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nEnvmap]->SetUndefined(); + } + + if( !params[info.m_nBaseTextureNoEnvmap]->IsDefined() ) + { + params[info.m_nBaseTextureNoEnvmap]->SetIntValue( 0 ); + } + if( !params[info.m_nBaseTexture2NoEnvmap]->IsDefined() ) + { + params[info.m_nBaseTexture2NoEnvmap]->SetIntValue( 0 ); + } + + if( ( info.m_nSelfShadowedBumpFlag != -1 ) && + ( !params[info.m_nSelfShadowedBumpFlag]->IsDefined() ) + ) + { + params[info.m_nSelfShadowedBumpFlag]->SetIntValue( 0 ); + } + // handle line art parms + InitFloatParam( info.m_nEdgeSoftnessStart, params, 0.5 ); + InitFloatParam( info.m_nEdgeSoftnessEnd, params, 0.5 ); + InitFloatParam( info.m_nOutlineAlpha, params, 1.0 ); +} + +void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ) +{ + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + } + + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap2]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap2 ); + } + + if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpMask]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpMask ); + } + + if (params[info.m_nBaseTexture]->IsDefined()) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + + if (!params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[info.m_nBaseTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2, TEXTUREFLAGS_SRGB ); + } + + if (params[info.m_nLightWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nLightWarpTexture ); + } + + if ((info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsDefined()) ) + { + pShader->LoadTexture( info.m_nBlendModulateTexture ); + } + + if (params[info.m_nDetail]->IsDefined()) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + nDetailBlendMode = nDetailBlendMode > 1 ? 1 : nDetailBlendMode; + + pShader->LoadTexture( info.m_nDetail, nDetailBlendMode != 0 ? TEXTUREFLAGS_SRGB : 0 ); + } + + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if (params[info.m_nEnvmap]->IsDefined()) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + else + { + pShader->LoadTexture( info.m_nEnvmap ); + } + + if ( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if ( params[info.m_nEnvmapMask]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + } + } + else + { + params[info.m_nEnvmapMask]->SetUndefined(); + } + + // We always need this because of the flashlight. + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); +} + +void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** params, bool hasFlashlight, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, + CBasePerMaterialContextData **pContextDataPtr + ) +{ + CLightmappedGeneric_DX9_Context *pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr ); + if ( pShaderShadow || ( ! pContextData ) || pContextData->m_bMaterialVarsChanged || hasFlashlight ) + { + bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture(); + int nAlphaChannelTextureVar = hasBaseTexture ? (int)info.m_nBaseTexture : (int)info.m_nEnvmapMask; + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( nAlphaChannelTextureVar, hasBaseTexture ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bFullyOpaqueWithoutAlphaTest = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && (!hasFlashlight || IsX360()); //dest alpha is free for special use + bool bFullyOpaque = bFullyOpaqueWithoutAlphaTest && !bIsAlphaTested; + bool bNeedRegenStaticCmds = (! pContextData ) || pShaderShadow; + + if ( ! pContextData ) // make sure allocated + { + pContextData = new CLightmappedGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + + bool hasBump = ( params[info.m_nBumpmap]->IsTexture() ) && ( !g_pHardwareConfig->PreferReducedFillrate() ); + bool hasSSBump = hasBump && (info.m_nSelfShadowedBumpFlag != -1) && ( params[info.m_nSelfShadowedBumpFlag]->GetIntValue() ); + bool hasBaseTexture2 = hasBaseTexture && params[info.m_nBaseTexture2]->IsTexture(); + bool hasLightWarpTexture = params[info.m_nLightWarpTexture]->IsTexture(); + bool hasBump2 = hasBump && params[info.m_nBumpmap2]->IsTexture(); + bool hasDetailTexture = params[info.m_nDetail]->IsTexture(); + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + bool hasBumpMask = hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum && + !hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0); + bool bHasBlendModulateTexture = + (info.m_nBlendModulateTexture != -1) && + (params[info.m_nBlendModulateTexture]->IsTexture() ); + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + if ( hasFlashlight && !IsX360() ) + { + // !!speed!! do this in the caller so we don't build struct every time + CBaseVSShader::DrawFlashlight_dx90_Vars_t vars; + vars.m_bBump = hasBump; + vars.m_nBumpmapVar = info.m_nBumpmap; + vars.m_nBumpmapFrame = info.m_nBumpFrame; + vars.m_nBumpTransform = info.m_nBumpTransform; + vars.m_nFlashlightTextureVar = info.m_nFlashlightTexture; + vars.m_nFlashlightTextureFrameVar = info.m_nFlashlightTextureFrame; + vars.m_bLightmappedGeneric = true; + vars.m_bWorldVertexTransition = hasBaseTexture2; + vars.m_nBaseTexture2Var = info.m_nBaseTexture2; + vars.m_nBaseTexture2FrameVar = info.m_nBaseTexture2Frame; + vars.m_nBumpmap2Var = info.m_nBumpmap2; + vars.m_nBumpmap2Frame = info.m_nBumpFrame2; + vars.m_nBump2Transform = info.m_nBumpTransform2; + vars.m_nAlphaTestReference = info.m_nAlphaTestReference; + vars.m_bSSBump = hasSSBump; + vars.m_nDetailVar = info.m_nDetail; + vars.m_nDetailScale = info.m_nDetailScale; + vars.m_nDetailTextureCombineMode = info.m_nDetailTextureCombineMode; + vars.m_nDetailTextureBlendFactor = info.m_nDetailTextureBlendFactor; + vars.m_nDetailTint = info.m_nDetailTint; + + if ( ( info.m_nSeamlessMappingScale != -1 ) ) + vars.m_fSeamlessScale = params[info.m_nSeamlessMappingScale]->GetFloatValue(); + else + vars.m_fSeamlessScale = 0.0; + pShader->DrawFlashlight_dx90( params, pShaderAPI, pShaderShadow, vars ); + return; + } + + pContextData->m_bFullyOpaque = bFullyOpaque; + pContextData->m_bFullyOpaqueWithoutAlphaTest = bFullyOpaqueWithoutAlphaTest; + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( hasBump && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + ITexture *pBumpTex = params[info.m_nBumpmap]->GetTextureValue(); + if ( pBumpTex ) + { + nNormalDecodeMode = pBumpTex->GetNormalDecodeMode(); + + if ( hasBump2 ) // Check encoding of secondary normal if there is oneg + { + ITexture *pBumpTex2 = params[info.m_nBumpmap]->GetTextureValue(); + if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) ) + { + DevMsg("LightmappedGeneric: Primary and Secondary normal map compression formats don't match. This is unsupported!\n"); + Assert(0); + } + } + } + } + + int nNormalMaskDecodeMode = 0; + if ( hasBumpMask && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + ITexture *pBumpMaskTex = params[info.m_nBumpMask]->GetTextureValue(); + if ( pBumpMaskTex ) + { + nNormalMaskDecodeMode = pBumpMaskTex->GetNormalDecodeMode(); + } + } + + bool bHasOutline = IsBoolSet( info.m_nOutline, params ); + pContextData->m_bPixelShaderForceFastPathBecauseOutline = bHasOutline; + bool bHasSoftEdges = IsBoolSet( info.m_nSoftEdges, params ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + + + float fDetailBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasDiffuseBumpmap = hasBump && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + + if ( bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + + if( !hasBaseTexture ) + { + if( hasEnvmap ) + { + // if we only have an envmap (no basetexture), then we want the albedo to be black. + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK ); + } + else + { + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + } + staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( bSeamlessMapping ) + { + staticCmdsBuf.SetVertexShaderConstant4( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, + params[info.m_nSeamlessMappingScale]->GetFloatValue(),0,0,0 ); + } + staticCmdsBuf.StoreEyePosInPixelShaderConstant( 10 ); + staticCmdsBuf.SetPixelShaderFogParams( 11 ); + staticCmdsBuf.End(); + // now, copy buf + pContextData->m_pStaticCmds = new uint8[staticCmdsBuf.Size()]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + if ( pShaderShadow ) + { + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + pShader->SetDefaultBlendingShadowState( nAlphaChannelTextureVar, hasBaseTexture ); + + unsigned int flags = VERTEX_POSITION; + + // base texture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if ( hasLightWarpTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false ); + } + if ( bHasBlendModulateTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false ); + } + + if ( hasBaseTexture2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true ); + } +// if( hasLightmap ) + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + else + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + } + + if( hasEnvmap || ( IsX360() && hasFlashlight ) ) + { + if( hasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + } + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + } + + int nDetailBlendMode = 0; + if ( hasDetailTexture ) + { + nDetailBlendMode = GetIntParam( info.m_nDetailTextureCombineMode, params ); + ITexture *pDetailTexture = params[info.m_nDetail]->GetTextureValue(); + if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP ) + { + if ( hasBump ) + nDetailBlendMode = 10; // ssbump + else + nDetailBlendMode = 11; // ssbump_nobump + } + } + + if( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); + bool bSRGBState = ( nDetailBlendMode == 1 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, bSRGBState ); + } + + if( hasBump || hasNormalMapAlphaEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Normal map alpha, in the compressed normal case + } + } + if( hasBump2 ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // Secondary normal alpha, in the compressed normal case + } + } + if( hasBumpMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); + if ( nNormalMaskDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // Normal mask alpha, in the compressed normal case + } + } + if( hasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + + if( hasFlashlight && IsX360() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER15, true ); + } + + if( hasVertexColor || hasBaseTexture2 || hasBump2 ) + { + flags |= VERTEX_COLOR; + } + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + + int bumpmap_variant=(hasSSBump) ? 2 : hasBump; + bool bMaskedBlending=( (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() != 0) ); + + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, hasEnvmapMask ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, params[info.m_nEnvmap]->IsTexture() ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, hasBaseTexture2 || hasBump2 ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, hasBumpMask ); + + bool bReliefMapping = false; //( bumpmap_variant == 2 ) && ( ! bSeamlessMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( RELIEF_MAPPING, false );//bReliefMapping ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP, params[info.m_nBaseTextureNoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending); + SET_STATIC_PIXEL_SHADER_COMBO( RELIEF_MAPPING, bReliefMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMASK_DECODE_MODE, (int) nNormalMaskDecodeMode ); +#ifdef _X360 + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight); +#endif + SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, bumpmap_variant ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, hasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, hasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP, params[info.m_nBaseTextureNoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, 0 ); // No normal compression with ps_2_0 (yikes!) + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMASK_DECODE_MODE, 0 ); // No normal compression with ps_2_0 + SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + } + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff and writing depth to dest alpha + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + pShaderShadow->EnableSRGBWrite( true ); + + pShader->DefaultFog(); + + + } // end shadow state + } // end shadow || regen display list + if ( pShaderAPI && pContextData->m_bMaterialVarsChanged ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + bool bHasBlendMaskTransform= ( + (info.m_nBlendMaskTransform != -1) && + (info.m_nMaskedBlending != -1) && + (params[info.m_nMaskedBlending]->GetIntValue() ) && + ( ! (params[info.m_nBumpTransform]->MatrixIsIdentity() ) ) ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[info.m_nBaseTextureTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform]->MatrixIsIdentity() && + params[info.m_nBumpTransform2]->MatrixIsIdentity() && + params[info.m_nEnvmapMaskTransform]->MatrixIsIdentity() ); + + bHasTextureTransform |= bHasBlendMaskTransform; + + pContextData->m_bVertexShaderFastPath = !bHasTextureTransform; + + if( params[info.m_nDetail]->IsTexture() ) + { + pContextData->m_bVertexShaderFastPath = false; + } + if (bHasBlendMaskTransform) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( + VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, info.m_nBlendMaskTransform ); + } + + if ( ! pContextData->m_bVertexShaderFastPath ) + { + bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && + ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) ); + bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture(); + if (!bSeamlessMapping ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + // If we have a detail texture, then the bump texcoords are the same as the base texcoords. + if( hasBump && !hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform ); + } + else if ( hasBump2 ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform2 ); + } + } + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint ); + // set up shader modulation color + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + pShader->ComputeModulationColor( color ); + float flLScale = pShaderAPI->GetLightMapScaleFactor(); + color[0] *= flLScale; + color[1] *= flLScale; + color[2] *= flLScale; + + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + color[3] *= ( IS_PARAM_DEFINED( info.m_nAlpha2 ) && params[ info.m_nAlpha2 ]->GetFloatValue() > 0.0f ) ? params[ info.m_nAlpha2 ]->GetFloatValue() : 1.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, color ); + + if ( hasDetailTexture ) + { + float detailTintAndBlend[4] = {1, 1, 1, 1}; + + if ( info.m_nDetailTint != -1 ) + { + params[info.m_nDetailTint]->GetVecValue( detailTintAndBlend, 3 ); + } + + detailTintAndBlend[3] = fDetailBlendFactor; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 8, detailTintAndBlend ); + } + + float envmapTintVal[4]; + float selfIllumTintVal[4]; + params[info.m_nEnvmapTint]->GetVecValue( envmapTintVal, 3 ); + params[info.m_nSelfIllumTint]->GetVecValue( selfIllumTintVal, 3 ); + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + float envmapSaturation = params[info.m_nEnvmapSaturation]->GetFloatValue(); + float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue(); + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + pContextData->m_bPixelShaderFastPath = true; + bool bUsingContrast = hasEnvmap && ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) && (envmapSaturation != 1.0f); + bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f); + bool bUsingSelfIllumTint = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && (selfIllumTintVal[0] != 1.0f || selfIllumTintVal[1] != 1.0f || selfIllumTintVal[2] != 1.0f); + if ( bUsingContrast || bUsingFresnel || bUsingSelfIllumTint || !g_pConfig->bShowSpecular ) + { + pContextData->m_bPixelShaderFastPath = false; + } + if( !pContextData->m_bPixelShaderFastPath ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstants( 2, 3 ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapContrast]->GetVecValue() ); + pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapSaturation]->GetVecValue() ); + float flFresnel = params[info.m_nFresnelReflection]->GetFloatValue(); + // [ 0, 0, 1-R(0), R(0) ] + pContextData->m_SemiStaticCmdsOut.OutputConstantData4( 0., 0., 1.0 - flFresnel, flFresnel ); + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, params[info.m_nSelfIllumTint]->GetVecValue() ); + } + else + { + if ( bHasOutline ) + { + float flOutlineParms[8] = { GetFloatParam( info.m_nOutlineStart0, params ), + GetFloatParam( info.m_nOutlineStart1, params ), + GetFloatParam( info.m_nOutlineEnd0, params ), + GetFloatParam( info.m_nOutlineEnd1, params ), + 0,0,0, + GetFloatParam( info.m_nOutlineAlpha, params ) }; + if ( info.m_nOutlineColor != -1 ) + { + params[info.m_nOutlineColor]->GetVecValue( flOutlineParms + 4, 3 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, flOutlineParms, 2 ); + } + + if ( bHasSoftEdges ) + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( + 4, GetFloatParam( info.m_nEdgeSoftnessStart, params ), + GetFloatParam( info.m_nEdgeSoftnessEnd, params ), + 0,0 ); + } + } + // texture binds + if( hasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + // handle mat_fullbright 2 + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + // BASE TEXTURE + if( hasSelfIllum ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + // BASE TEXTURE 2 + if( hasBaseTexture2 ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_GREY ); + } + + // DETAIL TEXTURE + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER12, TEXTURE_GREY ); + } + + // disable color modulation + float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + // turn off environment mapping + envmapTintVal[0] = 0.0f; + envmapTintVal[1] = 0.0f; + envmapTintVal[2] = 0.0f; + } + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale ); + } + + if( hasBaseTexture2 ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nBaseTexture2, info.m_nBaseTexture2Frame ); + } + if( hasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetail, info.m_nDetailFrame ); + } + + if( hasBump || hasNormalMapAlphaEnvmapMask ) + { + if( !g_pConfig->m_bFastNoBump ) + { + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pContextData->m_SemiStaticCmdsOut.BindMultiTexture( pShader, SHADER_SAMPLER4, SHADER_SAMPLER9, info.m_nBumpmap, info.m_nBumpFrame ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT ); + } + } + if( hasBump2 ) + { + if( !g_pConfig->m_bFastNoBump ) + { + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pContextData->m_SemiStaticCmdsOut.BindMultiTexture( pShader, SHADER_SAMPLER5, SHADER_SAMPLER10, info.m_nBumpmap2, info.m_nBumpFrame2 ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nBumpmap2, info.m_nBumpFrame2 ); + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALMAP_FLAT ); + } + } + if( hasBumpMask ) + { + if( !g_pConfig->m_bFastNoBump ) + { + if ( nNormalMaskDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + Assert(0); + //pContextData->m_SemiStaticCmdsOut.BindTexture( SHADER_SAMPLER8, SHADER_SAMPLER11, info.m_nBumpMask ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nBumpMask, -1 ); + } + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_NORMALMAP_FLAT ); + } + } + + if( hasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if ( hasLightWarpTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nLightWarpTexture, -1 ); + } + + if ( bHasBlendModulateTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBlendModulateTexture, -1 ); + } + + pContextData->m_SemiStaticCmdsOut.End(); + } + } + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + bool hasEnvmap = params[info.m_nEnvmap]->IsTexture(); + + if( hasEnvmap ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ); + + bool bVertexShaderFastPath = pContextData->m_bVertexShaderFastPath; + + if( nFixedLightingMode != 0 ) + { + if ( pContextData->m_bPixelShaderForceFastPathBecauseOutline ) + nFixedLightingMode = 0; + else + bVertexShaderFastPath = false; + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( + LIGHTING_PREVIEW, + (nFixedLightingMode)?1:0 + ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_vs20 ); + + bool bPixelShaderFastPath = pContextData->m_bPixelShaderFastPath; + if( nFixedLightingMode !=0 ) + { + bPixelShaderFastPath = false; + } + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( pContextData->m_bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue(); + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nFixedLightingMode ); + + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH, bPixelShaderFastPath ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST, bPixelShaderFastPath && envmapContrast == 1.0f ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nFixedLightingMode ); + + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps20 ); + } + + if( hasFlashlight && IsX360() ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + + DynamicCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 ); + + SetFlashLightColorFromState( flashlightState, pShaderAPI ); + + float atten[4], pos[4]; + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + DynamicCmdsOut.SetPixelShaderConstant( 13, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + DynamicCmdsOut.SetPixelShaderConstant( 14, pos, 1 ); + + pShader->BindTexture( SHADER_SAMPLER13, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER14, pFlashlightDepthTexture, 0 ); + DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER15, TEXTURE_SHADOW_NOISE_2D ); + + // Tweaks associated with a given flashlight + float tweaks[4]; + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + DynamicCmdsOut.SetPixelShaderConstant( 19, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + DynamicCmdsOut.SetPixelShaderConstant( 31, vScreenScale, 1 ); + } + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); + + if( IsPC() && (IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0) && pContextData->m_bFullyOpaqueWithoutAlphaTest ) + { + //Alpha testing makes it so we can't write to dest alpha + //Writing to depth makes it so later polygons can't write to dest alpha either + //This leads to situations with garbage in dest alpha. + + //Fix it now by converting depth to dest alpha for any pixels that just wrote. + pShader->DrawEqualDepthToDestAlpha(); + } +} + +void DrawLightmappedGeneric_DX9(CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, + CBasePerMaterialContextData **pContextDataPtr ) +{ + bool hasFlashlight = pShader->UsingFlashlight( params ); + if ( !IsX360() && !r_flashlight_version2.GetInt() ) + { + DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr ); + return; + } + + DrawLightmappedGeneric_DX9_Internal( pShader, params, hasFlashlight, pShaderAPI, pShaderShadow, info, pContextDataPtr ); +} diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h new file mode 100644 index 00000000..00375b9f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef LIGHTMAPPEDGENERIC_DX9_HELPER_H +#define LIGHTMAPPEDGENERIC_DX9_HELPER_H + +#include +#include "BaseVSShader.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct LightmappedGeneric_DX9_Vars_t +{ + LightmappedGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(LightmappedGeneric_DX9_Vars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nSelfIllumTint; + + int m_nAlpha2; // Hack for DoD srgb blend issues on overlays + + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + int m_nDetailTint; + + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nFresnelReflection; + int m_nNoDiffuseBumpLighting; + int m_nBumpmap2; + int m_nBumpFrame2; + int m_nBumpTransform2; + int m_nBumpMask; + int m_nBaseTexture2; + int m_nBaseTexture2Frame; + int m_nBaseTextureNoEnvmap; + int m_nBaseTexture2NoEnvmap; + int m_nDetailAlphaMaskBaseTexture; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + int m_nLightWarpTexture; + int m_nBlendModulateTexture; + int m_nMaskedBlending; + int m_nBlendMaskTransform; + int m_nSelfShadowedBumpFlag; + int m_nSeamlessMappingScale; + int m_nAlphaTestReference; + + int m_nSoftEdges; + int m_nEdgeSoftnessStart; + int m_nEdgeSoftnessEnd; + + int m_nOutline; + int m_nOutlineColor; + int m_nOutlineAlpha; + int m_nOutlineStart0; + int m_nOutlineStart1; + int m_nOutlineEnd0; + int m_nOutlineEnd1; + +}; + +void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, LightmappedGeneric_DX9_Vars_t &info ); +void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ); +void DrawLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr ); + + +#endif // LIGHTMAPPEDGENERIC_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_envmap.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_envmap.psh new file mode 100644 index 00000000..1e4a2bc4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_envmap.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lightmap (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs11.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs11.fxc new file mode 100644 index 00000000..3a0d059d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs11.fxc @@ -0,0 +1,122 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "NORMALMAP" "0..1" +// STATIC: "WORLDVERTEXTRANSITION" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +const float3 g_FlashlightPos : register( SHADER_SPECIFIC_CONST_0 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_1 ); +const float4 g_FlashlightAttenuationFactors : register( SHADER_SPECIFIC_CONST_5 ); + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cNormalMapTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_8 ); + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + // If this is float4, and the input is float3, the w component default to one. + float4 vPos : POSITION; + float3 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; +#if NORMALMAP + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +#endif + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float4 spotTexCoord : TEXCOORD0; + float2 baseTexCoord : TEXCOORD1; +#if NORMALMAP + float3 tangentPosToLightVector : TEXCOORD2; + float2 normalMapTexCoord : TEXCOORD3; +#else + float3 worldPosToLightVector : TEXCOORD2; + float3 normal : TEXCOORD3; +#endif + float4 vertAtten : COLOR0; +}; + +float RemapValClamped( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float4 projPos; + float3 worldPos; + float3 worldNormal; + float3 eyeVector; + + projPos = mul( v.vPos, cModelViewProj ); + o.projPos = projPos; + + worldPos = mul( v.vPos, cModel[0] ); + worldNormal = mul( v.vNormal, ( float3x3 )cModel[0] ); + +#if NORMALMAP + float3 worldTangentS = mul( v.vTangentS, cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, cModel[0] ); +#endif + +#if !defined( _X360 ) + o.fog = CalcFog( worldPos, projPos, g_FogType ); +#endif + + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + + float4 spotTexCoord = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.spotTexCoord = spotTexCoord.xyzw; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; +#if NORMALMAP + o.normalMapTexCoord.x = dot( v.vBaseTexCoord, cNormalMapTexCoordTransform[0] ) + cNormalMapTexCoordTransform[0].w; + o.normalMapTexCoord.y = dot( v.vBaseTexCoord, cNormalMapTexCoordTransform[1] ) + cNormalMapTexCoordTransform[1].w; + + o.tangentPosToLightVector.x = dot( worldPosToLightVector, worldTangentS ); + o.tangentPosToLightVector.y = dot( worldPosToLightVector, worldTangentT ); + o.tangentPosToLightVector.z = dot( worldPosToLightVector, worldNormal ); +#else + o.worldPosToLightVector = worldPosToLightVector; + o.normal = worldNormal; +#endif + + float3 delta = worldPosToLightVector; + float distSquared = dot( delta, delta ); + float dist = sqrt( distSquared ); + float farZ = g_FlashlightAttenuationFactors.w; + float endFalloffFactor = RemapValClamped( dist, farZ, 0.6 * farZ ); + o.vertAtten.xyz = saturate( endFalloffFactor * dot( g_FlashlightAttenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) ); + +#if WORLDVERTEXTRANSITION + o.vertAtten.w = 1 - v.vColor.w; +#else +#if VERTEXCOLOR + o.vertAtten.w = v.vColor.w; +#else + o.vertAtten.w = 1.0f; +#endif +#endif + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc new file mode 100644 index 00000000..7d23bb95 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_flashlight_vs20.fxc @@ -0,0 +1,184 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "NORMALMAP" "0..1" +// STATIC: "WORLDVERTEXTRANSITION" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "DETAIL" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +const float3 g_FlashlightPos : register( SHADER_SPECIFIC_CONST_0 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_1 ); +const float4 g_FlashlightAttenuationFactors : register( SHADER_SPECIFIC_CONST_5 ); + +#if SEAMLESS +const float4 SeamlessScale : register( SHADER_SPECIFIC_CONST_6 ); +#define SEAMLESS_SCALE (SeamlessScale.x) +#endif +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cNormalMapOrDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_8 ); + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float3 vPos : POSITION; //This HAS to match lightmappedgeneric_vs20.fxc's position input. Otherwise depth fighting errors occur on the 360 + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; +#if WORLDVERTEXTRANSITION + float2 vLightmapTexCoord : TEXCOORD1; + float4 vColor : COLOR0; +#endif +#if NORMALMAP + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + + float4 spotTexCoord : TEXCOORD0; + +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD1; +#else + float2 baseTexCoord : TEXCOORD1; +#endif + +#if NORMALMAP + float3 tangentPosToLightVector : TEXCOORD2; + float2 normalMapTexCoord : TEXCOORD3; +#else + float3 worldPosToLightVector : TEXCOORD2; + float3 normal : TEXCOORD3; +#endif + + float2 detailCoords : TEXCOORD4; + float4 worldPos_worldTransition : TEXCOORD5; + float3 vProjPos : TEXCOORD6; + float4 fogFactorW : TEXCOORD7; +}; + +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; +} + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float4 projPos; + float3 worldPos; + float3 worldNormal; + float3 eyeVector; + + //Projection math HAS to match lightmappedgeneric_vs20.fxc's math exactly. Otherwise depth fighting errors occur on the 360 + projPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = projPos; + o.vProjPos.xyz = projPos.xyw; + + worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + + o.worldPos_worldTransition = float4( worldPos.xyz, 1.0f ); + + o.fogFactorW = CalcFog( worldPos, projPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW.w; +#endif + +#if NORMALMAP + float3 worldTangentS = mul( v.vTangentS, cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, cModel[0] ); +#endif +#if SEAMLESS + float3 vNormal=normalize( worldNormal ); + o.fogFactorW.xyz = vNormal * vNormal; // sums to 1. + o.SeamlessTexCoord = SEAMLESS_SCALE*worldPos; + + // Generate new tangent and binormal with seamless projection + #if NORMALMAP + // Brute-force for prototype - This must match the projection in the pixel shader! + //float3 vVecX = { 1.0f, 0.0f, 0.0f }; + //float3 vVecY = { 0.0f, 1.0f, 0.0f }; + //float3 vVecZ = { 0.0f, 0.0f, 1.0f }; + //worldTangentS.xyz = normalize( ( o.fogFactorW.x * vVecZ.xyz ) + ( o.fogFactorW.y * vVecX.xyz ) + ( o.fogFactorW.z * vVecX.xyz ) ); + //worldTangentT.xyz = normalize( ( o.fogFactorW.x * vVecY.xyz ) + ( o.fogFactorW.y * vVecZ.xyz ) + ( o.fogFactorW.z * vVecY.xyz ) ); + + // Optimized version - This must match the projection in the pixel shader! + worldTangentS.xyz = normalize( float3( o.fogFactorW.y + o.fogFactorW.z, 0.0f, o.fogFactorW.x ) ); + worldTangentT.xyz = normalize( float3( 0.0f, o.fogFactorW.x + o.fogFactorW.z, o.fogFactorW.y ) ); + #endif +#else +#if (SEAMLESS == 0 ) + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; +#endif +#endif + + float4 spotTexCoord = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.spotTexCoord = spotTexCoord.xyzw; + + float3 worldPosToLightVector = g_FlashlightPos - worldPos; +#if NORMALMAP + +#if (DETAIL == 0) + o.normalMapTexCoord.x = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[0] ) + cNormalMapOrDetailTexCoordTransform[0].w; + o.normalMapTexCoord.y = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[1] ) + cNormalMapOrDetailTexCoordTransform[1].w; +#else + +#if SEAMLESS + o.normalMapTexCoord = v.vBaseTexCoord; +#else + o.normalMapTexCoord = o.baseTexCoord; +#endif + +#endif + + o.tangentPosToLightVector.x = dot( worldPosToLightVector, worldTangentS ); + o.tangentPosToLightVector.y = dot( worldPosToLightVector, worldTangentT ); + o.tangentPosToLightVector.z = dot( worldPosToLightVector, worldNormal ); +#else + o.worldPosToLightVector = worldPosToLightVector; + o.normal = worldNormal; +#endif + +#if DETAIL + o.detailCoords.x = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[0] ) + cNormalMapOrDetailTexCoordTransform[0].w; + o.detailCoords.y = dot( v.vBaseTexCoord, cNormalMapOrDetailTexCoordTransform[1] ) + cNormalMapOrDetailTexCoordTransform[1].w; +#else + o.detailCoords = float2(0,0); +#endif + + //float3 delta = worldPosToLightVector; + //float distSquared = dot( delta, delta ); + //float dist = sqrt( distSquared ); + //float farZ = g_FlashlightAttenuationFactors.w; + //float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f ); + //o.projPos_atten.w = endFalloffFactor * dot( g_FlashlightAttenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ); + //o.projPos_atten.w = saturate( o.projPos_atten.w ); + +#if WORLDVERTEXTRANSITION + o.worldPos_worldTransition.w = v.vColor.w; +#endif + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_inc.vsh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_inc.vsh new file mode 100644 index 00000000..a5d12a81 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_inc.vsh @@ -0,0 +1,110 @@ +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +; $SHADER_SPECIFIC_CONST_4 = Modulation color +;------------------------------------------------------------------------------ + +sub LightmappedGeneric +{ + local( $detail ) = shift; + local( $envmap ) = shift; + local( $envmapcameraspace ) = shift; + local( $envmapsphere ) = shift; + local( $vertexcolor ) = shift; + + local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + + &AllocateRegister( \$projPos ); + + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + mov oPos, $projPos + + &AllocateRegister( \$worldPos ); + + if( $DOWATERFOG == 1 ) + { + ; Get the worldpos z component only since that's all we need for height fog + dp4 $worldPos.z, $vPos, $cModel2 + } + &CalcFog( $worldPos, $projPos ); + &FreeRegister( \$projPos ); + + ;------------------------------------------------------------------------------ + ; Texture coordinates + ;------------------------------------------------------------------------------ + ; base texcoords + dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 + dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + ; lightmap texcoords + mov oT1, $vTexCoord1 + + if( $envmap ) + { + &AllocateRegister( \$worldNormal ); + + ; Transform the position + normal to world space + dp4 $worldPos.x, $vPos, $cModel0 + dp4 $worldPos.y, $vPos, $cModel1 + if( $DOWATERFOG ne 1 ) + { + dp4 $worldPos.z, $vPos, $cModel2 + } + + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + if( $envmapcameraspace ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + ; transform reflection vector into view space + dp3 oT2.x, $reflectionVector, $cViewModel0 + dp3 oT2.y, $reflectionVector, $cViewModel1 + dp3 oT2.z, $reflectionVector, $cViewModel2 + &FreeRegister( \$reflectionVector ); + } + elsif( $envmapsphere ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + &ComputeSphereMapTexCoords( $reflectionVector, "oT2" ); + &FreeRegister( \$reflectionVector ); + } + else + { + &ComputeReflectionVector( $worldPos, $worldNormal, "oT2" ); + } + ; envmap mask + dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 ; FIXME + dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 ; FIXME + +# &FreeRegister( \$worldPos ); + &FreeRegister( \$worldNormal ); + } + + &FreeRegister( \$worldPos ); # garymcthack + + if( $detail ) + { + dp4 oT2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 ; FIXME + dp4 oT2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 ; FIXME + } + + if( $vertexcolor ) + { + ; Modulation color + mul oD0, $vColor, $cModulationColor + } + else + { + ; Modulation color + mov oD0, $cModulationColor + } +} diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_overbright2_ps11.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_overbright2_ps11.fxc new file mode 100644 index 00000000..1dbb8b2f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_overbright2_ps11.fxc @@ -0,0 +1,12 @@ +sampler TextureSampler : register( s1 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord1 : TEXCOORD1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return tex2D( TextureSampler, i.vTexCoord1 ); +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_vs11.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_vs11.fxc new file mode 100644 index 00000000..afee6c9c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_lightingonly_vs11.fxc @@ -0,0 +1,51 @@ +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord1 : TEXCOORD1; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // YUCK! This is to make texcoords continuous for mat_softwaretl + o.vTexCoord0 = 0.0f; + o.vTexCoord1 = v.vTexCoord1; + + o.vDiffuse = 1.0f; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_maskedenvmap.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_maskedenvmap.psh new file mode 100644 index 00000000..4f72286f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_maskedenvmap.psh @@ -0,0 +1,22 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0, t0, v0 ; base times vertex color (with alpha) +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasealphamaskedselfillum.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasealphamaskedselfillum.psh new file mode 100644 index 00000000..a525a7b2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasealphamaskedselfillum.psh @@ -0,0 +1,24 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +def c0 0.5f 0.5f 0.5f 1.0f + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mul r1.a, t0, v0 ; base times vertex alpha +; GR - workaround for const/lerp issues +mul r0.rgb, c1, t0 ; Self illum * tint ++mul_sat r0.a, c1, t0 +lrp r1.rgb, t0.a, r1, r0 ; Blend between self-illum + lightmap +lrp r0, r1.a, r1, c0 ; interpolate between grey + color diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasenotexture.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasenotexture.psh new file mode 100644 index 00000000..77b05b9f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_multiplybylightingbasenotexture.psh @@ -0,0 +1,20 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 +tex t1 + +; Blend between grey and lightmap color based on total alpha + +def c2, 0.5f, 0.5f, 0.5f, 1.0f + +mul_x2 r1.rgb, c0, t1 ; Apply overbright to lightmap ++ mov r1.a, v0 ; vertex alpha +lrp r0, r1.a, r1, c2 ; interpolate between grey + color diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc new file mode 100644 index 00000000..d5be9e5f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps11.fxc @@ -0,0 +1,122 @@ +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "ENVMAP" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" + +// SKIP: !$ENVMAP && ( $BASEALPHAENVMAPMASK || $ENVMAPMASK ) +// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK +// SKIP: $SELFILLUM && $BASEALPHAENVMAPMASK +// SKIP: !$BASETEXTURE && $SELFILLUM + +const float3 g_OverbrightFactor : register( c0 ); +const float3 g_SelfIllumTint : register( c1 ); +const float3 g_EnvmapTint : register( c2 ); + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +sampler EnvmapMaskSampler : register( s3 ); + +//sampler DetailSampler : register( s3 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float2 lightmapTexCoord : TEXCOORD1; + float3 envmapTexCoord : TEXCOORD2; + float2 envmapMaskTexCoord : TEXCOORD3; + float4 vertexColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bBaseTexture = BASETEXTURE ? true : false; + bool bEnvmap = ENVMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + +#if 1 + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bBaseTexture ) + { + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + } + + float3 specularFactor = 1.0f; + + if( bEnvmapMask ) + { + specularFactor *= tex2D( EnvmapMaskSampler, i.envmapMaskTexCoord ).xyz; + } + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - baseColor.a; // this blows! + } + + float3 diffuseLighting = tex2D( LightmapSampler, i.lightmapTexCoord ); + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + if( bBaseTexture ) + { + albedo *= baseColor; + if( !bBaseAlphaEnvmapMask && !bSelfIllum ) + { + alpha *= baseColor.a; + } + } + + // The vertex color contains the modulation color + vertex color combined + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + float3 diffuseComponent = ( albedo * diffuseLighting * 2.0f ) * g_OverbrightFactor; + + if( bSelfIllum ) + { + float3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + + if( bEnvmap ) + { + specularLighting = tex2D( EnvmapSampler, i.envmapTexCoord ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + } + + float3 result = diffuseComponent + specularLighting; + return float4( result, alpha ); +#endif + +#if 0 + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + float3 diffuseLighting = tex2D( LightmapSampler, i.lightmapTexCoord ); + + float3 albedo = float3( 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + float3 diffuseComponent = ( albedo * diffuseLighting * 2.0f ) * g_OverbrightFactor; + float3 result = diffuseComponent; + return float4( result, alpha ); +#endif + +#if 0 + float4 result; + + result.rgb = tex2D( LightmapSampler, i.lightmapTexCoord ).rgb * i.vertexColor.rgb; + result.a = i.vertexColor.a; + result.rgb = ( result.rgb * g_OverbrightFactor ) * 2.0f; + return result; +#endif +} + + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h new file mode 100644 index 00000000..585ea1f6 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2_3_x.h @@ -0,0 +1,583 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// SKIP: $BUMPMAP2 && $WARPLIGHTING +// SKIP: $WARPLIGHTING && $DETAILTEXTURE +// SKIP: $ENVMAPMASK && $BUMPMAP +// SKIP: $NORMALMAPALPHAENVMAPMASK && $BASEALPHAENVMAPMASK +// SKIP: $NORMALMAPALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM +// SKIP: !$FASTPATH && $FASTPATHENVMAPCONTRAST +// SKIP: !$FASTPATH && $FASTPATHENVMAPTINT +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: !$BUMPMAP && $BUMPMAP2 +// SKIP: $ENVMAPMASK && $BUMPMAP2 +// SKIP: $BASETEXTURENOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) +// SKIP: $BASETEXTURE2NOENVMAP && ( !$BASETEXTURE2 || !$CUBEMAP ) +// SKIP: $BASEALPHAENVMAPMASK && $BUMPMAP +// SKIP: $PARALLAXMAP && $DETAILTEXTURE +// SKIP: $SEAMLESS && $RELIEF_MAPPING +// SKIP: $SEAMLESS && $DETAILTEXTURE +// SKIP: $SEAMLESS && $MASKEDBLENDING +// SKIP: $BUMPMASK && ( $SEAMLESS || $DETAILTEXTURE || $SELFILLUM || $BASETEXTURENOENVMAP || $BASETEXTURE2 ) +// SKIP: !$BUMPMAP && ($NORMAL_DECODE_MODE == 1) +// SKIP: !$BUMPMAP && ($NORMAL_DECODE_MODE == 2) +// SKIP: !$BUMPMAP && ($NORMALMASK_DECODE_MODE == 1) +// SKIP: !$BUMPMAP && ($NORMALMASK_DECODE_MODE == 2) +// NOSKIP: $FANCY_BLENDING && (!$FASTPATH) + +// 360 compiler craps out on some combo in this family. Content doesn't use blendmode 10 anyway +// SKIP: $FASTPATH && $PIXELFOGTYPE && $BASETEXTURE2 && $DETAILTEXTURE && $CUBEMAP && ($DETAIL_BLEND_MODE == 10 ) [XBOX] + +// debug crap: +// NOSKIP: $DETAILTEXTURE +// NOSKIP: $CUBEMAP +// NOSKIP: $ENVMAPMASK +// NOSKIP: $BASEALPHAENVMAPMASK +// NOSKIP: $SELFILLUM + +#define USE_32BIT_LIGHTMAPS_ON_360 //uncomment to use 32bit lightmaps, be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp + +#include "common_ps_fxc.h" +#include "common_flashlight_fxc.h" +#include "common_lightmappedgeneric_fxc.h" + +#if SEAMLESS +#define USE_FAST_PATH 1 +#else +#define USE_FAST_PATH FASTPATH +#endif + +const HALF4 g_EnvmapTint : register( c0 ); + +#if USE_FAST_PATH == 1 + +# if FASTPATHENVMAPCONTRAST == 0 +static const HALF3 g_EnvmapContrast = { 0.0f, 0.0f, 0.0f }; +# else +static const HALF3 g_EnvmapContrast = { 1.0f, 1.0f, 1.0f }; +# endif +static const HALF3 g_EnvmapSaturation = { 1.0f, 1.0f, 1.0f }; +static const HALF g_FresnelReflection = 1.0f; +static const HALF g_OneMinusFresnelReflection = 0.0f; +static const HALF4 g_SelfIllumTint = { 1.0f, 1.0f, 1.0f, 1.0f }; +# if OUTLINE +const float4 g_OutlineParams : register( c2 ); +#define OUTLINE_MIN_VALUE0 g_OutlineParams.x +#define OUTLINE_MIN_VALUE1 g_OutlineParams.y +#define OUTLINE_MAX_VALUE0 g_OutlineParams.z +#define OUTLINE_MAX_VALUE1 g_OutlineParams.w + +const float4 g_OutlineColor : register( c3 ); +#define OUTLINE_COLOR g_OutlineColor + +# endif +# if SOFTEDGES +const float4 g_EdgeSoftnessParms : register( c4 ); +#define SOFT_MASK_MIN g_EdgeSoftnessParms.x +#define SOFT_MASK_MAX g_EdgeSoftnessParms.y +# endif +#else + +const HALF3 g_EnvmapContrast : register( c2 ); +const HALF3 g_EnvmapSaturation : register( c3 ); +const HALF4 g_FresnelReflectionReg : register( c4 ); +#define g_FresnelReflection g_FresnelReflectionReg.a +#define g_OneMinusFresnelReflection g_FresnelReflectionReg.b +const HALF4 g_SelfIllumTint : register( c7 ); +#endif + +const float4 g_DetailTint_and_BlendFactor : register( c8 ); +#define g_DetailTint (g_DetailTint_and_BlendFactor.rgb) +#define g_DetailBlendFactor (g_DetailTint_and_BlendFactor.w) + +const HALF3 g_EyePos : register( c10 ); +const HALF4 g_FogParams : register( c11 ); +const float4 g_TintValuesAndLightmapScale : register( c12 ); + +#define g_flAlpha2 g_TintValuesAndLightmapScale.w + +const float4 g_FlashlightAttenuationFactors : register( c13 ); +const float3 g_FlashlightPos : register( c14 ); +const float4x4 g_FlashlightWorldToTexture : register( c15 ); // through c18 +const float4 g_ShadowTweaks : register( c19 ); + + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler EnvmapSampler : register( s2 ); +#if FANCY_BLENDING +sampler BlendModulationSampler : register( s3 ); +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s12 ); +#endif + +sampler BumpmapSampler : register( s4 ); +#if NORMAL_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMapSampler : register( s9 ); // alpha +#else +#define AlphaMapSampler BumpmapSampler +#endif + +#if BUMPMAP2 == 1 +sampler BumpmapSampler2 : register( s5 ); +#if NORMAL_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMapSampler2 : register( s10 ); // alpha +#else +#define AlphaMapSampler2 BumpmapSampler2 +#endif +#else +sampler EnvmapMaskSampler : register( s5 ); +#endif + + +#if WARPLIGHTING +sampler WarpLightingSampler : register( s6 ); +#endif +sampler BaseTextureSampler2 : register( s7 ); + +#if BUMPMASK == 1 +sampler BumpMaskSampler : register( s8 ); +#if NORMALMASK_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMaskSampler : register( s11 ); // alpha +#else +#define AlphaMaskSampler BumpMaskSampler +#endif +#endif + +#if defined( _X360 ) && FLASHLIGHT +sampler FlashlightSampler : register( s13 ); +sampler ShadowDepthSampler : register( s14 ); +sampler RandRotSampler : register( s15 ); +#endif + +struct PS_INPUT +{ +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD0; // zy xz + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; // envmap mask +#else + HALF2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. +#if ( RELIEF_MAPPING == 0 ) + HALF4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; +#endif +#endif +// CENTROID: TEXCOORD2 + HALF4 lightmapTexCoord1And2 : TEXCOORD2; +// CENTROID: TEXCOORD3 + HALF4 lightmapTexCoord3 : TEXCOORD3; + HALF4 worldPos_projPosZ : TEXCOORD4; + HALF3x3 tangentSpaceTranspose : TEXCOORD5; + // tangentSpaceTranspose : TEXCOORD6 + // tangentSpaceTranspose : TEXCOORD7 + HALF4 vertexColor : COLOR; + float4 vertexBlendX_fogFactorW : COLOR1; + + // Extra iterators on 360, used in flashlight combo +#if defined( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; + float4 vProjPos : TEXCOORD9; +#endif +}; + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +HALF4 main( PS_INPUT i ) : COLOR +#endif +{ + bool bBaseTexture2 = BASETEXTURE2 ? true : false; + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBumpmap = BUMPMAP ? true : false; + bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bBaseTextureNoEnvmap = BASETEXTURENOENVMAP ? true : false; + bool bBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP ? true : false; + + float4 baseColor = 0.0f; + float4 baseColor2 = 0.0f; + float4 vNormal = float4(0, 0, 1, 1); + float3 baseTexCoords = float3(0,0,0); + +#if SEAMLESS + baseTexCoords = i.SeamlessTexCoord.xyz; +#else + baseTexCoords.xy = i.baseTexCoord.xy; +#endif + + GetBaseTextureAndNormal( BaseTextureSampler, BaseTextureSampler2, BumpmapSampler, bBaseTexture2, bBumpmap || bNormalMapAlphaEnvmapMask, + baseTexCoords, i.vertexColor.rgb, baseColor, baseColor2, vNormal ); + +#if BUMPMAP == 1 // not ssbump + vNormal.xyz = vNormal.xyz * 2.0f - 1.0f; // make signed if we're not ssbump +#endif + + HALF3 lightmapColor1 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor2 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor3 = HALF3( 1.0f, 1.0f, 1.0f ); +#if LIGHTING_PREVIEW == 0 + if( bBumpmap && bDiffuseBumpmap ) + { + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + lightmapColor2 = LightMapSample( LightmapSampler, bumpCoord2 ); + lightmapColor3 = LightMapSample( LightmapSampler, bumpCoord3 ); + } + else + { + HALF2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ); + } +#endif + +#if RELIEF_MAPPING + // in the parallax case, all texcoords must be the same in order to free + // up an iterator for the tangent space view vector + HALF2 detailTexCoord = i.baseTexCoord.xy; + HALF2 bumpmapTexCoord = i.baseTexCoord.xy; + HALF2 envmapMaskTexCoord = i.baseTexCoord.xy; +#else + + #if ( DETAILTEXTURE == 1 ) + HALF2 detailTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.xy; + HALF2 bumpmapTexCoord = i.baseTexCoord.xy; + #elif ( BUMPMASK == 1 ) + HALF2 detailTexCoord = 0.0f; + HALF2 bumpmapTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.xy; + HALF2 bumpmap2TexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.wz; + #else + HALF2 detailTexCoord = 0.0f; + HALF2 bumpmapTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.xy; + #endif + + HALF2 envmapMaskTexCoord = i.detailOrBumpAndEnvmapMaskTexCoord.wz; +#endif // !RELIEF_MAPPING + + HALF4 detailColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); +#if DETAILTEXTURE + +#if SHADER_MODEL_PS_2_0 + detailColor = tex2D( DetailSampler, detailTexCoord ); +#else + detailColor = float4( g_DetailTint, 1.0f ) * tex2D( DetailSampler, detailTexCoord ); +#endif + +#endif + +#if ( OUTLINE || SOFTEDGES ) + float distAlphaMask = baseColor.a; + +# if OUTLINE + if ( ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && + ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) ) + { + float oFactor=1.0; + if ( distAlphaMask <= OUTLINE_MIN_VALUE1 ) + { + oFactor=smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask ); + } + else + { + oFactor=smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask ); + } + baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor ); + } +# endif +# if SOFTEDGES + baseColor.a *= smoothstep( SOFT_MASK_MAX, SOFT_MASK_MIN, distAlphaMask ); +# else + baseColor.a *= distAlphaMask >= 0.5; +# endif +#endif + + +#if LIGHTING_PREVIEW == 2 + baseColor.xyz=GammaToLinear(baseColor.xyz); +#endif + + float blendedAlpha = baseColor.a; + +#if MASKEDBLENDING + float blendfactor=0.5; +#else + float blendfactor=i.vertexBlendX_fogFactorW.r; +#endif + + if( bBaseTexture2 ) + { +#if (SELFILLUM == 0) && (PIXELFOGTYPE != PIXEL_FOG_TYPE_HEIGHT) && (FANCY_BLENDING) + float4 modt=tex2D(BlendModulationSampler,i.lightmapTexCoord3.zw); +#if MASKEDBLENDING + // FXC is unable to optimize this, despite blendfactor=0.5 above + //float minb=modt.g-modt.r; + //float maxb=modt.g+modt.r; + //blendfactor=smoothstep(minb,maxb,blendfactor); + blendfactor=modt.g; +#else + float minb=saturate(modt.g-modt.r); + float maxb=saturate(modt.g+modt.r); + blendfactor=smoothstep(minb,maxb,blendfactor); +#endif +#endif + baseColor.rgb = lerp( baseColor, baseColor2.rgb, blendfactor ); + blendedAlpha = lerp( baseColor.a, baseColor2.a, blendfactor ); + } + + HALF3 specularFactor = 1.0f; + float4 vNormalMask = float4(0, 0, 1, 1); + if( bBumpmap ) + { + if( bBaseTextureNoEnvmap ) + { + vNormal.a = 0.0f; + } + +#if ( BUMPMAP2 == 1 ) + { + #if ( BUMPMASK == 1 ) + HALF2 b2TexCoord = bumpmap2TexCoord; + #else + HALF2 b2TexCoord = bumpmapTexCoord; + #endif + + HALF4 vNormal2; + if ( BUMPMAP == 2 ) + vNormal2 = tex2D( BumpmapSampler2, b2TexCoord ); + else + vNormal2 = DecompressNormal( BumpmapSampler2, b2TexCoord, NORMAL_DECODE_MODE, AlphaMapSampler2 ); // Bump 2 coords + + if( bBaseTexture2NoEnvmap ) + { + vNormal2.a = 0.0f; + } + + #if ( BUMPMASK == 1 ) + float3 vNormal1 = DecompressNormal( BumpmapSampler, i.detailOrBumpAndEnvmapMaskTexCoord.xy, NORMALMASK_DECODE_MODE, AlphaMapSampler ); + + vNormal.xyz = normalize( vNormal1.xyz + vNormal2.xyz ); + + // Third normal map...same coords as base + vNormalMask = DecompressNormal( BumpMaskSampler, i.baseTexCoord.xy, NORMALMASK_DECODE_MODE, AlphaMaskSampler ); + + vNormal.xyz = lerp( vNormalMask.xyz, vNormal.xyz, vNormalMask.a ); // Mask out normals from vNormal + specularFactor = vNormalMask.a; + #else // BUMPMASK == 0 + if ( FANCY_BLENDING && bNormalMapAlphaEnvmapMask ) + { + vNormal = lerp( vNormal, vNormal2, blendfactor); + } + else + { + vNormal.xyz = lerp( vNormal.xyz, vNormal2.xyz, blendfactor); + } + + #endif + + } + +#endif // BUMPMAP2 == 1 + + if( bNormalMapAlphaEnvmapMask ) + { + specularFactor *= vNormal.a; + } + } + else if ( bNormalMapAlphaEnvmapMask ) + { + specularFactor *= vNormal.a; + } + +#if ( BUMPMAP2 == 0 ) + if( bEnvmapMask ) + { + specularFactor *= tex2D( EnvmapMaskSampler, envmapMaskTexCoord ).xyz; + } +#endif + + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - blendedAlpha; // Reversing alpha blows! + } + float4 albedo = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + float alpha = 1.0f; + albedo *= baseColor; + if( !bBaseAlphaEnvmapMask && !bSelfIllum ) + { + alpha *= baseColor.a; + } + + if( bDetailTexture ) + { + albedo = TextureCombine( albedo, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); + } + + // The vertex color contains the modulation color + vertex color combined +#if ( SEAMLESS == 0 ) + albedo.xyz *= i.vertexColor; +#endif + alpha *= i.vertexColor.a * g_flAlpha2; // not sure about this one + + // Save this off for single-pass flashlight, since we'll still need the SSBump vector, not a real normal + float3 vSSBumpVector = vNormal.xyz; + + HALF3 diffuseLighting; + if( bBumpmap && bDiffuseBumpmap ) + { + +// ssbump +#if ( BUMPMAP == 2 ) + diffuseLighting = vNormal.x * lightmapColor1 + + vNormal.y * lightmapColor2 + + vNormal.z * lightmapColor3; + diffuseLighting *= g_TintValuesAndLightmapScale.rgb; + + // now, calculate vNormal for reflection purposes. if vNormal isn't needed, hopefully + // the compiler will eliminate these calculations + vNormal.xyz = normalize( bumpBasis[0]*vNormal.x + bumpBasis[1]*vNormal.y + bumpBasis[2]*vNormal.z); +#else + float3 dp; + dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); + dp *= dp; + +#if ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP ) + dp *= 2*detailColor; +#endif + diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= g_TintValuesAndLightmapScale.rgb / sum; +#endif + } + else + { + diffuseLighting = lightmapColor1 * g_TintValuesAndLightmapScale.rgb; + } + +#if WARPLIGHTING && ( SEAMLESS == 0 ) + float len=0.5*length(diffuseLighting); + // FIXME: 8-bit lookup textures like this need a "nice filtering" VTF option, which converts + // them to 16-bit on load or does filtering in the shader (since most hardware - 360 + // included - interpolates 8-bit textures at 8-bit precision, which causes banding) + diffuseLighting *= 2.0*tex2D(WarpLightingSampler,float2(len,0)); +#endif + +#if CUBEMAP || LIGHTING_PREVIEW || ( defined( _X360 ) && FLASHLIGHT ) + float3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); +#endif + + float3 diffuseComponent = albedo.xyz * diffuseLighting; + +#if defined( _X360 ) && FLASHLIGHT + + // ssbump doesn't pass a normal to the flashlight...it computes shadowing a different way +#if ( BUMPMAP == 2 ) + bool bHasNormal = false; + + float3 worldPosToLightVector = g_FlashlightPos - i.worldPos_projPosZ.xyz; + + float3 tangentPosToLightVector; + tangentPosToLightVector.x = dot( worldPosToLightVector, i.tangentSpaceTranspose[0] ); + tangentPosToLightVector.y = dot( worldPosToLightVector, i.tangentSpaceTranspose[1] ); + tangentPosToLightVector.z = dot( worldPosToLightVector, i.tangentSpaceTranspose[2] ); + + tangentPosToLightVector = normalize( tangentPosToLightVector ); + + float nDotL = saturate( vSSBumpVector.x*dot( tangentPosToLightVector, bumpBasis[0]) + + vSSBumpVector.y*dot( tangentPosToLightVector, bumpBasis[1]) + + vSSBumpVector.z*dot( tangentPosToLightVector, bumpBasis[2]) ); +#else + bool bHasNormal = true; + float nDotL = 1.0f; +#endif + + float fFlashlight = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, i.flashlightSpacePos, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, 0, true, false, i.vProjPos.xy / i.vProjPos.w, false, g_ShadowTweaks, bHasNormal ); + + diffuseComponent = albedo.xyz * ( diffuseLighting + ( fFlashlight * nDotL ) ); +#endif + + if( bSelfIllum ) + { + float3 selfIllumComponent = g_SelfIllumTint * albedo.xyz; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); +#if CUBEMAP + if( bCubemap ) + { + float3 worldVertToEyeVector = g_EyePos - i.worldPos_projPosZ.xyz; + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldVertToEyeVector ); + + // Calc Fresnel factor + half3 eyeVect = normalize(worldVertToEyeVector); + HALF fresnel = 1.0 - dot( worldSpaceNormal, eyeVect ); + fresnel = pow( fresnel, 5.0 ); + fresnel = fresnel * g_OneMinusFresnelReflection + g_FresnelReflection; + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + + specularLighting *= g_EnvmapTint; +#if FANCY_BLENDING == 0 + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); +#endif + specularLighting *= fresnel; + } +#endif + + HALF3 result = diffuseComponent + specularLighting; + +#if LIGHTING_PREVIEW + worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose ); +# if LIGHTING_PREVIEW == 1 + float dotprod = 0.7+0.25 * dot( worldSpaceNormal, normalize( float3( 1, 2, -.5 ) ) ); + return FinalOutput( HALF4( dotprod*albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +# else + LPREVIEW_PS_OUT ret; + ret.color = float4( albedo.xyz,alpha ); + ret.normal = float4( worldSpaceNormal,alpha ); + ret.position = float4( i.worldPos_projPosZ.xyz, alpha ); + ret.flags = float4( 1, 1, 1, alpha ); + + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +# endif +#else // == end LIGHTING_PREVIEW == + + bool bWriteDepthToAlpha = false; + + // ps_2_b and beyond +#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) + bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w ); + +#endif +} + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc new file mode 100644 index 00000000..599d16a4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_ps2x.fxc @@ -0,0 +1,59 @@ +// STATIC: "MASKEDBLENDING" "0..1" +// STATIC: "BASETEXTURE2" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "BUMPMAP" "0..2" +// STATIC: "BUMPMAP2" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "BASETEXTURENOENVMAP" "0..1" +// STATIC: "BASETEXTURE2NOENVMAP" "0..1" +// STATIC: "WARPLIGHTING" "0..1" +// STATIC: "FANCY_BLENDING" "0..1" +// STATIC: "RELIEF_MAPPING" "0..0" [ps20b] +// STATIC: "SEAMLESS" "0..1" +// STATIC: "OUTLINE" "0..1" +// STATIC: "SOFTEDGES" "0..1" +// STATIC: "BUMPMASK" "0..1" +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] +// STATIC: "NORMALMASK_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMALMASK_DECODE_MODE" "0..0" [PC] +// STATIC: "DETAIL_BLEND_MODE" "0..11" +// STATIC: "FLASHLIGHT" "0..1" [ps20b] [XBOX] + +// DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1" +// DYNAMIC: "FASTPATH" "0..1" +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..2" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $SEAMLESS && $RELIEF_MAPPING [ps20b] + +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// SKIP: $SEAMLESS && ( $OUTLINE || $SOFTEDGES) +// SKIP: $BASETEXTURE2 && ( $OUTLINE || $SOFTEDGES) +// SKIP: $BUMPMAP2 && ( $OUTLINE || $SOFTEDGES) +// SKIP: $SELFILLUM && ( $OUTLINE || $SOFTEDGES) +// SKIP: $MASKEDBLENDING && ( $OUTLINE || $SOFTEDGES) +// SKIP: $FANCY_BLENDING && ( $OUTLINE || $SOFTEDGES) +// SKIP: $LIGHTING_PREVIEW && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($FASTPATH == 0) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($DETAILTEXTURE && $BUMPMAP) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($WARPLIGHTING) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($BUMPMAP) && ( $OUTLINE || $SOFTEDGES) +// SKIP: ($DETAIL_BLEND_MODE == 2 ) || ($DETAIL_BLEND_MODE == 3 ) || ($DETAIL_BLEND_MODE == 4 ) +// SKIP: ($DETAIL_BLEND_MODE == 5 ) || ($DETAIL_BLEND_MODE == 6 ) || ($DETAIL_BLEND_MODE == 7 ) +// SKIP: ($DETAIL_BLEND_MODE == 8 ) || ($DETAIL_BLEND_MODE == 9 ) +// SKIP ($DETAIL_BLEND_MODE == 10 ) && ($BUMPMAP == 0 ) +// SKIP ($DETAIL_BLEND_MODE == 11 ) && ($BUMPMAP != 0 ) + +#include "lightmappedgeneric_ps2_3_x.h" + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedenvmap.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedenvmap.psh new file mode 100644 index 00000000..84b56437 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedenvmap.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 + +mul r0.rgb, t0, v0 + ; base times vertex color (no alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mad r0.rgb, t2, c2, r0 ; + envmap * envmaptint (color only) + +mul r0.rgb, t1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedmaskedenvmap.psh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedmaskedenvmap.psh new file mode 100644 index 00000000..b4893363 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_selfilluminatedmaskedenvmap.psh @@ -0,0 +1,27 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; c1 - self-illum tint +; c2 - envmap tint +;------------------------------------------------------------------------------ + +tex t0 +tex t1 +tex t2 +tex t3 + +mul r0.rgb, t0, v0 + ; base times vertex color (with alpha) +mov r0.a, v0.a ; Grab alpha from vertex color + +mul r1, t2, t3 ; envmap * envmapmask +mad r0.rgb, r1, c2, r0 ; + envmap * envmapmask * envmaptint (color only) + +mul r1, c1, t0.a ; Self illum alpha * tint +mad r1, t0, r1, t1 ; Self illum * tint + lightmap +mul r0.rgb, r1, r0 ; fold in lighting (color only) +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_vs11.vsh b/sp/src/materialsystem/stdshaders/lightmappedgeneric_vs11.vsh new file mode 100644 index 00000000..cc1dd1f8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_vs11.vsh @@ -0,0 +1,20 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# STATIC: "DETAIL" "0..1" +# STATIC: "ENVMAP" "0..1" +# STATIC: "ENVMAPCAMERASPACE" "0..0" +# STATIC: "ENVMAPSPHERE" "0..1" +# STATIC: "VERTEXCOLOR" "0..1" + +# can't have envmapshere or envmapcameraspace without envmap +# SKIP: !$ENVMAP && ( $ENVMAPSPHERE || $ENVMAPCAMERASPACE ) + +# can't have both envmapsphere and envmapcameraspace +# SKIP: $ENVMAPSPHERE && $ENVMAPCAMERASPACE + +#include "LightmappedGeneric_inc.vsh" + +&LightmappedGeneric( $DETAIL, $ENVMAP, $ENVMAPCAMERASPACE, $ENVMAPSPHERE, + $VERTEXCOLOR ); + diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc b/sp/src/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc new file mode 100644 index 00000000..362eb668 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_vs20.fxc @@ -0,0 +1,254 @@ +// STATIC: "ENVMAP_MASK" "0..1" +// STATIC: "TANGENTSPACE" "0..1" +// STATIC: "BUMPMAP" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "VERTEXALPHATEXBLENDFACTOR" "0..1" +// STATIC: "RELIEF_MAPPING" "0..0" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "BUMPMASK" "0..1" +// STATIC: "FLASHLIGHT" "0..1" [XBOX] + +// DYNAMIC: "FASTPATH" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] + +// This should not be a combo since I'm a moron with the tangent space and the flashlight. +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: $SEAMLESS && $RELIEF_MAPPING +// SKIP: $BUMPMASK && $RELIEF_MAPPING +// SKIP: $BUMPMASK && $SEAMLESS + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_UseSeparateEnvmapMask = ENVMAP_MASK; +static const bool g_bTangentSpace = TANGENTSPACE; +static const bool g_bBumpmap = BUMPMAP; +static const bool g_bBumpmapDiffuseLighting = DIFFUSEBUMPMAP; +static const bool g_bVertexColor = VERTEXCOLOR; +static const bool g_bVertexAlphaTexBlendFactor = VERTEXALPHATEXBLENDFACTOR; +static const bool g_BumpMask = BUMPMASK; + +#if SEAMLESS +const float4 SeamlessScale : register( SHADER_SPECIFIC_CONST_0 ); +#define SEAMLESS_SCALE (SeamlessScale.x) +#else +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailOrBumpTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); +#endif +// This should be identity if we are bump mapping, otherwise we'll screw up the lightmapTexCoordOffset. +const float4 cEnvmapMaskTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cBlendMaskTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_10 ); // not contiguous with the rest! + +struct VS_INPUT +{ + float3 vPos : POSITION; + float4 vNormal : NORMAL; + float2 vBaseTexCoord : TEXCOORD0; + float2 vLightmapTexCoord : TEXCOORD1; + float2 vLightmapTexCoordOffset : TEXCOORD2; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + +#if SEAMLESS + float3 SeamlessTexCoord : TEXCOORD0; // x y z + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; // envmap mask +#else + float2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. +#if RELIEF_MAPPING + float3 TangentSpaceViewRay : TEXCOORD1; +#else + float4 detailOrBumpAndEnvmapMaskTexCoord : TEXCOORD1; +#endif +#endif + float4 lightmapTexCoord1And2 : TEXCOORD2; + float4 lightmapTexCoord3 : TEXCOORD3; // and basetexcoord*mask_scale + float4 worldPos_projPosZ : TEXCOORD4; + +#if TANGENTSPACE || (LIGHTING_PREVIEW) || defined( _X360 ) + float3x3 tangentSpaceTranspose : TEXCOORD5; // and 6 and 7 +#endif + + float4 vertexColor : COLOR; // in seamless, r g b = blend weights + float4 vertexBlendX_fogFactorW : COLOR1; + + // Extra iterators on 360, used in flashlight combo +#if defined( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; + float4 vProjPos : TEXCOORD9; +#endif +#endif + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 vObjNormal; + DecompressVertex_Normal( v.vNormal, vObjNormal ); + + float3 worldPos = mul( float4( v.vPos, 1 ), cModel[0] ); + + float4 vProjPos = mul( float4( v.vPos, 1 ), cModelViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( v.vPos, 1 ), cModelViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos, vProjPos.z ); + + float3 worldNormal = mul( vObjNormal, ( float3x3 )cModel[0] ); + +#if TANGENTSPACE || (LIGHTING_PREVIEW) || defined( _X360 ) + float3 worldTangentS = mul( v.vTangentS, ( const float3x3 )cModel[0] ); + float3 worldTangentT = mul( v.vTangentT, ( const float3x3 )cModel[0] ); + + #if SEAMLESS && BUMPMAP && defined( _X360 ) + float3 n = normalize( worldNormal ); + float3 n2 = n * n; // sums to 1. + + o.tangentSpaceTranspose[0] = normalize( float3( n2.y + n2.z, 0.0f, n2.x ) ); + o.tangentSpaceTranspose[1] = normalize( float3( 0.0f, n2.x + n2.z, n2.y ) ); + o.tangentSpaceTranspose[2] = worldNormal; + #else + o.tangentSpaceTranspose[0] = worldTangentS; + o.tangentSpaceTranspose[1] = worldTangentT; + o.tangentSpaceTranspose[2] = worldNormal; + #endif + +#endif + + float3 worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + +#if SEAMLESS + { + // we need to fill in the texture coordinate projections + o.SeamlessTexCoord = SEAMLESS_SCALE*worldPos; + } +#else + { + if (FASTPATH) + { + o.baseTexCoord.xy = v.vBaseTexCoord; + } + else + { + o.baseTexCoord.x = dot( v.vBaseTexCoord, cBaseTexCoordTransform[0] ) + cBaseTexCoordTransform[0].w; + o.baseTexCoord.y = dot( v.vBaseTexCoord, cBaseTexCoordTransform[1] ) + cBaseTexCoordTransform[1].w; + } +#if ( RELIEF_MAPPING == 0 ) + { + // calculate detailorbumptexcoord + if ( FASTPATH ) + o.detailOrBumpAndEnvmapMaskTexCoord.xy = v.vBaseTexCoord.xy; + else + { + o.detailOrBumpAndEnvmapMaskTexCoord.x = dot( v.vBaseTexCoord, cDetailOrBumpTexCoordTransform[0] ) + cDetailOrBumpTexCoordTransform[0].w; + o.detailOrBumpAndEnvmapMaskTexCoord.y = dot( v.vBaseTexCoord, cDetailOrBumpTexCoordTransform[1] ) + cDetailOrBumpTexCoordTransform[1].w; + } + } +#endif + } +#endif + if ( FASTPATH ) + { + o.lightmapTexCoord3.zw = v.vBaseTexCoord; + } + else + { + o.lightmapTexCoord3.z = dot( v.vBaseTexCoord, cBlendMaskTexCoordTransform[0] ) + cBlendMaskTexCoordTransform[0].w; + o.lightmapTexCoord3.w = dot( v.vBaseTexCoord, cBlendMaskTexCoordTransform[1] ) + cBlendMaskTexCoordTransform[1].w; + } + + // compute lightmap coordinates + if( g_bBumpmap && g_bBumpmapDiffuseLighting ) + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + } + else + { + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord; + } + +#if ( RELIEF_MAPPING == 0) + if( g_UseSeparateEnvmapMask || g_BumpMask ) + { + // reversed component order +# if FASTPATH + o.detailOrBumpAndEnvmapMaskTexCoord.wz = v.vBaseTexCoord.xy; +# else + o.detailOrBumpAndEnvmapMaskTexCoord.w = dot( v.vBaseTexCoord, cEnvmapMaskTexCoordTransform[0] ) + cEnvmapMaskTexCoordTransform[0].w; + o.detailOrBumpAndEnvmapMaskTexCoord.z = dot( v.vBaseTexCoord, cEnvmapMaskTexCoordTransform[1] ) + cEnvmapMaskTexCoordTransform[1].w; +# endif + } +#endif + + o.vertexBlendX_fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.vertexBlendX_fogFactorW; +#endif + + if (!g_bVertexColor) + { + o.vertexColor = float4( 1.0f, 1.0f, 1.0f, cModulationColor.a ); + } + else + { +#if FASTPATH + o.vertexColor = v.vColor; +#else + if ( g_bVertexAlphaTexBlendFactor ) + { + o.vertexColor.rgb = v.vColor.rgb; + o.vertexColor.a = cModulationColor.a; + } + else + { + o.vertexColor = v.vColor; + o.vertexColor.a *= cModulationColor.a; + } +#endif + } +#if SEAMLESS + // compute belnd weights in rgb + float3 vNormal=normalize( worldNormal ); + o.vertexColor.xyz = vNormal * vNormal; // sums to 1. +#endif + +// On 360, we have extra iterators and can fold the flashlight into this shader +#if defined( _X360 ) + #if FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); + o.vProjPos = vProjPos; + #endif +#endif + + if ( g_bVertexAlphaTexBlendFactor ) + { + o.vertexBlendX_fogFactorW.r = v.vColor.a; + } + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/refract.cpp b/sp/src/materialsystem/stdshaders/refract.cpp new file mode 100644 index 00000000..852e93a5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/refract.cpp @@ -0,0 +1,111 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" +#include "refract_dx9_helper.h" + +DEFINE_FALLBACK_SHADER( Refract, Refract_DX90 ) + +BEGIN_VS_SHADER( Refract_DX90, "Help for Refract" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( NORMALMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $normalmap" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $normalmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$normalmap texcoord transform" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$normalmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0f", "" ) + SHADER_PARAM( BLURAMOUNT, SHADER_PARAM_TYPE_INTEGER, "1", "0, 1, or 2 for how much blur you want" ) + SHADER_PARAM( FADEOUTONSILHOUETTE, SHADER_PARAM_TYPE_BOOL, "1", "0 for no fade out on silhouette, 1 for fade out on sillhouette" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( REFRACTTINTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shield", "" ) + SHADER_PARAM( REFRACTTINTTEXTUREFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NOWRITEZ, SHADER_PARAM_TYPE_INTEGER, "0", "0 == write z, 1 = no write z" ) + SHADER_PARAM( MASKED, SHADER_PARAM_TYPE_BOOL, "0", "mask using dest alpha" ) + SHADER_PARAM( VERTEXCOLORMODULATE, SHADER_PARAM_TYPE_BOOL, "0","Use the vertex color to effect refract color. alpha will adjust refract amount" ) + SHADER_PARAM( FORCEALPHAWRITE, SHADER_PARAM_TYPE_BOOL, "0","Force the material to write alpha to the dest buffer" ) + END_SHADER_PARAMS +// FIXME: doesn't support Fresnel! + + void SetupVars( Refract_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nFrame = FRAME; + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nRefractTint = REFRACTTINT; + info.m_nNormalMap = NORMALMAP; + info.m_nNormalMap2 = NORMALMAP2; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBlurAmount = BLURAMOUNT; + info.m_nFadeOutOnSilhouette = FADEOUTONSILHOUETTE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nRefractTintTexture = REFRACTTINTTEXTURE; + info.m_nRefractTintTextureFrame = REFRACTTINTTEXTUREFRAME; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoWriteZ = NOWRITEZ; + info.m_nMasked = MASKED; + info.m_nVertexColorModulate = VERTEXCOLORMODULATE; + info.m_nForceAlphaWrite = FORCEALPHAWRITE; + } + + SHADER_INIT_PARAMS() + { + Refract_DX9_Vars_t info; + SetupVars( info ); + InitParamsRefract_DX9( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 82 ) + return "Refract_DX80"; + + return 0; + } + + SHADER_INIT + { + Refract_DX9_Vars_t info; + SetupVars( info ); + InitRefract_DX9( this, params, info ); + } + + SHADER_DRAW + { + Refract_DX9_Vars_t info; + SetupVars( info ); + + // If ( snapshotting ) or ( we need to draw this frame ) + bool bHasFlashlight = this->UsingFlashlight( params ); + if ( ( pShaderShadow != NULL ) || ( bHasFlashlight == false ) ) + { + DrawRefract_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + Draw( false ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/refract_dx60.cpp b/sp/src/materialsystem/stdshaders/refract_dx60.cpp new file mode 100644 index 00000000..2ca7a83c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/refract_dx60.cpp @@ -0,0 +1,16 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// FIXME: This is a placeholder. . need to do something for real here. +DEFINE_FALLBACK_SHADER( Refract, Refract_DX60 ) +DEFINE_FALLBACK_SHADER( Refract_DX60, UnlitGeneric ) + + diff --git a/sp/src/materialsystem/stdshaders/refract_dx80.cpp b/sp/src/materialsystem/stdshaders/refract_dx80.cpp new file mode 100644 index 00000000..b6e6e5a0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/refract_dx80.cpp @@ -0,0 +1,317 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + + +#include "BaseVSShader.h" + +#include "refract_model_vs11.inc" +#include "refract_world_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define MAXBLUR 1 + +DEFINE_FALLBACK_SHADER( Refract, Refract_DX80 ) + +BEGIN_VS_SHADER( Refract_DX80, + "Help for Refract_DX80" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_COLOR, "{255 255 255}", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( DUDVMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_dudv", "dudv bump map" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( DUDVFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $dudvmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0f", "" ) + SHADER_PARAM( BLURAMOUNT, SHADER_PARAM_TYPE_INTEGER, "1", "0, 1, or 2 for how much blur you want" ) + SHADER_PARAM( FADEOUTONSILHOUETTE, SHADER_PARAM_TYPE_BOOL, "1", "0 for no fade out on silhouette, 1 for fade out on sillhouette" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( REFRACTTINTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shield", "" ) + SHADER_PARAM( REFRACTTINTTEXTUREFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( FALLBACK, SHADER_PARAM_TYPE_STRING, "", "Name of the fallback shader" ) + SHADER_PARAM( FORCEREFRACT, SHADER_PARAM_TYPE_BOOL, "0", "Forces refraction on boards that have poor performance" ) + SHADER_PARAM( NOWRITEZ, SHADER_PARAM_TYPE_INTEGER, "0", "0 == write z, 1 = no write z" ) + SHADER_PARAM( MASKED, SHADER_PARAM_TYPE_BOOL, "0", "mask using dest alpha" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + if( !params[MASKED]->IsDefined() ) + { + params[MASKED]->SetIntValue( 0 ); + } + if( !params[BLURAMOUNT]->IsDefined() ) + { + params[BLURAMOUNT]->SetIntValue( 0 ); + } + if( !params[FADEOUTONSILHOUETTE]->IsDefined() ) + { + params[FADEOUTONSILHOUETTE]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + SHADER_FALLBACK + { + if ( IsPC() ) + { + const char *pFallback = (params && params[FALLBACK]->IsDefined()) ? params[FALLBACK]->GetStringValue() : ""; + if (!pFallback[0]) + { + pFallback = "Refract_DX60"; + } + + if( g_pHardwareConfig->GetDXSupportLevel() < 80 || !g_pHardwareConfig->HasProjectedBumpEnv() ) + return pFallback; + + if ( g_pHardwareConfig->PreferReducedFillrate() && (params && (params[FORCEREFRACT]->GetIntValue() == 0)) ) + return pFallback; + } + + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE ); + } + if (params[DUDVMAP]->IsDefined() ) + { + LoadTexture( DUDVMAP ); + } + if (params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + if( params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP ); + } + if( params[REFRACTTINTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTINTTEXTURE ); + } + } + + inline int ComputePixelShaderIndex( bool bRefractTintTexture, bool bNormalMapAlpha ) + { + // "REFRACTTINTTEXTURE" "0..1" + // "NORMALMAPALPHA" "0..1" + int pshIndex = 0; + if( bRefractTintTexture ) pshIndex |= 0x1; + if( bNormalMapAlpha ) pshIndex |= 0x2; + return pshIndex; + } + + SHADER_DRAW + { + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasEnvmap = params[ENVMAP]->IsTexture(); + int blurAmount = params[BLURAMOUNT]->GetIntValue(); + bool bRefractTintTexture = params[REFRACTTINTTEXTURE]->IsTexture(); + if( blurAmount < 0 ) + { + blurAmount = 0; + } + else if( blurAmount > MAXBLUR ) + { + blurAmount = MAXBLUR; + } + bool bMasked = (params[MASKED]->GetIntValue() != 0); + + SHADOW_STATE + { + if ( params[NOWRITEZ]->GetIntValue() != 0 ) + { + pShaderShadow->EnableDepthWrites( false ); + } + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // If envmap is not specified, the alpha channel is the translucency + // (If envmap *is* specified, alpha channel is the reflection amount) + bool bNormalMapAlpha = false; + if ( params[NORMALMAP]->IsTexture() && !bHasEnvmap ) + { + SetDefaultBlendingShadowState( NORMALMAP, false ); + if ( !bMasked && TextureIsTranslucent( NORMALMAP, false ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + bNormalMapAlpha = true; + } + } + + // dudv map + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // renderable texture for refraction + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + if( bRefractTintTexture ) + { + // refract tint texture + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + if( bIsModel ) + { + userDataSize = 4; + } + else + { + fmt |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, userDataSize ); + + if( bIsModel ) + { + refract_model_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Refract_model_vs11", vshIndex.GetIndex() ); + } + else + { + refract_world_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Refract_world_vs11", vshIndex.GetIndex() ); + } + + int pshIndex; + pshIndex = ComputePixelShaderIndex( bRefractTintTexture, bNormalMapAlpha ); + pShaderShadow->SetPixelShader( "Refract_ps11", pshIndex ); + + if( bMasked ) + { + EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + } + DefaultFog(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + + if ( params[DUDVFRAME]->GetIntValue() == 0 ) + { + BindTexture( SHADER_SAMPLER0, DUDVMAP, BUMPFRAME ); + } + else + { + BindTexture( SHADER_SAMPLER0, DUDVMAP, DUDVFRAME ); + } + + if ( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + } + + if( bRefractTintTexture ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTINTTEXTURE, REFRACTTINTTEXTUREFRAME ); + } + + if ( params[NORMALMAP]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER3, NORMALMAP, BUMPFRAME ); + } + + float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + // used to invert y + // xboxfixme - move this into defined constants + float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFRACTTINT ); + if( bIsModel ) + { + refract_model_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + refract_world_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + + Draw(); + + if( bHasEnvmap ) + { + bool bNoWriteZ = (params[NOWRITEZ]->GetIntValue() != 0); + const bool bBlendSpecular = true; + if( bIsModel ) + { + DrawModelBumpedSpecularLighting( NORMALMAP, BUMPFRAME, + ENVMAP, ENVMAPFRAME, + ENVMAPTINT, ALPHA, + ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, + bBlendSpecular, bNoWriteZ ); + } + else + { + DrawWorldBumpedSpecularLighting( NORMALMAP, ENVMAP, + BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, + ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + bBlendSpecular, bNoWriteZ ); + } + } + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/refract_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/refract_dx9_helper.cpp new file mode 100644 index 00000000..f436e62a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/refract_dx9_helper.cpp @@ -0,0 +1,342 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "refract_dx9_helper.h" +#include "convar.h" +#include "Refract_vs20.inc" +#include "Refract_ps20.inc" +#include "Refract_ps20b.inc" +#include "cpp_shader_constant_register_map.h" + +#define MAXBLUR 1 + +// FIXME: doesn't support fresnel! +void InitParamsRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, Refract_DX9_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + if( !params[info.m_nEnvmapTint]->IsDefined() ) + { + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + if( !params[info.m_nEnvmapContrast]->IsDefined() ) + { + params[info.m_nEnvmapContrast]->SetFloatValue( 0.0f ); + } + if( !params[info.m_nEnvmapSaturation]->IsDefined() ) + { + params[info.m_nEnvmapSaturation]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nEnvmapFrame]->IsDefined() ) + { + params[info.m_nEnvmapFrame]->SetIntValue( 0 ); + } + if( !params[info.m_nFresnelReflection]->IsDefined() ) + { + params[info.m_nFresnelReflection]->SetFloatValue( 1.0f ); + } + if( !params[info.m_nMasked]->IsDefined() ) + { + params[info.m_nMasked]->SetIntValue( 0 ); + } + if( !params[info.m_nBlurAmount]->IsDefined() ) + { + params[info.m_nBlurAmount]->SetIntValue( 0 ); + } + if( !params[info.m_nFadeOutOnSilhouette]->IsDefined() ) + { + params[info.m_nFadeOutOnSilhouette]->SetIntValue( 0 ); + } + if( !params[info.m_nForceAlphaWrite]->IsDefined() ) + { + params[info.m_nForceAlphaWrite]->SetIntValue( 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); +} + +void InitRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, Refract_DX9_Vars_t &info ) +{ + if (params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + } + if (params[info.m_nNormalMap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap ); + } + if (params[info.m_nNormalMap2]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nNormalMap2 ); + } + if( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap, TEXTUREFLAGS_SRGB ); + } + if( params[info.m_nRefractTintTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nRefractTintTexture, TEXTUREFLAGS_SRGB ); + } +} + +void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) +{ + bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); + bool bHasEnvmap = params[info.m_nEnvmap]->IsTexture(); + bool bRefractTintTexture = params[info.m_nRefractTintTexture]->IsTexture(); + bool bFadeOutOnSilhouette = params[info.m_nFadeOutOnSilhouette]->GetIntValue() != 0; + int blurAmount = params[info.m_nBlurAmount]->GetIntValue(); + bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0); + bool bSecondaryNormal = ( ( info.m_nNormalMap2 != -1 ) && ( params[info.m_nNormalMap2]->IsTexture() ) ); + bool bColorModulate = ( ( info.m_nVertexColorModulate != -1 ) && ( params[info.m_nVertexColorModulate]->GetIntValue() ) ); + bool bWriteZ = params[info.m_nNoWriteZ]->GetIntValue() == 0; + + if( blurAmount < 0 ) + { + blurAmount = 0; + } + else if( blurAmount > MAXBLUR ) + { + blurAmount = MAXBLUR; + } + + BlendType_t nBlendType = pShader->EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + bFullyOpaque &= !bMasked; + + bool bTranslucentNormal = pShader->TextureIsTranslucent( info.m_nNormalMap, false ); + bFullyOpaque &= (! bTranslucentNormal ); + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( g_pHardwareConfig->SupportsNormalMapCompression() ) + { + ITexture *pBumpTex = params[info.m_nNormalMap]->GetTextureValue(); + if ( pBumpTex ) + { + nNormalDecodeMode = pBumpTex->GetNormalDecodeMode(); + + if ( bSecondaryNormal ) // Check encoding of secondary normal if there is one + { + ITexture *pBumpTex2 = params[info.m_nNormalMap2]->GetTextureValue(); + if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) ) + { + DevMsg("Refract: Primary and Secondary normal map compression formats don't match. This is unsupported!\n"); + Assert(0); + } + } + } + } + + SHADOW_STATE + { + pShader->SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( bWriteZ ); + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // If envmap is not specified, the alpha channel is the translucency + // (If envmap *is* specified, alpha channel is the reflection amount) + if ( params[info.m_nNormalMap]->IsTexture() && !bHasEnvmap ) + { + pShader->SetDefaultBlendingShadowState( info.m_nNormalMap, false ); + } + + // source render target that contains the image that we are warping. + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Normal map alpha, in the compressed normal case + } + + if ( bSecondaryNormal ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Secondary normal map alpha, in the compressed normal case + } + } + + if( bHasEnvmap ) + { + // envmap + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); + } + if( bRefractTintTexture ) + { + // refract tint texture + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); + } + + pShaderShadow->EnableSRGBWrite( true ); + + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + int userDataSize = 0; + int nTexCoordCount = 1; + if( bIsModel ) + { + userDataSize = 4; + } + else + { + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; + } + + if ( bColorModulate ) + { + flags |= VERTEX_COLOR; + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + DECLARE_STATIC_VERTEX_SHADER( refract_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); + SET_STATIC_VERTEX_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_VERTEX_SHADER( refract_vs20 ); + + // We have to do this in the shader on R500 or Leopard + bool bShaderSRGBConvert = IsOSX() && ( g_pHardwareConfig->FakeSRGBWrite() || !g_pHardwareConfig->CanDoSRGBReadFromRTs() ); + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send OpenGL down the ps2b path + { + DECLARE_STATIC_PIXEL_SHADER( refract_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); + SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSRGBConvert ); + SET_STATIC_PIXEL_SHADER( refract_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( refract_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); + SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); + SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( refract_ps20 ); + } + pShader->DefaultFog(); + if( bMasked ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + } + + bool bAlphaWrites = bFullyOpaque || ( params[ info.m_nForceAlphaWrite ]->GetIntValue() != 0 ); + pShaderShadow->EnableAlphaWrites( bAlphaWrites ); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + if ( params[info.m_nBaseTexture]->IsTexture() ) + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture, info.m_nFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); + } + + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShader->BindTexture( SHADER_SAMPLER3, SHADER_SAMPLER6, info.m_nNormalMap, info.m_nBumpFrame ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame ); + } + + if ( bSecondaryNormal ) + { + if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) + { + pShader->BindTexture( SHADER_SAMPLER1, SHADER_SAMPLER7, info.m_nNormalMap2, info.m_nBumpFrame2 ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nNormalMap2, info.m_nBumpFrame2 ); + } + } + + if( bHasEnvmap ) + { + pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + if( bRefractTintTexture ) + { + pShader->BindTexture( SHADER_SAMPLER5, info.m_nRefractTintTexture, info.m_nRefractTintTextureFrame ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( refract_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( refract_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send Posix down the ps2b path + { + DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( refract_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( refract_ps20 ); + } + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform ); // 1 & 2 + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nBumpTransform2 ); // 3 & 4 + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + pShader->SetPixelShaderConstantGammaToLinear( 0, info.m_nEnvmapTint ); + pShader->SetPixelShaderConstantGammaToLinear( 1, info.m_nRefractTint ); + pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation ); + float c5[4] = { params[info.m_nRefractAmount]->GetFloatValue(), + params[info.m_nRefractAmount]->GetFloatValue(), 0.0f, 0.0f }; + + // Time % 1000 + c5[3] = pShaderAPI->CurrentTime(); + c5[3] -= (float)( (int)( c5[3] / 1000.0f ) ) * 1000.0f; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + + float cVs3[4] = { c5[3], 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, cVs3, 1 ); + } + pShader->Draw(); +} + diff --git a/sp/src/materialsystem/stdshaders/refract_dx9_helper.h b/sp/src/materialsystem/stdshaders/refract_dx9_helper.h new file mode 100644 index 00000000..69d6116f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/refract_dx9_helper.h @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef REFRACT_DX9_HELPER_H +#define REFRACT_DX9_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct Refract_DX9_Vars_t +{ + Refract_DX9_Vars_t() { memset( this, 0xFF, sizeof( *this ) ); } + + int m_nBaseTexture; + int m_nFrame; + int m_nRefractAmount; + int m_nRefractTint; + int m_nNormalMap; + int m_nNormalMap2; + int m_nBumpFrame; + int m_nBumpFrame2; + int m_nBumpTransform; + int m_nBumpTransform2; + int m_nBlurAmount; + int m_nFadeOutOnSilhouette; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapTint; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nRefractTintTexture; + int m_nRefractTintTextureFrame; + int m_nFresnelReflection; + int m_nNoWriteZ; + int m_nMasked; + int m_nVertexColorModulate; + int m_nForceAlphaWrite; +}; + +void InitParamsRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, + Refract_DX9_Vars_t &info ); +void InitRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, Refract_DX9_Vars_t &info ); +void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // REFRACT_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/refract_ps2x.fxc b/sp/src/materialsystem/stdshaders/refract_ps2x.fxc new file mode 100644 index 00000000..2f974230 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/refract_ps2x.fxc @@ -0,0 +1,250 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======= +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "BLUR" "0..1" +// STATIC: "FADEOUTONSILHOUETTE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "REFRACTTINTTEXTURE" "0..1" +// STATIC: "MASKED" "0..1" +// STATIC: "COLORMODULATE" "0..1" +// STATIC: "SECONDARY_NORMAL" "0..1" +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] +// STATIC: "SHADER_SRGB_READ" "0..1" [ps20b] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $MASKED && $BLUR + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler NormalSampler2 : register( s1 ); +sampler RefractSampler : register( s2 ); +sampler NormalSampler : register( s3 ); +#if CUBEMAP +sampler EnvmapSampler : register( s4 ); +#endif +#if REFRACTTINTTEXTURE +sampler RefractTintSampler : register( s5 ); +#endif + +#if NORMAL_DECODE_MODE == NORM_DECODE_ATI2N_ALPHA +sampler AlphaMapSampler : register( s6 ); // alpha +sampler AlphaMapSampler2 : register( s7 ); +#else +#define AlphaMapSampler2 NormalSampler +#define AlphaMapSampler NormalSampler2 +#endif + +const float3 g_EnvmapTint : register( c0 ); +const float3 g_RefractTint : register( c1 ); +const float3 g_EnvmapContrast : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_c5 : register( c5 ); +#define g_RefractScale g_c5.x +#define g_flTime g_c5.w + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +static const int g_BlurCount = BLUR; +static const float g_BlurFraction = 1.0f / 512.0f; +static const float g_HalfBlurFraction = 0.5 * g_BlurFraction; +static const float4 g_BlurFractionVec = float4( g_BlurFraction, g_HalfBlurFraction, + -g_BlurFraction,-g_HalfBlurFraction ); + +struct PS_INPUT +{ + float4 vBumpTexCoord : TEXCOORD0; // NormalMap1 in xy, NormalMap2 in wz + float3 vTangentVertToEyeVector : TEXCOORD1; + float3 vWorldNormal : TEXCOORD2; + float3 vWorldTangent : TEXCOORD3; + float3 vWorldBinormal : TEXCOORD4; + float3 vRefractXYW : TEXCOORD5; + float3 vWorldViewVector : TEXCOORD6; +#if COLORMODULATE + float4 ColorModulate : COLOR0; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 result; + + float pixelFogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + +#if FADEOUTONSILHOUETTE + //float blend = -i.projNormal.z; + float blend = saturate( dot( -i.vWorldViewVector.xyz, i.vWorldNormal.xyz ) ); + blend = blend * blend * blend; +#else + float blend = 1.0f; +#endif + + // Decompress normal + float4 vNormal = DecompressNormal( NormalSampler, i.vBumpTexCoord.xy, NORMAL_DECODE_MODE, AlphaMapSampler ); + +#if SECONDARY_NORMAL + float3 vNormal2 = DecompressNormal( NormalSampler2, i.vBumpTexCoord.wz, NORMAL_DECODE_MODE, AlphaMapSampler2 ); + vNormal.xyz = normalize( vNormal.xyz + vNormal2.xyz ); +#endif + +#if REFRACTTINTTEXTURE + float3 refractTintColor = 2.0 * g_RefractTint * tex2D( RefractTintSampler, i.vBumpTexCoord.xy ); +#else + float3 refractTintColor = g_RefractTint; +#endif + +#if COLORMODULATE + refractTintColor *= i.ColorModulate.rgb; +#endif + + // Perform division by W only once + float ooW = 1.0f / i.vRefractXYW.z; + + // Compute coordinates for sampling refraction + float2 vRefractTexCoordNoWarp = i.vRefractXYW.xy * ooW; + float2 vRefractTexCoord = vNormal.xy; + float scale = vNormal.a * g_RefractScale; +#if COLORMODULATE + scale *= i.ColorModulate.a; +#endif + vRefractTexCoord *= scale; + vRefractTexCoord += vRefractTexCoordNoWarp; + +#if (BLUR==1) // use polyphase magic to convert 9 lookups into 4 + + // basic principle behind this transformation: + // [ A B C ] + // [ D E F ] + // [ G H I ] + // use bilinear filtering hardware to weight upper 2x2 samples evenly (0.25* [A + B + D + E]). + // scale the upper 2x2 by 4/9 (total area of kernel occupied) + // use bilinear filtering hardware to weight right 1x2 samples evenly (0.5*[C + F]) + // scale right 1x2 by 2/9 + // use bilinear filtering hardware to weight lower 2x1 samples evenly (0.5*[G + H]) + // scale bottom 2x1 by 2/9 + // fetch last sample (I) and scale by 1/9. + + float2 upper_2x2_loc = vRefractTexCoord.xy - float2(g_HalfBlurFraction, g_HalfBlurFraction); + float2 right_1x2_loc = vRefractTexCoord.xy + float2(g_BlurFraction, -g_HalfBlurFraction); + float2 lower_2x1_loc = vRefractTexCoord.xy + float2(-g_HalfBlurFraction, g_BlurFraction); + float2 singleton_loc = vRefractTexCoord.xy + float2(g_BlurFraction, g_BlurFraction); + result = tex2D(RefractSampler, upper_2x2_loc) * 0.4444444; + result += tex2D(RefractSampler, right_1x2_loc) * 0.2222222; + result += tex2D(RefractSampler, lower_2x1_loc) * 0.2222222; + result += tex2D(RefractSampler, singleton_loc) * 0.1111111; + + #if ( SHADER_SRGB_READ == 1 ) + { + // Just do this once rather than after every blur step, which is wrong, but much more efficient + result = GammaToLinear( result ); + } + #endif + + float3 unblurredColor = tex2D(RefractSampler, vRefractTexCoordNoWarp.xy); + #if ( SHADER_SRGB_READ == 1 ) + { + unblurredColor = GammaToLinear( unblurredColor ); + } + #endif + + result = lerp(unblurredColor, result * refractTintColor, blend); + +#elif (BLUR>0) // iteratively step through render target + int x, y; + + result = float3( 0.0f, 0.0f, 0.0f ); + for( x = -g_BlurCount; x <= g_BlurCount; x++ ) + { + for( y = -g_BlurCount; y <= g_BlurCount; y++ ) + { + result += tex2D( RefractSampler, vRefractTexCoord.xy + float2( g_BlurFraction * x, g_BlurFraction * y ) ); + } + } + + int width = g_BlurCount * 2 + 1; + result *= 1.0f / ( width * width ); + + #if ( SHADER_SRGB_READ == 1 ) + { + // Just do this once rather than after every blur step, which is wrong, but much more efficient + result = GammaToLinear( result ); + } + #endif + + // result is the blurred one now. . .now lerp. + float3 unblurredColor = tex2D( RefractSampler, vRefractTexCoordNoWarp.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + unblurredColor = GammaToLinear( unblurredColor ); + } + #endif + + result = lerp( unblurredColor, result * refractTintColor, blend ); +#else +# if MASKED + float4 fMaskedResult = tex2D( RefractSampler, vRefractTexCoord.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + fMaskedResult = GammaToLinear( fMaskedResult ); + } + #endif + + return FinalOutput( fMaskedResult, pixelFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE ); +# else + float3 colorWarp = tex2D( RefractSampler, vRefractTexCoord.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + colorWarp = GammaToLinear( colorWarp ); + } + #endif + float3 colorNoWarp = tex2D( RefractSampler, vRefractTexCoordNoWarp.xy ); + #if ( SHADER_SRGB_READ == 1 ) + { + colorNoWarp = GammaToLinear( colorNoWarp ); + } + #endif + + colorWarp *= refractTintColor; + result = lerp( colorNoWarp, colorWarp, blend ); +# endif +#endif + +#if CUBEMAP + float specularFactor = vNormal.a; + + float3 worldSpaceNormal = Vec3TangentToWorld( vNormal.xyz, i.vWorldNormal, i.vWorldTangent, i.vWorldBinormal ); + + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.vTangentVertToEyeVector ); + float3 specularLighting = texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint; + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + result += specularLighting; +#endif + +#if COLORMODULATE + float resultAlpha = i.ColorModulate.a * vNormal.a; +#else + float resultAlpha = vNormal.a; +#endif + + return FinalOutput( float4( result, resultAlpha ), pixelFogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/sp/src/materialsystem/stdshaders/shadowmodel_dx8.cpp b/sp/src/materialsystem/stdshaders/shadowmodel_dx8.cpp new file mode 100644 index 00000000..e7d7228a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/shadowmodel_dx8.cpp @@ -0,0 +1,97 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "shadowmodel.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( ShadowModel, ShadowModel_DX8 ) + +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX8, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) + SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) + SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) + SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) + SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + if (!params[BASETEXTURESCALE]->IsDefined()) + { + Vector2D scale(1, 1); + params[BASETEXTURESCALE]->SetVecValue( scale.Base(), 2 ); + } + + if (!params[FALLOFFDISTANCE]->IsDefined()) + params[FALLOFFDISTANCE]->SetFloatValue( 100.0f ); + + if (!params[FALLOFFAMOUNT]->IsDefined()) + params[FALLOFFAMOUNT]->SetFloatValue( 0.9f ); + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + // Base texture on stage 0 + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Multiplicative blending state... + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_ZERO ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + shadowmodel_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "ShadowModel", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "ShadowModel" ); + + // We need to fog to *white* regardless of overbrighting... + FogToWhite(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderMatrix3x4( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTUREOFFSET ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURESCALE ); + + Vector4D shadow; + shadow[0] = params[FALLOFFOFFSET]->GetFloatValue(); + shadow[1] = params[FALLOFFDISTANCE]->GetFloatValue() + shadow[0]; + if (shadow[1] != 0.0f) + shadow[1] = 1.0f / shadow[1]; + shadow[2] = params[FALLOFFAMOUNT]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, shadow.Base(), 1 ); + + // The constant color is the shadow color... + SetModulationVertexShaderDynamicState(); + + shadowmodel_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw( ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/shadowmodel_dx9.cpp b/sp/src/materialsystem/stdshaders/shadowmodel_dx9.cpp new file mode 100644 index 00000000..0198e86f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/shadowmodel_dx9.cpp @@ -0,0 +1,154 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +//Note: Not upgraded to vs/ps 2.0 fxc's because this shader is unused and there are no test cases to verify against. +#include "BaseVSShader.h" + +#if !defined( _X360 ) +#include "shadowmodel_ps20.inc" +#include "shadowmodel_vs20.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( ShadowModel, ShadowModel_DX9 ) + + +#if !defined( _X360 ) //not used for anything at time of 360 ship, and we want to avoid storing/loading assembly shaders + +//PC version +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX9, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + +BEGIN_SHADER_PARAMS +SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) +SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) +SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) +SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) +SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ + if (!params[BASETEXTURESCALE]->IsDefined()) + { + Vector2D scale(1, 1); + params[BASETEXTURESCALE]->SetVecValue( scale.Base(), 2 ); + } + + if (!params[FALLOFFDISTANCE]->IsDefined()) + params[FALLOFFDISTANCE]->SetFloatValue( 100.0f ); + + if (!params[FALLOFFAMOUNT]->IsDefined()) + params[FALLOFFAMOUNT]->SetFloatValue( 0.9f ); +} + +SHADER_FALLBACK +{ + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "ShadowModel_DX8"; + + return 0; +} + +SHADER_INIT +{ + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + } +} + +SHADER_DRAW +{ + SHADOW_STATE + { + // Base texture on stage 0 + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Multiplicative blending state... + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_ZERO ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( shadowmodel_vs20 ); + SET_STATIC_VERTEX_SHADER( shadowmodel_vs20 ); + + DECLARE_STATIC_PIXEL_SHADER( shadowmodel_ps20 ); + SET_STATIC_PIXEL_SHADER( shadowmodel_ps20 ); + + // We need to fog to *white* regardless of overbrighting... + FogToWhite(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderMatrix3x4( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTUREOFFSET ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURESCALE ); + + Vector4D shadow; + shadow[0] = params[FALLOFFOFFSET]->GetFloatValue(); + shadow[1] = params[FALLOFFDISTANCE]->GetFloatValue() + shadow[0]; + if (shadow[1] != 0.0f) + shadow[1] = 1.0f / shadow[1]; + shadow[2] = params[FALLOFFAMOUNT]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, shadow.Base(), 1 ); + + // The constant color is the shadow color... + SetModulationVertexShaderDynamicState(); + + DECLARE_DYNAMIC_VERTEX_SHADER( shadowmodel_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER( shadowmodel_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( shadowmodel_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( shadowmodel_ps20 ); + } + Draw( ); +} +END_SHADER + + +#else + +//360 version + +BEGIN_VS_SHADER_FLAGS( ShadowModel_DX9, "Help for ShadowModel", SHADER_NOT_EDITABLE ) + +BEGIN_SHADER_PARAMS +SHADER_PARAM( BASETEXTUREOFFSET, SHADER_PARAM_TYPE_VEC2, "[0 0]", "$baseTexture texcoord offset" ) +SHADER_PARAM( BASETEXTURESCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "$baseTexture texcoord scale" ) +SHADER_PARAM( FALLOFFOFFSET, SHADER_PARAM_TYPE_FLOAT, "0", "Distance at which shadow starts to fade" ) +SHADER_PARAM( FALLOFFDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100", "Max shadow distance" ) +SHADER_PARAM( FALLOFFAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.9", "Amount to brighten the shadow at max dist" ) +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ +} + +SHADER_FALLBACK +{ + return 0; +} + +SHADER_INIT +{ +} + +SHADER_DRAW +{ + Draw( false ); +} +END_SHADER + +#endif \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/shadowmodel_ps20.fxc b/sp/src/materialsystem/stdshaders/shadowmodel_ps20.fxc new file mode 100644 index 00000000..d0aedda9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/shadowmodel_ps20.fxc @@ -0,0 +1,20 @@ + +struct PS_INPUT +{ + float4 T0 : TEXCOORD0; + float3 T1 : TEXCOORD1; + float3 T2 : TEXCOORD2; + float T3 : TEXCOORD3; + float3 vColor : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + // Kill pixel against various fields computed in vertex shader + clip ( i.T1 ); + clip ( i.T2 ); + clip ( i.T3 ); // Backface cull + + // i.T0.a is uninitialized by the vs, but this is how the original asm shader was written???? + return float4( lerp( float3(1,1,1), i.vColor.xyz, i.T0.a ), 1 ); +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/shadowmodel_vs20.fxc b/sp/src/materialsystem/stdshaders/shadowmodel_vs20.fxc new file mode 100644 index 00000000..9d1ff02c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/shadowmodel_vs20.fxc @@ -0,0 +1,81 @@ +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cShadowTextureMatrix[3] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cTexOrigin : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cTexScale : register( SHADER_SPECIFIC_CONST_4 ); + +// { Shadow falloff offset, 1/Shadow distance, Shadow scale, 0 } +const float3 cShadowConstants : register( SHADER_SPECIFIC_CONST_5 ); +#define flShadowFalloffOffset cShadowConstants.x +#define flOneOverShadowDist cShadowConstants.y +#define flShadowScale cShadowConstants.z + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float3 vNormal : NORMAL; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position + float3 T0 : TEXCOORD0; // PS wants this to be 4D but VS doesn't? (see original asm sources) + float3 T1 : TEXCOORD1; + float3 T2 : TEXCOORD2; + float T3 : TEXCOORD3; + float4 vColor : COLOR0; + float fog : FOG; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( g_bSkinning, v.vPos, v.vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + + // Compute fog + o.fog = CalcFog( worldPos, o.projPos, g_FogType ); + + // Transform position into texture space (from 0 to 1) + float3 vTexturePos; + vTexturePos.x = dot( worldPos.xyz, cShadowTextureMatrix[0].xyz ); + vTexturePos.y = dot( worldPos.xyz, cShadowTextureMatrix[1].xyz ); + vTexturePos.z = dot( worldPos.xyz, cShadowTextureMatrix[2].xyz ); + + // Figure out the shadow fade amount + float flShadowFade = ( vTexturePos.z - flShadowFalloffOffset ) * flOneOverShadowDist; + + // Offset it into the texture + o.T0 = vTexturePos * cTexScale + cTexOrigin; + + // We're doing clipping by using texkill + o.T1.xyz = vTexturePos.xyz; // Also clips when shadow z < 0 ! + o.T2.xyz = float3( 1.0f, 1.0f, 1.0f ) - vTexturePos.xyz; + o.T2.z = 1.0f - flShadowFade; // Clips when shadow z > shadow distance + + // We're doing backface culling by using texkill also (wow yucky) + // -------------------------------------------------------------- + // Transform z component of normal in texture space + // If it's negative, then don't draw the pixel + o.T3 = dot( worldNormal, -cShadowTextureMatrix[2] ); + + // Shadow color, falloff + o.vColor.xyz = cModulationColor.xyz; + o.vColor.w = flShadowFade * flShadowScale; + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp new file mode 100644 index 00000000..1e2d30f3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp @@ -0,0 +1,977 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "BaseVSShader.h" +#include "skin_dx9_helper.h" +#include "convar.h" +#include "cpp_shader_constant_register_map.h" +#include "skin_vs20.inc" +#include "skin_ps20b.inc" +#include "commandbuilder.h" + +#ifndef _X360 +#include "skin_vs30.inc" +#include "skin_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); + +// Textures may be bound to the following samplers: +// SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha +// SHADER_SAMPLER1 Specular warp (including iridescence) +// SHADER_SAMPLER2 Diffuse Lighting warp texture +// SHADER_SAMPLER3 Normal Map +// SHADER_SAMPLER4 Flashlight Shadow Depth Map +// SHADER_SAMPLER5 Normalization cube map +// SHADER_SAMPLER6 Flashlight Cookie +// SHADER_SAMPLER7 Specular exponent +// SHADER_SAMPLER8 Cubic environment map +// SHADER_SAMPLER9 Compressed wrinklemap +// SHADER_SAMPLER10 Stretched wrinklemap +// SHADER_SAMPLER11 Compressed wrinkle normal map +// SHADER_SAMPLER12 Stretched wrinkle normal map +// SHADER_SAMPLER13 Detail texture + + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info ) +{ + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + Assert( info.m_nFlashlightTexture >= 0 ); + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping. + if( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // No texture means no env mask in base alpha + if ( !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // Lots of reasons to want tangent space, since we bind a flat normal map in many cases where we don't have a bump map + bool bBump = (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined(); + bool bEnvMap = (info.m_nEnvmap != -1) && params[info.m_nEnvmap]->IsDefined(); + bool bDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined(); + bool bPhong = (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined(); + if( bBump || bEnvMap || bDiffuseWarp || bPhong ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } + + if ( ( info.m_nSelfIllumFresnel != -1 ) && ( !params[info.m_nSelfIllumFresnel]->IsDefined() ) ) + { + params[info.m_nSelfIllumFresnel]->SetIntValue( 0 ); + } + + if ( ( info.m_nSelfIllumFresnelMinMaxExp != -1 ) && ( !params[info.m_nSelfIllumFresnelMinMaxExp]->IsDefined() ) ) + { + params[info.m_nSelfIllumFresnelMinMaxExp]->SetVecValue( 0.0f, 1.0f, 1.0f ); + } + + if ( ( info.m_nBaseMapAlphaPhongMask != -1 ) && ( !params[info.m_nBaseMapAlphaPhongMask]->IsDefined() ) ) + { + params[info.m_nBaseMapAlphaPhongMask]->SetIntValue( 0 ); + } + + if ( ( info.m_nEnvmapFresnel != -1 ) && ( !params[info.m_nEnvmapFresnel]->IsDefined() ) ) + { + params[info.m_nEnvmapFresnel]->SetFloatValue( 0 ); + } +} + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- +void InitSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, VertexLitGeneric_DX9_Vars_t &info ) +{ + Assert( info.m_nFlashlightTexture >= 0 ); + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + + bool bIsBaseTextureTranslucent = false; + if ( params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + + if ( ( info.m_nWrinkle != -1 ) && ( info.m_nStretch != -1 ) && + params[info.m_nWrinkle]->IsDefined() && params[info.m_nStretch]->IsDefined() ) + { + pShader->LoadTexture( info.m_nWrinkle, TEXTUREFLAGS_SRGB ); + pShader->LoadTexture( info.m_nStretch, TEXTUREFLAGS_SRGB ); + } + } + + bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsDefined(); + + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + // Can still be self illum with no base alpha if using one of these alternate modes + if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nPhongExponentTexture ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + if ( (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsDefined() && + (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() ) + { + pShader->LoadTexture( info.m_nPhongWarpTexture ); + } + + if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() ) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + if ( nDetailBlendMode == 0 ) // Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail, TEXTUREFLAGS_SRGB ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + + if ( ( info.m_nNormalWrinkle != -1 ) && ( info.m_nNormalStretch != -1 ) && + params[info.m_nNormalWrinkle]->IsDefined() && params[info.m_nNormalStretch]->IsDefined() ) + { + pShader->LoadTexture( info.m_nNormalWrinkle ); + pShader->LoadTexture( info.m_nNormalStretch ); + } + } + } + + if ( params[info.m_nEnvmap]->IsDefined() ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + + if ( bHasSelfIllumMask ) + { + pShader->LoadTexture( info.m_nSelfIllumMask ); + } +} + +class CSkin_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; + bool m_bFastPath; + +}; + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bHasFlashlight, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) +{ + bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture(); + bool bHasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture(); + + bool bHasBaseTextureWrinkle = bHasBaseTexture && + (info.m_nWrinkle != -1) && params[info.m_nWrinkle]->IsTexture() && + (info.m_nStretch != -1) && params[info.m_nStretch]->IsTexture(); + + bool bHasBumpWrinkle = bHasBump && + (info.m_nNormalWrinkle != -1) && params[info.m_nNormalWrinkle]->IsTexture() && + (info.m_nNormalStretch != -1) && params[info.m_nNormalStretch]->IsTexture(); + + bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bHasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) != 0; + bool bHasSelfIllumFresnel = ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + bool bHasSelfIllumMask = ( bHasSelfIllum ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsTexture(); + + // Tie these to specular + bool bHasPhong = (info.m_nPhong != -1) && ( params[info.m_nPhong]->GetIntValue() != 0 ); + bool bHasSpecularExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture(); + bool bHasPhongTintMap = bHasSpecularExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 ); + bool bHasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + bool bHasPhongWarp = (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsTexture(); + bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + +#if !defined( _X360 ) + bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); +#endif + + // Rimlight must be set to non-zero to trigger rim light combo (also requires Phong) + bool bHasRimLight = r_rimlight.GetBool() && bHasPhong && (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 ); + bool bHasRimMaskMap = bHasSpecularExponentTexture && bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 ); + + float fBlendFactor=( info.m_nDetailTextureBlendFactor == -1 )? 1 : params[info.m_nDetailTextureBlendFactor]->GetFloatValue(); + bool hasDetailTexture = ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsTexture(); + int nDetailBlendMode = ( hasDetailTexture && info.m_nDetailTextureCombineMode != -1 ) ? params[info.m_nDetailTextureCombineMode]->GetIntValue() : 0; + + bool bBlendTintByBaseAlpha = IsBoolSet( info.m_nBlendTintByBaseAlpha, params ) && !bHasSelfIllum; // Pixel shader can't do both BLENDTINTBYBASEALPHA and SELFILLUM, so let selfillum win + + float flTintReplacementAmount = GetFloatParam( info.m_nTintReplacesBaseColor, params ); + + BlendType_t nBlendType= pShader->EvaluateBlendRequirements( bBlendTintByBaseAlpha ? -1 : info.m_nBaseTexture, true ); + + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlight; //dest alpha is free for special use + + CSkin_DX9_Context *pContextData = reinterpret_cast< CSkin_DX9_Context *> ( *pContextDataPtr ); + if ( ! pContextData ) + { + pContextData = new CSkin_DX9_Context; + *pContextDataPtr = pContextData; + } + + if( pShader->IsSnapshotting() ) + { + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + bool bHasEnvmap = !bHasFlashlight && params[info.m_nEnvmap]->IsTexture(); + bool bHasNormal = params[info.m_nBumpmap]->IsTexture(); + bool bCanUseBaseAlphaPhongMaskFastPath = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 ); + + if ( ! ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) ) + bCanUseBaseAlphaPhongMaskFastPath = true; + + pContextData->m_bFastPath = + (! bHasBump ) && + (! bHasSpecularExponentTexture ) && + (! bHasPhongTintMap ) && + (! bHasPhongWarp ) && + (! bHasRimLight ) && + (! hasDetailTexture ) && + bCanUseBaseAlphaPhongMaskFastPath && + (! bHasSelfIllum ) && + (! bBlendTintByBaseAlpha ); + + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if( bHasFlashlight ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + + if( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + else // not flashlight pass + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true ); + } + + if ( bHasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Cubic environment map + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true ); + } + } + } + + unsigned int flags = VERTEX_POSITION; + if( bHasNormal ) + { + flags |= VERTEX_NORMAL; + } + + int userDataSize = 0; + + // Always enable...will bind white if nothing specified... + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + if ( bHasBaseTextureWrinkle || bHasBumpWrinkle ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Base (albedo) compression map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // Base (albedo) expansion map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true ); + } + + if( bHasDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Diffuse warp texture + } + + if( bHasPhongWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Specular warp texture + } + + // Specular exponent map or dummy + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Specular exponent map + + if( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true ); + userDataSize = 4; // tangent S + } + + // Always enable, since flat normal will be bound + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Normal map + userDataSize = 4; // tangent S + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Normalizing cube map + + if ( bHasBaseTextureWrinkle || bHasBumpWrinkle ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // Normal compression map + pShaderShadow->EnableTexture( SHADER_SAMPLER12, true ); // Normal expansion map + } + + if ( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER13, true ); + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER13, true ); + } + + if ( bHasSelfIllum ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER14, true ); + } + + if( bHasVertexColor || bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } + + pShaderShadow->EnableSRGBWrite( true ); + + // texcoord0 : base texcoord, texcoord2 : decal hw morph delta + int pTexCoordDim[3] = { 2, 0, 3 }; + int nTexCoordCount = 1; + +#ifndef _X360 + // Special morphed decal information + if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( skin_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( skin_vs20 ); + + // Assume we're only going to get in here if we support 2b + DECLARE_STATIC_PIXEL_SHADER( skin_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, bHasPhongWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, bHasBaseTextureWrinkle || bHasBumpWrinkle ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bHasRimLight ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FASTPATH_NOBUMP, pContextData->m_bFastPath ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( skin_ps20b ); + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( skin_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER( skin_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( skin_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel && !bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, bHasPhongWarp && bHasPhong ); + SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, bHasBaseTextureWrinkle || bHasBumpWrinkle ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bHasRimLight ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( FASTPATH_NOBUMP, pContextData->m_bFastPath ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( skin_ps30 ); + } +#endif + + if( bHasFlashlight ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + else // not snapshotting -- begin dynamic state + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + bool bHasEnvmap = !bHasFlashlight && params[info.m_nEnvmap]->IsTexture(); + + if( bHasBaseTexture ) + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + if ( bHasBaseTextureWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER9, info.m_nWrinkle, info.m_nBaseTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER10, info.m_nStretch, info.m_nBaseTextureFrame ); + } + else if ( bHasBumpWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER9, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + pShader->BindTexture( SHADER_SAMPLER10, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + + if( bHasDiffuseWarp && bHasPhong ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER2, info.m_nDiffuseWarpTexture ); + } + } + + if( bHasPhongWarp ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nPhongWarpTexture ); + } + + if( bHasSpecularExponentTexture && bHasPhong ) + { + pShader->BindTexture( SHADER_SAMPLER7, info.m_nPhongExponentTexture ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE ); + } + + if( !g_pConfig->m_bFastNoBump ) + { + if( bHasBump ) + pShader->BindTexture( SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + else + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + + if ( bHasBumpWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER11, info.m_nNormalWrinkle, info.m_nBumpFrame ); + pShader->BindTexture( SHADER_SAMPLER12, info.m_nNormalStretch, info.m_nBumpFrame ); + } + else if ( bHasBaseTextureWrinkle ) + { + pShader->BindTexture( SHADER_SAMPLER11, info.m_nBumpmap, info.m_nBumpFrame ); + pShader->BindTexture( SHADER_SAMPLER12, info.m_nBumpmap, info.m_nBumpFrame ); + } + } + else + { + if( bHasBump ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + if ( bHasBaseTextureWrinkle || bHasBumpWrinkle ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER11, TEXTURE_NORMALMAP_FLAT ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER12, TEXTURE_NORMALMAP_FLAT ); + } + } + + if ( hasDetailTexture ) + { + pShader->BindTexture( SHADER_SAMPLER13, info.m_nDetail, info.m_nDetailFrame ); + } + + if ( bHasSelfIllum ) + { + if ( bHasSelfIllumMask ) // Separate texture for self illum? + { + pShader->BindTexture( SHADER_SAMPLER14, info.m_nSelfIllumMask ); // Bind it + } + else // else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER14, TEXTURE_BLACK ); // Bind dummy + } + } + + LightState_t lightState = { 0, false, false }; + bool bFlashlightShadows = false; + if( bHasFlashlight ) + { + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame ); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D ); + } + } + else // no flashlight + { + if ( bHasEnvmap ) + { + pShader->BindTexture( SHADER_SAMPLER8, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + int numBones = pShaderAPI->GetCurrentNumBones(); + + // don't have an easy way to get this through to GLM, so just print it old school + //printf("\n-D- DrawSkin_DX9_Internal numBones is %d", numBones ); + + bool bWriteDepthToAlpha = false; + bool bWriteWaterFogToAlpha = false; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( skin_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( skin_vs20 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( skin_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( skin_ps20b ); + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( skin_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( skin_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( skin_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( skin_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + + if( bHasBump ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); + } + + if ( hasDetailTexture ) + { + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, + info.m_nDetailTextureTransform, + info.m_nDetailScale ); + else + pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, + info.m_nBaseTextureTransform, + info.m_nDetailScale ); + } + + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + pShader->SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, fBlendFactor ); + bool bInvertPhongMask = ( info.m_nInvertPhongMask != -1 ) && ( params[info.m_nInvertPhongMask]->GetIntValue() != 0 ); + float fInvertPhongMask = bInvertPhongMask ? 1 : 0; + + bool bHasBaseAlphaPhongMask = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 ); + float fHasBaseAlphaPhongMask = bHasBaseAlphaPhongMask ? 1 : 0; + // Controls for lerp-style paths through shader code + float vShaderControls[4] = { fHasBaseAlphaPhongMask, 0.0f/*unused*/, flTintReplacementAmount, fInvertPhongMask }; + pShaderAPI->SetPixelShaderConstant( PSREG_CONSTANT_27, vShaderControls, 1 ); + + if ( hasDetailTexture ) + { +#if 0 // needs constant change + if ( info.m_nDetailTint != -1 ) + pShader->SetPixelShaderConstantGammaToLinear( 10, info.m_nDetailTint ); + else + { + float boring_tint[4]={1,1,1,1}; + pShaderAPI->SetPixelShaderConstant( 10, boring_tint, 1 ); + } +#endif + } + + if ( bHasSelfIllumFresnel && !bHasFlashlight ) + { + float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f; + float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f; + float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f; + + vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias + vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale + vConstScaleBiasExp[2] = flExp; // Exp + vConstScaleBiasExp[3] = flMax; // Brightness + + pShaderAPI->SetPixelShaderConstant( PSREG_SELFILLUM_SCALE_BIAS_EXP, vConstScaleBiasExp, 1 ); + } + + pShader->SetAmbientCubeDynamicStateVertexShader(); + + if( !bHasFlashlight ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // Setting .x to 1 means to apply Fresnel to env map. Setting w to 1 means use separate selfillummask + float vEnvMapFresnel_SelfIllumMask[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + vEnvMapFresnel_SelfIllumMask[3] = bHasSelfIllumMask ? 1.0f : 0.0f; + + if( bHasEnvmap ) + { + float vEnvMapTint_MaskControl[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + + // If we have a tint, grab it + if ( (info.m_nEnvmapTint != -1) && params[info.m_nEnvmapTint]->IsDefined() ) + params[info.m_nEnvmapTint]->GetVecValue(vEnvMapTint_MaskControl, 3); + + // Set control for source of env map mask (normal alpha or base alpha) + vEnvMapTint_MaskControl[3] = bHasNormalMapAlphaEnvmapMask ? 1.0f : 0.0f; + + if ( (info.m_nEnvmapFresnel != -1) && params[info.m_nEnvmapFresnel]->IsDefined() ) + vEnvMapFresnel_SelfIllumMask[0] = params[info.m_nEnvmapFresnel]->GetFloatValue(); + + // Handle mat_fullbright 2 (diffuse lighting only with 50% gamma space basetexture) + if( bLightingOnly ) + { + vEnvMapTint_MaskControl[0] = vEnvMapTint_MaskControl[1] = vEnvMapTint_MaskControl[2] = 0.0f; + } + + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, vEnvMapTint_MaskControl, 1 ); + } + + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_FRESNEL__SELFILLUMMASK, vEnvMapFresnel_SelfIllumMask, 1 ); + } + + pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight ); // Force to black if not bAmbientLight + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + + // Pack Phong exponent in with the eye position + float vEyePos_SpecExponent[4], vFresnelRanges_SpecBoost[4] = {1, 0.5, 1, 1}, vRimBoost[4] = {1, 1, 1, 1}; + float vSpecularTint[4] = {1, 1, 1, 4}; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + + // Use the alpha channel of the normal map for the exponent by default + vEyePos_SpecExponent[3] = -1.f; + if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) + { + float fValue = params[info.m_nPhongExponent]->GetFloatValue(); + if ( fValue > 0.f ) + { + // Nonzero value in material overrides map channel + vEyePos_SpecExponent[3] = fValue; + } + } + + // Get the tint parameter + if ( (info.m_nPhongTint != -1) && params[info.m_nPhongTint]->IsDefined() ) + { + params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 3); + } + + // Get the rim light power (goes in w of Phong tint) + if ( bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() ) + { + vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue(); + vSpecularTint[3] = max(vSpecularTint[3], 1.0f); // Make sure this is at least 1 + } + + // Get the rim boost (goes in w of flashlight position) + if ( bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() ) + { + vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue(); + } + + if ( !bHasFlashlight ) + { + float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code + vRimMaskControl[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f; + + // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 ); + } + + // If it's all zeros, there was no constant tint in the vmt + if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) ) + { + if ( bHasPhongTintMap ) // If we have a map to use, tell the shader + { + vSpecularTint[0] = -1; + } + else // Otherwise, just tint with white + { + vSpecularTint[0] = 1.0f; + vSpecularTint[1] = 1.0f; + vSpecularTint[2] = 1.0f; + } + } + + // handle mat_fullbright 2 (diffuse lighting only) + if( bLightingOnly ) + { + // BASETEXTURE + if( bHasSelfIllum && !bHasFlashlight ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + + // DETAILTEXTURE + if ( hasDetailTexture ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER13, TEXTURE_GREY ); + } + + // turn off specularity + vSpecularTint[0] = vSpecularTint[1] = vSpecularTint[2] = 0.0f; + } + + if ( (info.m_nPhongFresnelRanges != -1) && params[info.m_nPhongFresnelRanges]->IsDefined() ) + { + params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 ); // Grab optional Fresnel range parameters + // Change fresnel range encoding from (min, mid, max) to ((mid-min)*2, mid, (max-mid)*2) + vFresnelRanges_SpecBoost[0] = (vFresnelRanges_SpecBoost[1] - vFresnelRanges_SpecBoost[0]) * 2; + vFresnelRanges_SpecBoost[2] = (vFresnelRanges_SpecBoost[2] - vFresnelRanges_SpecBoost[1]) * 2; + } + + if ( (info.m_nPhongBoost != -1 ) && params[info.m_nPhongBoost]->IsDefined()) // Grab optional Phong boost param + vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue(); + else + vFresnelRanges_SpecBoost[3] = 1.0f; + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + pShaderAPI->SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 ); + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 ); // Rim boost in w on non-flashlight pass + + pShaderAPI->SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 ); + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + // flashlightfixme: put this in common code. + if( bHasFlashlight ) + { + VMatrix worldToTexture; + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } + } + } + pShader->Draw(); +} + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +extern ConVar r_flashlight_version2; +void DrawSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) + +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawSkin_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, false, info, vertexCompression, pContextDataPtr++ ); + if ( pShaderShadow ) + { + pShader->SetInitialShadowState( ); + } + } + DrawSkin_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bHasFlashlight, info, vertexCompression, pContextDataPtr ); +} diff --git a/sp/src/materialsystem/stdshaders/skin_dx9_helper.h b/sp/src/materialsystem/stdshaders/skin_dx9_helper.h new file mode 100644 index 00000000..414e8dd2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/skin_dx9_helper.h @@ -0,0 +1,35 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef SKIN_DX9_HELPER_H +#define SKIN_DX9_HELPER_H + +#include + +#include "vertexlitgeneric_dx9_helper.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +void InitParamsSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, + const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info ); +void InitSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, + VertexLitGeneric_DX9_Vars_t &info ); + +void DrawSkin_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ); + + + +#endif // SKIN_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/skin_ps20b.fxc b/sp/src/materialsystem/stdshaders/skin_ps20b.fxc new file mode 100644 index 00000000..20c3eef9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/skin_ps20b.fxc @@ -0,0 +1,371 @@ +//======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== +// STATIC: "CONVERT_TO_SRGB" "0..0" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "SELFILLUMFRESNEL" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "PHONGWARPTEXTURE" "0..1" +// STATIC: "WRINKLEMAP" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..6" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "RIMLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "FASTPATH_NOBUMP" "0..1" +// STATIC: "BLENDTINTBYBASEALPHA" "0..1" + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + + +// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) + +// blend mode doesn't matter if we only have one texture +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30] + +// Only need self illum fresnel when self illum enabled +// SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUM == 1 ) + +// BlendTintByBaseAlpha and self illum and are opposing meanings for alpha channel +// SKIP: ( $BLENDTINTBYBASEALPHA ) && ( $SELFILLUM ) + +// fastpath means: +// no bumpmap +// basealphaenvmapmask (not inverted) +// no spec expmap +// no spectint +// no specwarp +// no rimlight +// no selfillum +// no detail +// no BlendTintByBaseAlpha + +// SKIP: $FASTPATH_NOBUMP && ( $RIMLIGHT || $DETAILTEXTURE || $PHONGWARPTEXTURE || $SELFILLUM || $BLENDTINTBYBASEALPHA ) + + + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +const float4 g_SelfIllumTint_and_DetailBlendFactor : register( PSREG_SELFILLUMTINT ); +#if ( SELFILLUMFRESNEL == 1 ) +const float4 g_SelfIllumScaleBiasExpBrightness : register( PSREG_SELFILLUM_SCALE_BIAS_EXP ); +#endif +const float4 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION ); +const float4 g_EnvmapTint_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); // w controls spec mask +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_EnvMapFresnel : register( PSREG_ENVMAP_FRESNEL__SELFILLUMMASK ); // x is envmap fresnel ... w is selfillummask control +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control +const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost +const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total (4th light spread across w's) + +// TODO: give this a better name. For now, I don't want to touch shader_constant_register_map.h since I don't want to trigger a recompile of everything... +const float4 g_ShaderControls : register( PSREG_CONSTANT_27 ); // x is basemap alpgha phong mask, y is 1 - blendtintbybasealpha, z is tint overlay amount, w controls "INVERTPHONGMASK" +#define g_FlashlightPos g_FlashlightPos_RimBoost.xyz +#define g_fRimBoost g_FlashlightPos_RimBoost.w +#define g_FresnelRanges g_FresnelSpecParams.xyz +#define g_SpecularBoost g_FresnelSpecParams.w +#define g_SpecularTint g_SpecularRimParams.xyz +#define g_RimExponent g_SpecularRimParams.w +#define g_FlashlightAttenuationFactors g_FlashlightAttenuationFactors_RimMask +#define g_RimMaskControl g_FlashlightAttenuationFactors_RimMask.x +#define g_SelfIllumMaskControl g_EnvMapFresnel.w +#define g_fBaseMapAlphaPhongMask g_ShaderControls.x +#define g_fTintReplacementControl g_ShaderControls.z +#define g_fInvertPhongMask g_ShaderControls.w + +sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha +sampler SpecularWarpSampler : register( s1 ); // Specular warp sampler (for iridescence etc) +sampler DiffuseWarpSampler : register( s2 ); // Lighting warp sampler (1D texture for diffuse lighting modification) +sampler NormalMapSampler : register( s3 ); // Normal map, specular mask in alpha +sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler +sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers +sampler FlashlightSampler : register( s6 ); // Flashlight cookie +sampler SpecExponentSampler : register( s7 ); // Specular exponent map +sampler EnvmapSampler : register( s8 ); // Cubic environment map + +#if WRINKLEMAP +sampler WrinkleSampler : register( s9 ); // Compression base +sampler StretchSampler : register( s10 ); // Expansion base +sampler NormalWrinkleSampler : register( s11 ); // Compression base +sampler NormalStretchSampler : register( s12 ); // Expansion base +#endif + +#if DETAILTEXTURE +sampler DetailSampler : register( s13 ); // detail texture +#endif + +sampler SelfIllumMaskSampler : register( s14 ); // selfillummask + + +struct PS_INPUT +{ + float4 baseTexCoordDetailTexCoord : TEXCOORD0; // xy=base zw=detail + float3 lightAtten : TEXCOORD1; // Scalar light attenuation factors for FOUR lights + float3 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3x3 tangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float4 worldPos_atten3 : TEXCOORD6; + float4 projPos_fWrinkleWeight : TEXCOORD7; +}; + + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bWrinkleMap = WRINKLEMAP ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + bool bDoSpecularWarp = PHONGWARPTEXTURE ? true : false; + bool bDoAmbientOcclusion = false; + bool bFlashlight = (FLASHLIGHT!=0) ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bDoRimLighting = RIMLIGHT ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + int nNumLights = NUM_LIGHTS; + + // Unpacking for convenience + float fWrinkleWeight = i.projPos_fWrinkleWeight.w; + float3 vProjPos = i.projPos_fWrinkleWeight.xyz; + float3 vWorldPos = i.worldPos_atten3.xyz; + float atten3 = i.worldPos_atten3.w; + + float4 vLightAtten = float4( i.lightAtten, atten3 ); + +#if WRINKLEMAP + float flWrinkleAmount = saturate( -fWrinkleWeight ); // One of these two is zero + float flStretchAmount = saturate( fWrinkleWeight ); // while the other is in the 0..1 range + + float flTextureAmount = 1.0f - flWrinkleAmount - flStretchAmount; // These should sum to one +#endif + + float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoordDetailTexCoord.xy ); +#if WRINKLEMAP + float4 wrinkleColor = tex2D( WrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); + float4 stretchColor = tex2D( StretchSampler, i.baseTexCoordDetailTexCoord.xy ); + + // Apply wrinkle blend to only RGB. Alpha comes from the base texture + baseColor.rgb = flTextureAmount * baseColor + flWrinkleAmount * wrinkleColor + flStretchAmount * stretchColor; +#endif + +#if DETAILTEXTURE + float4 detailColor = tex2D( DetailSampler, i.baseTexCoordDetailTexCoord.zw ); + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactor.w ); +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, vWorldPos.z, vProjPos.z ); + + float3 vEyeDir = normalize(i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz); + float3 vRimAmbientCubeColor = PixelShaderAmbientLight(vEyeDir, cAmbientCube); + + float3 worldSpaceNormal, tangentSpaceNormal; + float fSpecMask = 1.0f; + float4 normalTexel = tex2D( NormalMapSampler, i.baseTexCoordDetailTexCoord.xy ); + +#if WRINKLEMAP + float4 wrinkleNormal = tex2D( NormalWrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); + float4 stretchNormal = tex2D( NormalStretchSampler, i.baseTexCoordDetailTexCoord.xy ); + normalTexel = flTextureAmount * normalTexel + flWrinkleAmount * wrinkleNormal + flStretchAmount * stretchNormal; +#endif + +#if (FASTPATH_NOBUMP == 0 ) + tangentSpaceNormal = lerp( 2.0f * normalTexel.xyz - 1.0f, float3(0, 0, 1), g_fBaseMapAlphaPhongMask ); + fSpecMask = lerp( normalTexel.a, baseColor.a, g_fBaseMapAlphaPhongMask ); +#else + tangentSpaceNormal = float3(0, 0, 1); + fSpecMask = baseColor.a; +#endif + + // We need a normal if we're doing any lighting + worldSpaceNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + + float fFresnelRanges = Fresnel( worldSpaceNormal, vEyeDir, g_FresnelRanges ); + float fRimFresnel = Fresnel4( worldSpaceNormal, vEyeDir ); + + // Break down reflect so that we can share dot(worldSpaceNormal,vEyeDir) with fresnel terms + float3 vReflect = 2 * worldSpaceNormal * dot(worldSpaceNormal, vEyeDir) - vEyeDir; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + float3 envMapColor = float3( 0.0f, 0.0f, 0.0f ); + if( !bFlashlight ) + { + // Summation of diffuse illumination from all local lights + diffuseLighting = PixelShaderDoLighting( vWorldPos, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, true, vLightAtten, + cAmbientCube, NormalizeRandRotSampler, nNumLights, cLightInfo, true, + + // These parameters aren't passed by generic shaders: + false, 1.0f, + bDoDiffuseWarp, DiffuseWarpSampler ); + + if( bCubemap ) + { + // Mask is either normal map alpha or base map alpha +#if ( SELFILLUMFRESNEL == 1 ) // This is to match the 2.0 version of vertexlitgeneric + float fEnvMapMask = lerp( baseColor.a, g_fInvertPhongMask, g_EnvmapTint_ShadowTweaks.w ); +#else + float fEnvMapMask = lerp( baseColor.a, fSpecMask, g_EnvmapTint_ShadowTweaks.w ); +#endif + + envMapColor = (ENV_MAP_SCALE * + lerp(1, fFresnelRanges, g_EnvMapFresnel.x) * + lerp(fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask)) * + texCUBE( EnvmapSampler, vReflect ) * + g_EnvmapTint_ShadowTweaks.xyz; + } + } + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 rimLighting = float3( 0.0f, 0.0f, 0.0f ); + + float3 vSpecularTint = 1; + float fRimMask = 0; + float fSpecExp = 1; + +#if ( FASTPATH_NOBUMP == 0 ) + float4 vSpecExpMap = tex2D( SpecExponentSampler, i.baseTexCoordDetailTexCoord.xy ); + + if ( !bFlashlight ) + { + fRimMask = lerp( 1.0f, vSpecExpMap.a, g_RimMaskControl ); // Select rim mask + } + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent +#if defined( _X360 ) + [flatten] +#endif + + fSpecExp = (g_EyePos_SpecExponent.w >= 0.0) ? g_EyePos_SpecExponent.w : (1.0f + 149.0f * vSpecExpMap.r); + + // If constant tint is negative, tint with albedo, based upon scalar tint map +#if defined( _X360 ) + [flatten] +#endif + vSpecularTint = lerp( float3(1.0f, 1.0f, 1.0f), baseColor.rgb, vSpecExpMap.g ); + vSpecularTint = (g_SpecularTint.r >= 0.0) ? g_SpecularTint.rgb : vSpecularTint; + +#else + fSpecExp = max(g_EyePos_SpecExponent.w, 0); +#endif + + float3 albedo = baseColor.rgb; + + if ( !bFlashlight ) + { + // Summation of specular from all local lights besides the flashlight + PixelShaderDoSpecularLighting( vWorldPos, worldSpaceNormal, + fSpecExp, vEyeDir, vLightAtten, + nNumLights, cLightInfo, false, 1.0f, bDoSpecularWarp, + SpecularWarpSampler, fFresnelRanges, bDoRimLighting, g_RimExponent, + + // Outputs + specularLighting, rimLighting ); + } + else + { + float4 flashlightSpacePosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); + + DoSpecularFlashlight( g_FlashlightPos, vWorldPos, flashlightSpacePosition, worldSpaceNormal, + g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, + FlashlightSampler, ShadowDepthSampler, NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, vProjPos.xy / vProjPos.z, + fSpecExp, vEyeDir, bDoSpecularWarp, SpecularWarpSampler, fFresnelRanges, g_EnvmapTint_ShadowTweaks, + + // These two values are output + diffuseLighting, specularLighting ); + } + + // If we didn't already apply Fresnel to specular warp, modulate the specular + if ( !bDoSpecularWarp ) + fSpecMask *= fFresnelRanges; + + // Modulate with spec mask, boost and tint + specularLighting *= fSpecMask * g_SpecularBoost; + + if (bBlendTintByBaseAlpha) + { + float3 tintedColor = albedo * g_DiffuseModulation.rgb; + tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_fTintReplacementControl); + albedo = lerp(albedo, tintedColor, baseColor.a); + } + else + { + albedo = albedo * g_DiffuseModulation.rgb; + } + + + float3 diffuseComponent = albedo * diffuseLighting; + if ( bSelfIllum && !bFlashlight ) + { +#if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file + // This will apply a Fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look + float3 vVertexNormal = normalize( float3( i.tangentSpaceTranspose[0].z, i.tangentSpaceTranspose[1].z, i.tangentSpaceTranspose[2].z ) ); + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, vEyeDir.xyz ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo * g_SelfIllumScaleBiasExpBrightness.w, baseColor.a * saturate( flSelfIllumFresnel ) ); +#else + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoordDetailTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactor.rgb * albedo, vSelfIllumMask ); +#endif + + diffuseComponent = max( 0.0f, diffuseComponent ); + } + +#if DETAILTEXTURE + diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, + DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactor.w ); +#endif + + if ( bDoRimLighting && !bFlashlight ) + { + float fRimMultiply = fRimMask * fRimFresnel; // both unit range: [0, 1] + + // Add in rim light modulated with tint, mask and traditional Fresnel (not using Fresnel ranges) + rimLighting *= fRimMultiply; + + // Fold rim lighting into specular term by using the max so that we don't really add light twice... + specularLighting = max( specularLighting, rimLighting ); + + // Add in view-ray lookup from ambient cube + specularLighting += (vRimAmbientCubeColor * g_fRimBoost) * saturate(fRimMultiply * worldSpaceNormal.z); + } + + float3 result = specularLighting*vSpecularTint + envMapColor + diffuseComponent; + +#if WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) + float alpha = fogFactor; +#else + float alpha = g_DiffuseModulation.a; + if ( !bSelfIllum && !bBlendTintByBaseAlpha ) + { + alpha = lerp( baseColor.a * alpha, alpha, g_fBaseMapAlphaPhongMask ); + } +#endif + + bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 ); + + //FIXME: need to take dowaterfog into consideration + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, vProjPos.z ); +} diff --git a/sp/src/materialsystem/stdshaders/skin_vs20.fxc b/sp/src/materialsystem/stdshaders/skin_vs20.fxc new file mode 100644 index 00000000..9b04b7aa --- /dev/null +++ b/sp/src/materialsystem/stdshaders/skin_vs20.fxc @@ -0,0 +1,173 @@ +//======= Copyright (c) 1996-2007, Valve Corporation, All rights reserved. ====== + +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float4 vPosFlex : POSITION1; + float4 vNormalFlex : NORMAL1; + +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + // Stuff that is seen by the pixel shader + float4 baseTexCoord : TEXCOORD0; // includes detail tex coord + float3 lightAtten : TEXCOORD1; + float3 worldVertToEyeVector : TEXCOORD2; + float3x3 tangentSpaceTranspose : TEXCOORD3; + // second row : TEXCOORD4; + // third row : TEXCOORD5; + float4 worldPos_atten3 : TEXCOORD6; + float4 projPos_fWrinkleWeight : TEXCOORD7; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, + vPosition.xyz, vNormal, vTangent.xyz, o.projPos_fWrinkleWeight.w ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, v.vTexCoord2, + vPosition.xyz, vNormal, vTangent.xyz, o.projPos_fWrinkleWeight.w ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.projPos_fWrinkleWeight.xyz = vProjPos.xyz; + +#if !defined( _X360 ) + o.fog = CalcFog( worldPos, vProjPos.xyz, g_FogType ); +#endif + // Needed for water fog alpha and diffuse lighting + // FIXME: we shouldn't have to compute this all the time. + o.worldPos_atten3.xyz = worldPos; + + // Needed for specular + o.worldVertToEyeVector = VSHADER_VECT_SCALE * (cEyePos - worldPos); + + // Compute bumped lighting + // FIXME: We shouldn't have to compute this for unlit materials +#if defined ( SHADER_MODEL_VS_2_0 ) && ( !USE_STATIC_CONTROL_FLOW ) + o.lightAtten.xyz = float3(0,0,0); + o.worldPos_atten3.w = 0.0f; + #if ( NUM_LIGHTS > 0 ) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.worldPos_atten3.w = GetVertexAttenForLight( worldPos, 3, false ); + #endif +#else + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, true ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, true ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, true ); + o.worldPos_atten3.w = GetVertexAttenForLight( worldPos, 3, true ); +#endif + + // Base texture coordinate transform + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + o.baseTexCoord.z = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.baseTexCoord.w = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/sky_dx6.cpp b/sp/src/materialsystem/stdshaders/sky_dx6.cpp new file mode 100644 index 00000000..15bdc553 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_dx6.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Teeth renderer +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Sky, UnlitGeneric ) +DEFINE_FALLBACK_SHADER( Sky_dx6, UnlitGeneric ) + diff --git a/sp/src/materialsystem/stdshaders/sky_dx9.cpp b/sp/src/materialsystem/stdshaders/sky_dx9.cpp new file mode 100644 index 00000000..93eb6115 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_dx9.cpp @@ -0,0 +1,126 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// +#include "BaseVSShader.h" +#include "sky_vs20.inc" +#include "sky_ps20.inc" +#include "sky_ps20b.inc" + +#include "convar.h" + +BEGIN_VS_SHADER( Sky_DX9, "Help for Sky_DX9 shader" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_VEC3, "[ 1 1 1]", "color multiplier", SHADER_PARAM_NOT_EDITABLE ) + SHADER_PARAM_OVERRIDE( ALPHA, SHADER_PARAM_TYPE_FLOAT, "1.0", "unused", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "sky_dx6"; + } + return 0; + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NOFOG ); + SET_FLAGS( MATERIAL_VAR_IGNOREZ ); + } + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + ImageFormat fmt = params[BASETEXTURE]->GetTextureValue()->GetImageFormat(); + LoadTexture( BASETEXTURE, (fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616) ? 0 : TEXTUREFLAGS_SRGB ); + } + } + SHADER_DRAW + { + SHADOW_STATE + { + SetInitialShadowState(); + +// pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + ITexture *txtr=params[BASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ((fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616)) + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + else + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,true); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, NULL, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sky_vs20 ); + SET_STATIC_VERTEX_SHADER( sky_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_ps20 ); + } + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + float c1[4]={0,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + float c0[4]={1,1,1,1}; + if (params[COLOR]->IsDefined()) + { + memcpy(c0,params[COLOR]->GetVecValue(),3*sizeof(float)); + } + ITexture *txtr=params[BASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( + (fmt==IMAGE_FORMAT_RGBA16161616) || + ( (fmt==IMAGE_FORMAT_RGBA16161616F) && + (g_pHardwareConfig->GetHDRType()==HDR_TYPE_INTEGER)) + ) + { + c0[0]*=16.0; + c0[1]*=16.0; + c0[2]*=16.0; + } + pShaderAPI->SetPixelShaderConstant(0,c0,1); + DECLARE_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + + // Texture coord transform + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BASETEXTURETRANSFORM ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + } + } + Draw( ); + } + +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc b/sp/src/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc new file mode 100644 index 00000000..8e54d21f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_hdr_compressed_ps2x.fxc @@ -0,0 +1,29 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler ExposureTextureSampler0 : register( s0 ); +sampler ExposureTextureSampler1 : register( s1 ); +sampler ExposureTextureSampler2 : register( s2 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF3 color0 = 0.25*tex2D( ExposureTextureSampler0, i.baseTexCoord ); + HALF3 color1 = 2.0*tex2D( ExposureTextureSampler1, i.baseTexCoord ); + HALF3 color2 = 16.0*tex2D( ExposureTextureSampler2, i.baseTexCoord ); + + // This is never fogged. +// return FinalOutput( float4( max(max(color0,color1),color2), 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate + return FinalOutput( float4(1,0,0,1 ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/sp/src/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc b/sp/src/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc new file mode 100644 index 00000000..4871da56 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_hdr_compressed_rgbs_ps2x.fxc @@ -0,0 +1,81 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler RGBSTextureSampler : register( s0 ); +HALF4 InputScale : register( c0 ); + +float2 texWidthHeight : register( c1 ); + +float4 texOffsets : register( c2 ); + +struct PS_INPUT +{ +//#if defined( _X360 ) +// float2 baseTexCoord : TEXCOORD0; +//#else + float2 baseTexCoord00 : TEXCOORD0; + float2 baseTexCoord01 : TEXCOORD1; + float2 baseTexCoord10 : TEXCOORD2; + float2 baseTexCoord11 : TEXCOORD3; + float2 baseTexCoord_In_Pixels: TEXCOORD4; +//#endif +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float3 result; + +//#if defined( _X360 ) //360 has a cheaper way to handle RGBscale +// float4 Weights; +// float4 samples_0; //no arrays allowed in inline assembly +// float4 samples_1; +// float4 samples_2; +// float4 samples_3; +// float2 vTexCoord = i.baseTexCoord; +// +// asm { +// tfetch2D samples_0, vTexCoord.xy, RGBSTextureSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_1, vTexCoord.xy, RGBSTextureSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_2, vTexCoord.xy, RGBSTextureSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// tfetch2D samples_3, vTexCoord.xy, RGBSTextureSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false +// +// getWeights2D Weights, vTexCoord.xy, RGBSTextureSampler +// }; +// +// Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y ); +// +// result.rgb = samples_0.rgb * (samples_0.a * Weights.x); +// result.rgb += samples_1.rgb * (samples_1.a * Weights.y); +// result.rgb += samples_2.rgb * (samples_2.a * Weights.z); +// result.rgb += samples_3.rgb * (samples_3.a * Weights.w); +// +//#else + float4 s00 = tex2D(RGBSTextureSampler, i.baseTexCoord00); + float4 s10 = tex2D(RGBSTextureSampler, i.baseTexCoord10); + float4 s01 = tex2D(RGBSTextureSampler, i.baseTexCoord01); + float4 s11 = tex2D(RGBSTextureSampler, i.baseTexCoord11); + + float2 fracCoord = frac(i.baseTexCoord_In_Pixels); + + s00.rgb*=s00.a; + s10.rgb*=s10.a; + + s00.xyz = lerp(s00, s10, fracCoord.x); + + s01.rgb*=s01.a; + s11.rgb*=s11.a; + s01.xyz = lerp(s01, s11, fracCoord.x); + + result = lerp(s00, s01, fracCoord.y); +//#endif + + // This is never fogged. + return FinalOutput( float4( InputScale*result, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/sp/src/materialsystem/stdshaders/sky_hdr_dx9.cpp b/sp/src/materialsystem/stdshaders/sky_hdr_dx9.cpp new file mode 100644 index 00000000..285879c0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_hdr_dx9.cpp @@ -0,0 +1,297 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// +#include "BaseVSShader.h" +#include "sky_vs20.inc" +#include "sky_ps20.inc" +#include "sky_ps20b.inc" +#include "sky_hdr_compressed_ps20.inc" +#include "sky_hdr_compressed_ps20b.inc" +#include "sky_hdr_compressed_rgbs_ps20.inc" +#include "sky_hdr_compressed_rgbs_ps20b.inc" + +#include "convar.h" + +static ConVar mat_use_compressed_hdr_textures( "mat_use_compressed_hdr_textures", "1" ); + +DEFINE_FALLBACK_SHADER( Sky, Sky_HDR_DX9 ) + +BEGIN_VS_SHADER( Sky_HDR_DX9, "Help for Sky_HDR_DX9 shader" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( HDRBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "base texture when running with HDR enabled" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "base texture (compressed) for hdr compression method A" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE0, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture0 for hdr compression method B" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE1, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture1 for hdr compression method B" ) + SHADER_PARAM( HDRCOMPRESSEDTEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "compressed base texture2 for hdr compression method B" ) + SHADER_PARAM_OVERRIDE( COLOR, SHADER_PARAM_TYPE_VEC3, "[ 1 1 1]", "color multiplier", SHADER_PARAM_NOT_EDITABLE ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 || g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "Sky_DX9"; + } + return 0; + } + + SHADER_INIT_PARAMS() + { + SET_FLAGS( MATERIAL_VAR_NOFOG ); + SET_FLAGS( MATERIAL_VAR_IGNOREZ ); + } + SHADER_INIT + { + // First figure out if sampler zero wants to be sRGB + int nSamplerZeroFlags = 0; + if ( (params[HDRCOMPRESSEDTEXTURE]->IsDefined()) && mat_use_compressed_hdr_textures.GetBool() ) + { + nSamplerZeroFlags = 0; + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + nSamplerZeroFlags = 0; + } + else + { + nSamplerZeroFlags = TEXTUREFLAGS_SRGB; + + if ( params[HDRBASETEXTURE]->IsDefined() && params[HDRBASETEXTURE]->IsTexture() ) + { + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( ( fmt == IMAGE_FORMAT_RGBA16161616F ) || ( fmt == IMAGE_FORMAT_RGBA16161616 ) ) + { + nSamplerZeroFlags = 0; + } + } + } + } + + // Next, figure out which texture will be on sampler zero + int nSampler0 = HDRCOMPRESSEDTEXTURE; + if ( params[HDRCOMPRESSEDTEXTURE]->IsDefined() && mat_use_compressed_hdr_textures.GetBool() ) + { + nSampler0 = HDRCOMPRESSEDTEXTURE; + } + else + { + if ( params[HDRCOMPRESSEDTEXTURE0]->IsDefined() ) + { + nSampler0 = HDRCOMPRESSEDTEXTURE0; + } + else + { + nSampler0 = HDRBASETEXTURE; + } + } + + // Load the appropriate textures, making sure that the texture set on sampler 0 is sRGB if necessary + if ( params[HDRCOMPRESSEDTEXTURE]->IsDefined() && (mat_use_compressed_hdr_textures.GetBool() ) ) + { + LoadTexture( HDRCOMPRESSEDTEXTURE, HDRCOMPRESSEDTEXTURE == nSampler0 ? nSamplerZeroFlags : 0 ); + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE0, HDRCOMPRESSEDTEXTURE0 == nSampler0 ? nSamplerZeroFlags : 0 ); + if ( params[HDRCOMPRESSEDTEXTURE1]->IsDefined() ) + { + LoadTexture( HDRCOMPRESSEDTEXTURE1, HDRCOMPRESSEDTEXTURE1 == nSampler0 ? nSamplerZeroFlags : 0 ); + } + if ( params[HDRCOMPRESSEDTEXTURE2]->IsDefined()) + { + LoadTexture( HDRCOMPRESSEDTEXTURE2, HDRCOMPRESSEDTEXTURE2 == nSampler0 ? nSamplerZeroFlags : 0 ); + } + } + else + { + if ( params[HDRBASETEXTURE]->IsDefined() ) + { + LoadTexture( HDRBASETEXTURE, HDRBASETEXTURE == nSampler0 ? nSamplerZeroFlags : 0 ); + } + } + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + SetInitialShadowState(); + +// pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, NULL, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sky_vs20 ); + SET_STATIC_VERTEX_SHADER( sky_vs20 ); + + if ( (params[HDRCOMPRESSEDTEXTURE]->IsDefined()) && + mat_use_compressed_hdr_textures.GetBool() ) + { + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + } + } + else + { + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER1,false); + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER2,false); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + } + } + else + { + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ((fmt==IMAGE_FORMAT_RGBA16161616F) || (fmt==IMAGE_FORMAT_RGBA16161616)) + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,false); + else + pShaderShadow->EnableSRGBRead(SHADER_SAMPLER0,true); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20b ); + SET_STATIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sky_ps20 ); + SET_STATIC_PIXEL_SHADER( sky_ps20 ); + } + } + } + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + + DYNAMIC_STATE + { + DECLARE_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( sky_vs20 ); + + // Texture coord transform + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BASETEXTURETRANSFORM ); + + float c0[4]={1,1,1,1}; + if (params[COLOR]->IsDefined()) + { + memcpy(c0,params[COLOR]->GetVecValue(),3*sizeof(float)); + } + if ( + params[HDRCOMPRESSEDTEXTURE]->IsDefined() && + mat_use_compressed_hdr_textures.GetBool() + ) + { + // set up data needs for pixel shader interpolation + ITexture *txtr=params[HDRCOMPRESSEDTEXTURE]->GetTextureValue(); + float w=txtr->GetActualWidth(); + float h=txtr->GetActualHeight(); + float FUDGE=0.01/max(w,h); // per ATI + float c1[4]={0.5/w-FUDGE, 0.5/h-FUDGE, w, h }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + BindTexture( SHADER_SAMPLER0, HDRCOMPRESSEDTEXTURE, FRAME ); + c0[0]*=8.0; + c0[1]*=8.0; + c0[2]*=8.0; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_rgbs_ps20 ); + } + } + else + { + float c1[4]={0,0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, c1); + + if (params[HDRCOMPRESSEDTEXTURE0]->IsDefined() ) + { + BindTexture( SHADER_SAMPLER0, HDRCOMPRESSEDTEXTURE0, FRAME ); + BindTexture( SHADER_SAMPLER1, HDRCOMPRESSEDTEXTURE1, FRAME ); + BindTexture( SHADER_SAMPLER2, HDRCOMPRESSEDTEXTURE2, FRAME ); + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_hdr_compressed_ps20 ); + } + + } + else + { + BindTexture( SHADER_SAMPLER0, HDRBASETEXTURE, FRAME ); + ITexture *txtr=params[HDRBASETEXTURE]->GetTextureValue(); + ImageFormat fmt=txtr->GetImageFormat(); + if ( + (fmt==IMAGE_FORMAT_RGBA16161616) || + ( (fmt==IMAGE_FORMAT_RGBA16161616F) && + (g_pHardwareConfig->GetHDRType()==HDR_TYPE_INTEGER)) + ) + { + c0[0]*=16.0; + c0[1]*=16.0; + c0[2]*=16.0; + } + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( sky_ps20 ); + } + } + } + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + } + Draw( ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/sky_ps2x.fxc b/sp/src/materialsystem/stdshaders/sky_ps2x.fxc new file mode 100644 index 00000000..563fddbb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_ps2x.fxc @@ -0,0 +1,27 @@ +// HDRFIXME: Make this work with nonHDR +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +#include "common_ps_fxc.h" + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +sampler BaseTextureSampler : register( s0 ); +HALF4 InputScale : register( c0 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + HALF4 color = tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + color.rgb *= InputScale.rgb; + + // This is never fogged. + return FinalOutput( color, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR, WRITE_DEPTH_TO_DESTALPHA, 1e20 ); //when writing depth to dest alpha, write a value guaranteed to saturate +} diff --git a/sp/src/materialsystem/stdshaders/sky_vs20.fxc b/sp/src/materialsystem/stdshaders/sky_vs20.fxc new file mode 100644 index 00000000..1bc2a3e6 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sky_vs20.fxc @@ -0,0 +1,64 @@ +#include "common_vs_fxc.h" + +const float4 g_vTextureSizeInfo : register( SHADER_SPECIFIC_CONST_0 ); +const float4 g_mBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + //SHADER_SPECIFIC_CONST_2 + +#define TEXEL_XINCR (g_vTextureSizeInfo.x) +#define TEXEL_YINCR (g_vTextureSizeInfo.y) +#define U_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.z) +#define V_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.w) + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + +//#if defined( _X360 ) +// float2 baseTexCoord : TEXCOORD0; +//#else + float2 baseTexCoord00 : TEXCOORD0; + float2 baseTexCoord01 : TEXCOORD1; + float2 baseTexCoord10 : TEXCOORD2; + float2 baseTexCoord11 : TEXCOORD3; + float2 baseTexCoord_In_Pixels: TEXCOORD4; +//#endif +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.projPos = mul( v.vPos, cModelViewProj ); + + float4 vTexCoordInput = { v.vTexCoord0.x, v.vTexCoord0.y, 0.0f, 1.0f }; + float2 vTexCoord; + vTexCoord.x = dot( vTexCoordInput.xyzw, g_mBaseTexCoordTransform[0] ); + vTexCoord.y = dot( vTexCoordInput.xyzw, g_mBaseTexCoordTransform[1] ); + +//#if defined( _X360 ) +// o.baseTexCoord.xy = vTexCoord.xy; +//#else + // Compute quantities needed for pixel shader texture lerping + o.baseTexCoord00.x = vTexCoord.x - TEXEL_XINCR; + o.baseTexCoord00.y = vTexCoord.y - TEXEL_YINCR; + o.baseTexCoord10.x = vTexCoord.x + TEXEL_XINCR; + o.baseTexCoord10.y = vTexCoord.y - TEXEL_YINCR; + + o.baseTexCoord01.x = vTexCoord.x - TEXEL_XINCR; + o.baseTexCoord01.y = vTexCoord.y + TEXEL_YINCR; + o.baseTexCoord11.x = vTexCoord.x + TEXEL_XINCR; + o.baseTexCoord11.y = vTexCoord.y + TEXEL_YINCR; + + o.baseTexCoord_In_Pixels.xy = o.baseTexCoord00.xy; + o.baseTexCoord_In_Pixels.x *= U_TO_PIXEL_COORD_SCALE; + o.baseTexCoord_In_Pixels.y *= V_TO_PIXEL_COORD_SCALE; +//#endif + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/sprite.cpp b/sp/src/materialsystem/stdshaders/sprite.cpp new file mode 100644 index 00000000..77934f57 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite.cpp @@ -0,0 +1,379 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +// Implementation of the sprite shader +//=============================================================================// + +#include "BaseVSShader.h" +#include +#include "const.h" +#include "sprite_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX8 ) + +BEGIN_VS_SHADER( Sprite_DX8, + "Help for Sprite_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "Sprite_DX6"; + return 0; + } + + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + // FIXME: Not sure if this is the best solution, but it's a very] + // easy one. When graphics aren't enabled, we oftentimes need to get + // at the parameters of a shader. Therefore, we must set the default + // values in a separate phase from when we load resources. + + if (!params[ALPHA]->IsDefined()) + params[ ALPHA ]->SetFloatValue( 1.0f ); + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + +#define SHADER_USE_VERTEX_COLOR 1 +#define SHADER_USE_CONSTANT_COLOR 2 + + void SetSpriteCommonShadowState( unsigned int shaderFlags ) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + unsigned int flags = VERTEX_POSITION; + if( shaderFlags & SHADER_USE_VERTEX_COLOR ) + { + flags |= VERTEX_COLOR; + } + s_pShaderShadow->VertexShaderVertexFormat( flags, 1, 0, 0 ); + + sprite_vs11_Static_Index vshIndex; + bool vertexColor = ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false; + vshIndex.SetVERTEXCOLOR( vertexColor ); + s_pShaderShadow->SetVertexShader( "sprite_vs11", vshIndex.GetIndex() ); + + // "VERTEXCOLOR" "0..1" + // "CONSTANTCOLOR" "0..1" + int pshIndex = 0; + if ( shaderFlags & SHADER_USE_VERTEX_COLOR ) pshIndex |= 0x1; + if ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) pshIndex |= 0x2; + s_pShaderShadow->SetPixelShader( "sprite_ps11", pshIndex ); + } + + void SetSpriteCommonDynamicState( unsigned int shaderFlags ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + sprite_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( 0 ); + vshIndex.SetDOWATERFOG( fogIndex ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + s_pShaderAPI->SetPixelShaderIndex( 0 ); + if ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) + { + SetPixelShaderConstant( 0, COLOR, ALPHA ); + } + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + // identity base texture transorm + float ident[2][4] = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f } + }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &ident[0][0], 2 ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + FogToFogColor(); + SetSpriteCommonShadowState( 0 ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( 0 ); + } + Draw(); + break; + case kRenderTransColor: + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_ALWAYS ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlpha: + // untested cut and past from kRenderTransAlphaAdd . . same as first pass of that. + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + + SHADOW_STATE + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + + case kRenderTransAdd: + { + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( flags ); + } + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + sprite_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( 0 ); + vshIndex.SetDOWATERFOG( fogIndex ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + + + // identity base texture transorm + float ident[2][4] = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f } + }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &ident[0][0], 2 ); + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + sprite_vs11_Dynamic_Index vshIndex; + vshIndex.SetSKINNING( 0 ); + vshIndex.SetDOWATERFOG( fogIndex ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + + s_pShaderAPI->SetPixelShaderIndex( 0 ); + + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + + // identity base texture transorm + float ident[2][4] = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f } + }; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, &ident[0][0], 2 ); + } + Draw(); + } + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/sprite_dx6.cpp b/sp/src/materialsystem/stdshaders/sprite_dx6.cpp new file mode 100644 index 00000000..15ba22a6 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite_dx6.cpp @@ -0,0 +1,289 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +// Implementation of the sprite shader +//=============================================================================// + +#include "shaderlib/cshader.h" +#include +#include "const.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX6 ) + +BEGIN_SHADER( Sprite_DX6, + "Help for Sprite_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + // FIXME: Not sure if this is the best solution, but it's a very] + // easy one. When graphics aren't enabled, we oftentimes need to get + // at the parameters of a shader. Therefore, we must set the default + // values in a separate phase from when we load resources. + + if (!params[ALPHA]->IsDefined()) + params[ ALPHA ]->SetFloatValue( 1.0f ); + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransColor: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransAlpha: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + + case kRenderTransAdd: + SHADOW_STATE + { + if( params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + } + else + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + } + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + FogToBlack(); + } + DYNAMIC_STATE + { + SetColorState( COLOR, ALPHA ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + SHADOW_STATE + { + if( params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + } + else + { + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_COLOR ); + } + pShaderShadow->EnableConstantColor( true ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + FogToBlack(); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + pShaderAPI->Color3f( flFade * frameBlendAlpha, flFade * frameBlendAlpha, flFade * frameBlendAlpha ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + pShaderAPI->Color3f( flFade * frameBlendAlpha, flFade * frameBlendAlpha, flFade * frameBlendAlpha ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + } + Draw(); + } + + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/sprite_dx9.cpp b/sp/src/materialsystem/stdshaders/sprite_dx9.cpp new file mode 100644 index 00000000..0a0bb9f4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite_dx9.cpp @@ -0,0 +1,490 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "BaseVSShader.h" +#include +#include "const.h" + +#include "cpp_shader_constant_register_map.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#include "sprite_vs20.inc" +#include "sprite_ps20.inc" +#include "sprite_ps20b.inc" + +// WARNING! Change these in engine/SpriteGn.h if you change them here! +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + + +DEFINE_FALLBACK_SHADER( Sprite, Sprite_DX9 ) + +BEGIN_VS_SHADER( Sprite_DX9, + "Help for Sprite_DX9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( SPRITEORIGIN, SHADER_PARAM_TYPE_VEC3, "[0 0 0]", "sprite origin" ) + SHADER_PARAM( SPRITEORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "sprite orientation" ) + SHADER_PARAM( SPRITERENDERMODE, SHADER_PARAM_TYPE_INTEGER, "0", "sprite rendermode" ) + SHADER_PARAM( IGNOREVERTEXCOLORS, SHADER_PARAM_TYPE_BOOL, "1", "ignore vertex colors" ) + SHADER_PARAM( NOSRGB, SHADER_PARAM_TYPE_BOOL, "0", "do not operate in srgb space" ) + SHADER_PARAM( HDRCOLORSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "hdr color scale" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 90) + return "Sprite_DX8"; + return 0; + } + SHADER_INIT_PARAMS() + { + // FIXME: This can share code with sprite.cpp + if (!params[ALPHA]->IsDefined()) + { + params[ALPHA]->SetFloatValue( 1.0f ); + } + + if (!params[HDRCOLORSCALE]->IsDefined()) + { + params[HDRCOLORSCALE]->SetFloatValue( 1.0f ); + } + + if ( !params[NOSRGB]->IsDefined() ) + { + // Disable sRGB reads and writes by default + params[NOSRGB]->SetIntValue( 1 ); + } + + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + SET_FLAGS( MATERIAL_VAR_VERTEXCOLOR ); + SET_FLAGS( MATERIAL_VAR_VERTEXALPHA ); + + // translate from a string orientation to an enumeration + if (params[SPRITEORIENTATION]->IsDefined()) + { + const char *orientationString = params[SPRITEORIENTATION]->GetStringValue(); + if( stricmp( orientationString, "parallel_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + else if( stricmp( orientationString, "facing_upright" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_FACING_UPRIGHT ); + } + else if( stricmp( orientationString, "vp_parallel" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL ); + } + else if( stricmp( orientationString, "oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_ORIENTED ); + } + else if( stricmp( orientationString, "vp_parallel_oriented" ) == 0 ) + { + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_ORIENTED ); + } + else + { + Warning( "error with $spriteOrientation\n" ); + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + else + { + // default case + params[SPRITEORIENTATION]->SetIntValue( SPR_VP_PARALLEL_UPRIGHT ); + } + } + + SHADER_INIT + { + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + LoadTexture( BASETEXTURE, bSRGB ? TEXTUREFLAGS_SRGB : 0 ); + } + +#define SHADER_USE_VERTEX_COLOR 1 +#define SHADER_USE_CONSTANT_COLOR 2 + + void SetSpriteCommonShadowState( unsigned int shaderFlags ) + { + IShaderShadow *pShaderShadow = s_pShaderShadow; + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bSRGB ); + + // Only enabling this on OSX() - it causes GL mode's light glow sprites to be much darker vs. D3D9 under Linux/Win GL. + bool bSRGBOutputAdapter = ( IsOSX() && !g_pHardwareConfig->FakeSRGBWrite() ) && !bSRGB; + + unsigned int flags = VERTEX_POSITION; + if( shaderFlags & SHADER_USE_VERTEX_COLOR ) + { + flags |= VERTEX_COLOR; + } + int numTexCoords = 1; + s_pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + DECLARE_STATIC_VERTEX_SHADER( sprite_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_VERTEX_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_STATIC_PIXEL_SHADER( sprite_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTCOLOR, ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB_OUTPUT_ADAPTER, bSRGBOutputAdapter ); + SET_STATIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( sprite_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, ( shaderFlags & SHADER_USE_VERTEX_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( CONSTANTCOLOR, ( shaderFlags & SHADER_USE_CONSTANT_COLOR ) ? true : false ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB, bSRGB ); + SET_STATIC_PIXEL_SHADER( sprite_ps20 ); + } + + // OSX always has to sRGB write (don't do this on Linux/Win GL - it causes glow sprites to be way too dark) + s_pShaderShadow->EnableSRGBWrite( bSRGB || ( IsOSX() && !g_pHardwareConfig->FakeSRGBWrite() ) ); + } + + void SetSpriteCommonDynamicState( unsigned int shaderFlags ) + { + IShaderDynamicAPI *pShaderAPI = s_pShaderAPI; + bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0; + + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if( shaderFlags & SHADER_USE_CONSTANT_COLOR ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 0, COLOR, ALPHA ); + else + SetPixelShaderConstant( 0, COLOR, ALPHA ); + } + + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + + SHADER_DRAW + { + bool bSRGB = params[NOSRGB]->GetIntValue() == 0; + + SHADOW_STATE + { + pShaderShadow->EnableCulling( false ); + } + + switch( params[SPRITERENDERMODE]->GetIntValue() ) + { + case kRenderNormal: + SHADOW_STATE + { + FogToFogColor(); + + SetSpriteCommonShadowState( 0 ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( 0 ); + } + Draw(); + break; + case kRenderTransColor: + case kRenderTransTexture: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderGlow: + case kRenderWorldGlow: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlpha: + // untested cut and past from kRenderTransAlphaAdd . . same as first pass of that. + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + case kRenderTransAlphaAdd: + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + FogToFogColor(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + + SHADOW_STATE + { + SetInitialShadowState(); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( SHADER_USE_VERTEX_COLOR ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( SHADER_USE_VERTEX_COLOR ); + } + Draw(); + break; + + case kRenderTransAdd: + { + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + SetSpriteCommonDynamicState( flags ); + } + } + Draw(); + break; + case kRenderTransAddFrameBlend: + { + float flFrame = params[FRAME]->GetFloatValue(); + float flFade = params[ALPHA]->GetFloatValue(); + unsigned int flags = SHADER_USE_CONSTANT_COLOR; + if( !params[ IGNOREVERTEXCOLORS ]->GetIntValue() ) + { + flags |= SHADER_USE_VERTEX_COLOR; + } + SHADOW_STATE + { + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = 1.0f - ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + BindTexture( SHADER_SAMPLER0, pTexture, ( int )flFrame ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + float color[4]; + if ( bSRGB ) + color[0] = color[1] = color[2] = GammaToLinear( flFade * frameBlendAlpha ); + else + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + Draw(); + SHADOW_STATE + { + FogToBlack(); + + SetSpriteCommonShadowState( flags ); + } + DYNAMIC_STATE + { + float frameBlendAlpha = ( flFrame - ( int )flFrame ); + ITexture *pTexture = params[BASETEXTURE]->GetTextureValue(); + int numAnimationFrames = pTexture->GetNumAnimationFrames(); + BindTexture( SHADER_SAMPLER0, pTexture, ( ( int )flFrame + 1 ) % numAnimationFrames ); + + MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + DECLARE_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER( sprite_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( sprite_ps20 ); + } + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + float color[4]; + if ( bSRGB ) + color[0] = color[1] = color[2] = GammaToLinear( flFade * frameBlendAlpha ); + else + color[0] = color[1] = color[2] = flFade * frameBlendAlpha; + color[3] = 1.0f; + s_pShaderAPI->SetPixelShaderConstant( 0, color ); + if( IsHDREnabled() ) + { + if ( bSRGB ) + SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE ); + else + SetPixelShaderConstant( 1, HDRCOLORSCALE ); + } + } + Draw(); + } + + break; + default: + ShaderWarning( "shader Sprite: Unknown sprite render mode\n" ); + break; + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/sprite_ps11.psh b/sp/src/materialsystem/stdshaders/sprite_ps11.psh new file mode 100644 index 00000000..5f5def5b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite_ps11.psh @@ -0,0 +1,15 @@ +; STATIC: "VERTEXCOLOR" "0..1" +; STATIC: "CONSTANTCOLOR" "0..1" + +ps.1.1 + +tex t0 +mov r0, t0 + +#if VERTEXCOLOR +mul r0, r0, v0 +#endif + +#if CONSTANTCOLOR +mul r0, r0, c0 +#endif \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/sprite_ps2x.fxc b/sp/src/materialsystem/stdshaders/sprite_ps2x.fxc new file mode 100644 index 00000000..83a7ab08 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite_ps2x.fxc @@ -0,0 +1,61 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "CONSTANTCOLOR" "0..1" +// STATIC: "HDRTYPE" "0..2" +// STATIC: "SRGB" "0..1" +// STATIC: "SRGB_OUTPUT_ADAPTER" "0..1" [ps20b] + +// DYNAMIC: "HDRENABLED" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +const HALF4 g_Color : register( c0 ); +const float g_HDRColorScale : register( c1 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +sampler TexSampler : register( s0 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result, sample = tex2D( TexSampler, i.baseTexCoord ); + +#if VERTEXCOLOR + sample *= i.color; +#endif + +#if CONSTANTCOLOR + sample *= g_Color; +#endif + +#if HDRTYPE && HDRENABLED + sample.xyz *= g_HDRColorScale; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); +#if SRGB + result = FinalOutput( sample, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +#else + result = FinalOutput( sample, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_GAMMA ); +#endif + + // On Posix, we're being forced through a linear-to-gamma curve but don't want it, so we do the opposite here first +#if SRGB_OUTPUT_ADAPTER + result = GammaToLinear( result ); +#endif + + return result; +} + diff --git a/sp/src/materialsystem/stdshaders/sprite_vs11.vsh b/sp/src/materialsystem/stdshaders/sprite_vs11.vsh new file mode 100644 index 00000000..5ffa45f1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite_vs11.vsh @@ -0,0 +1,9 @@ +vs.1.1 + +# STATIC: "VERTEXCOLOR" "0..1" +# DYNAMIC: "SKINNING" "0..0" +# DYNAMIC: "DOWATERFOG" "0..1" + +#include "UnlitGeneric_inc.vsh" + +&UnlitGeneric( 0, 0, 0, 0, $VERTEXCOLOR ); diff --git a/sp/src/materialsystem/stdshaders/sprite_vs20.fxc b/sp/src/materialsystem/stdshaders/sprite_vs20.fxc new file mode 100644 index 00000000..5e427c19 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/sprite_vs20.fxc @@ -0,0 +1,65 @@ +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "SRGB" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vColor : COLOR0; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; +#endif + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + // Transform into projection space + float4 projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = projPos; + projPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, projPos.z ); + +#if !defined( _X360 ) + o.fog = CalcFog( worldPos, projPos, g_FogType ); +#endif + if ( g_bVertexColor ) + { + // Assume that this is unlitgeneric if you are using vertex color. +#if SRGB + o.color.rgba = GammaToLinear( v.vColor.rgba ); +#else + o.color.rgba = v.vColor.rgba; +#endif + } + + // Base texture coordinates + o.baseTexCoord.xy = v.vTexCoord0.xy; + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/spritecard.cpp b/sp/src/materialsystem/stdshaders/spritecard.cpp new file mode 100644 index 00000000..850c357a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/spritecard.cpp @@ -0,0 +1,484 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: shader for drawing sprites as cards, with animation frame lerping +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +// STDSHADER_DX9_DLL_EXPORT +#include "spritecard_ps20.inc" +#include "spritecard_ps20b.inc" +#include "spritecard_vs20.inc" +#include "splinecard_vs20.inc" + +#if SUPPORT_DX8 +// STDSHADER_DX8_DLL_EXPORT +#include "spritecard_vs11.inc" +#include "spritecard_ps11.inc" +#include "splinecard_vs11.inc" +#endif + +#include "tier0/icommandline.h" //command line + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define DEFAULT_PARTICLE_FEATHERING_ENABLED 1 + +#ifdef STDSHADER_DX8_DLL_EXPORT +DEFINE_FALLBACK_SHADER( Spritecard, Spritecard_DX8 ) +#endif + +int GetDefaultDepthFeatheringValue( void ) //Allow the command-line to go against the default soft-particle value +{ + static int iRetVal = -1; + + if( iRetVal == -1 ) + { +# if( DEFAULT_PARTICLE_FEATHERING_ENABLED == 1 ) + { + if( CommandLine()->CheckParm( "-softparticlesdefaultoff" ) ) + iRetVal = 0; + else + iRetVal = 1; + } +# else + { + if( CommandLine()->CheckParm( "-softparticlesdefaulton" ) ) + iRetVal = 1; + else + iRetVal = 0; + } +# endif + } + + // On low end parts on the Mac, we reduce particles and shut off depth blending here + static ConVarRef mat_reduceparticles( "mat_reduceparticles" ); + if ( mat_reduceparticles.GetBool() ) + { + iRetVal = 0; + } + + return iRetVal; +} + + +#ifdef STDSHADER_DX9_DLL_EXPORT +BEGIN_VS_SHADER_FLAGS( Spritecard, "Help for Spritecard", SHADER_NOT_EDITABLE ) +#else +BEGIN_VS_SHADER_FLAGS( Spritecard_DX8, "Help for Spritecard_DX8", SHADER_NOT_EDITABLE ) +#endif + +BEGIN_SHADER_PARAMS +SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries" ) +SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) +SHADER_PARAM( ORIENTATION, SHADER_PARAM_TYPE_INTEGER, "0", "0 = always face camera, 1 = rotate around z, 2= parallel to ground" ) +SHADER_PARAM( ADDBASETEXTURE2, SHADER_PARAM_TYPE_FLOAT, "0.0", "amount to blend second texture into frame by" ) +SHADER_PARAM( OVERBRIGHTFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "overbright factor for texture. For HDR effects.") +SHADER_PARAM( DUALSEQUENCE, SHADER_PARAM_TYPE_INTEGER, "0", "blend two separate animated sequences.") +SHADER_PARAM( SEQUENCE_BLEND_MODE, SHADER_PARAM_TYPE_INTEGER, "0", "defines the blend mode between the images un dual sequence particles. 0 = avg, 1=alpha from first, rgb from 2nd, 2= first over second" ) +SHADER_PARAM( MAXLUMFRAMEBLEND1, SHADER_PARAM_TYPE_INTEGER, "0", "instead of blending between animation frames for the first sequence, select pixels based upon max luminance" ) +SHADER_PARAM( MAXLUMFRAMEBLEND2, SHADER_PARAM_TYPE_INTEGER, "0", "instead of blending between animation frames for the 2nd sequence, select pixels based upon max luminance" ) +SHADER_PARAM( RAMPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "if specified, then the red value of the image is used to index this ramp to produce the output color" ) +SHADER_PARAM( ZOOMANIMATESEQ2, SHADER_PARAM_TYPE_FLOAT, "1.0", "amount to gradually zoom between frames on the second sequence. 2.0 will double the size of a frame over its lifetime.") +SHADER_PARAM( EXTRACTGREENALPHA, SHADER_PARAM_TYPE_INTEGER, "0", "grayscale data sitting in green/alpha channels") +SHADER_PARAM( ADDOVERBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "use ONE:INVSRCALPHA blending") +SHADER_PARAM( ADDSELF, SHADER_PARAM_TYPE_FLOAT, "0.0", "amount of base texture to additively blend in" ) +SHADER_PARAM( BLENDFRAMES, SHADER_PARAM_TYPE_BOOL, "1", "whether or not to smoothly blend between animated frames" ) +SHADER_PARAM( MINSIZE, SHADER_PARAM_TYPE_FLOAT, "0.0", "minimum screen fractional size of particle") +SHADER_PARAM( STARTFADESIZE, SHADER_PARAM_TYPE_FLOAT, "10.0", "screen fractional size to start fading particle out") +SHADER_PARAM( ENDFADESIZE, SHADER_PARAM_TYPE_FLOAT, "20.0", "screen fractional size to finish fading particle out") +SHADER_PARAM( MAXSIZE, SHADER_PARAM_TYPE_FLOAT, "20.0", "maximum screen fractional size of particle") +SHADER_PARAM( USEINSTANCING, SHADER_PARAM_TYPE_BOOL, "1", "whether to use GPU vertex instancing (submit 1 vert per particle quad)") +SHADER_PARAM( SPLINETYPE, SHADER_PARAM_TYPE_INTEGER, "0", "spline type 0 = none, 1=ctamull rom") +SHADER_PARAM( MAXDISTANCE, SHADER_PARAM_TYPE_FLOAT, "100000.0", "maximum distance to draw particles at") +SHADER_PARAM( FARFADEINTERVAL, SHADER_PARAM_TYPE_FLOAT, "400.0", "interval over which to fade out far away particles") +END_SHADER_PARAMS + +SHADER_INIT_PARAMS() +{ + INIT_FLOAT_PARM( MAXDISTANCE, 100000.0); + INIT_FLOAT_PARM( FARFADEINTERVAL, 400.0); + INIT_FLOAT_PARM( MAXSIZE, 20.0 ); + INIT_FLOAT_PARM( ENDFADESIZE, 20.0 ); + INIT_FLOAT_PARM( STARTFADESIZE, 10.0 ); + INIT_FLOAT_PARM( DEPTHBLENDSCALE, 50.0 ); + INIT_FLOAT_PARM( OVERBRIGHTFACTOR, 1.0 ); + INIT_FLOAT_PARM( ADDBASETEXTURE2, 0.0 ); + INIT_FLOAT_PARM( ADDSELF, 0.0 ); + INIT_FLOAT_PARM( ZOOMANIMATESEQ2, 0.0 ); + + if ( !params[DEPTHBLEND]->IsDefined() ) + { + params[ DEPTHBLEND ]->SetIntValue( GetDefaultDepthFeatheringValue() ); + } + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + params[ DEPTHBLEND ]->SetIntValue( 0 ); + } + if ( !params[DUALSEQUENCE]->IsDefined() ) + { + params[DUALSEQUENCE]->SetIntValue( 0 ); + } + if ( !params[MAXLUMFRAMEBLEND1]->IsDefined() ) + { + params[MAXLUMFRAMEBLEND1]->SetIntValue( 0 ); + } + if ( !params[MAXLUMFRAMEBLEND2]->IsDefined() ) + { + params[MAXLUMFRAMEBLEND2]->SetIntValue( 0 ); + } + if ( !params[EXTRACTGREENALPHA]->IsDefined() ) + { + params[EXTRACTGREENALPHA]->SetIntValue( 0 ); + } + if ( !params[ADDOVERBLEND]->IsDefined() ) + { + params[ADDOVERBLEND]->SetIntValue( 0 ); + } + if ( !params[BLENDFRAMES]->IsDefined() ) + { + params[ BLENDFRAMES ]->SetIntValue( 1 ); + } + if ( !params[USEINSTANCING]->IsDefined() ) + { + params[ USEINSTANCING ]->SetIntValue( IsX360() ? 1 : 0 ); + } + SET_FLAGS2( MATERIAL_VAR2_IS_SPRITECARD ); +} + +SHADER_FALLBACK +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "SpriteCard_DX8"; +#endif +#ifdef STDSHADER_DX8_DLL_EXPORT + // STDSHADER_DX8_DLL_EXPORT + if ( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "Wireframe"; +#endif + return 0; +} + +SHADER_INIT +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + const bool bDX8 = false; +#endif +#ifdef STDSHADER_DX8_DLL_EXPORT + const bool bDX8 = true; +#endif + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + if ( params[BASETEXTURE]->IsDefined() ) + { + bool bExtractGreenAlpha = false; + if ( params[EXTRACTGREENALPHA]->IsDefined() ) + { + bExtractGreenAlpha = params[EXTRACTGREENALPHA]->GetIntValue() != 0; + } + + LoadTexture( BASETEXTURE, !bExtractGreenAlpha && !bDX8 ? TEXTUREFLAGS_SRGB : 0 ); + } + if ( params[RAMPTEXTURE]->IsDefined() ) + { + LoadTexture( RAMPTEXTURE, TEXTUREFLAGS_SRGB ); + } +} + +SHADER_DRAW +{ +#ifdef STDSHADER_DX9_DLL_EXPORT + const bool bDX8 = false; +#endif +#ifdef STDSHADER_DX8_DLL_EXPORT + const bool bDX8 = true; +#endif + bool bUseRampTexture = (! bDX8 ) && ( params[RAMPTEXTURE]->IsDefined() ); + bool bZoomSeq2 = (! bDX8 ) && ( ( params[ZOOMANIMATESEQ2]->GetFloatValue()) > 1.0 ); + bool bDepthBlend = (! bDX8 ) && ( params[DEPTHBLEND]->GetIntValue() != 0 ); + bool bAdditive2ndTexture = params[ADDBASETEXTURE2]->GetFloatValue() != 0.0; + int nSplineType = params[SPLINETYPE]->GetIntValue(); + + SHADOW_STATE + { + bool bSecondSequence = params[DUALSEQUENCE]->GetIntValue() != 0; + bool bAddOverBlend = params[ADDOVERBLEND]->GetIntValue() != 0; + bool bExtractGreenAlpha = (! bDX8 ) && ( params[EXTRACTGREENALPHA]->GetIntValue() != 0 ); + bool bBlendFrames = (! bDX8 ) && ( params[BLENDFRAMES]->GetIntValue() != 0 ); + if ( nSplineType ) + { + bBlendFrames = false; + } + bool bAddSelf = params[ADDSELF]->GetFloatValue() != 0.0; + bool bUseInstancing = IsX360() ? ( params[ USEINSTANCING ]->GetIntValue() != 0 ) : false; + if ( nSplineType ) + bUseInstancing = false; + + // draw back-facing because of yaw spin + pShaderShadow->EnableCulling( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + if ( bDX8 ) + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + if ( bAdditive2ndTexture && bDX8 ) + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + if ( bUseRampTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + + if ( bDepthBlend ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + + if ( bAdditive2ndTexture || bAddSelf ) + pShaderShadow->EnableAlphaTest( false ); + else + pShaderShadow->EnableAlphaTest( true ); + + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.01f ); + + if ( bAdditive2ndTexture || bAddOverBlend || bAddSelf ) + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + if ( IS_FLAG_SET(MATERIAL_VAR_ADDITIVE) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + } + + unsigned int flags = VERTEX_POSITION | VERTEX_COLOR; + static int s_TexCoordSize[8]={4, // 0 = sheet bounding uvs, frame0 + 4, // 1 = sheet bounding uvs, frame 1 + 4, // 2 = frame blend, rot, radius, ??? + 2, // 3 = corner identifier ( 0/0,1/0,1/1, 1/0 ) + 4, // 4 = texture 2 bounding uvs + 4, // 5 = second sequence bounding uvs, frame0 + 4, // 6 = second sequence bounding uvs, frame1 + 4, // 7 = second sequence frame blend, ?,?,? + }; + static int s_TexCoordSizeSpline[]={4, // 0 = sheet bounding uvs, frame0 + 4, // 1 = sheet bounding uvs, frame 1 + 4, // 2 = frame blend, rot, radius, ??? + 4, // 3 = corner identifier ( 0/0,1/0,1/1, 1/0 ) + 4, // 4 = texture 2 bounding uvs + 4, // 5 = second sequence bounding uvs, frame0 + 4, // 6 = second sequence bounding uvs, frame1 + 4, // 7 = second sequence frame blend, ?,?,? + }; + + int numTexCoords = 4; + if ( true /* bAdditive2ndTexture */ ) // there is no branch for 2nd texture in the VS! -henryg + { + numTexCoords = 5; + } + if ( bSecondSequence ) + { + // the whole shebang - 2 sequences, with a possible multi-image sequence first + numTexCoords = 8; + } + pShaderShadow->VertexShaderVertexFormat( flags, + numTexCoords, + nSplineType? s_TexCoordSizeSpline : s_TexCoordSize, 0 ); + + if ( bDX8 ) + { +#if SUPPORT_DX8 + if ( nSplineType ) + { + DECLARE_STATIC_VERTEX_SHADER( splinecard_vs11 ); + SET_STATIC_VERTEX_SHADER( splinecard_vs11 ); + } + else + { + DECLARE_STATIC_VERTEX_SHADER( spritecard_vs11 ); + if ( bSecondSequence ) + bAdditive2ndTexture = false; + SET_STATIC_VERTEX_SHADER_COMBO( DUALSEQUENCE, false ); + SET_STATIC_VERTEX_SHADER_COMBO( ZOOM_ANIMATE_SEQ2, false ); + SET_STATIC_VERTEX_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_VERTEX_SHADER( spritecard_vs11 ); + } + + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps11 ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( USEALPHAASRGB, bSecondSequence ); + SET_STATIC_PIXEL_SHADER( spritecard_ps11 ); +#endif + } + else + { + if ( nSplineType ) + { + DECLARE_STATIC_VERTEX_SHADER( splinecard_vs20 ); + SET_STATIC_VERTEX_SHADER( splinecard_vs20 ); + } + else + { + DECLARE_STATIC_VERTEX_SHADER( spritecard_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_VERTEX_SHADER_COMBO( ZOOM_ANIMATE_SEQ2, bZoomSeq2 ); + SET_STATIC_VERTEX_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_INSTANCING, bUseInstancing ); + SET_STATIC_VERTEX_SHADER( spritecard_vs20 ); + } + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( ANIMBLEND, bBlendFrames ); + SET_STATIC_PIXEL_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_PIXEL_SHADER_COMBO( SEQUENCE_BLEND_MODE, bSecondSequence ? params[SEQUENCE_BLEND_MODE]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND1, params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND2, bSecondSequence? params[MAXLUMFRAMEBLEND1]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORRAMP, bUseRampTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDepthBlend ); + SET_STATIC_PIXEL_SHADER( spritecard_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( spritecard_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDBASETEXTURE2, bAdditive2ndTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DUALSEQUENCE, bSecondSequence ); + SET_STATIC_PIXEL_SHADER_COMBO( ADDSELF, bAddSelf ); + SET_STATIC_PIXEL_SHADER_COMBO( ANIMBLEND, bBlendFrames ); + SET_STATIC_PIXEL_SHADER_COMBO( SEQUENCE_BLEND_MODE, bSecondSequence ? params[SEQUENCE_BLEND_MODE]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND1, params[MAXLUMFRAMEBLEND1]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MAXLUMFRAMEBLEND2, bSecondSequence? params[MAXLUMFRAMEBLEND1]->GetIntValue() : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( COLORRAMP, bUseRampTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( EXTRACTGREENALPHA, bExtractGreenAlpha ); + SET_STATIC_PIXEL_SHADER( spritecard_ps20 ); + } + + if ( !bDX8 ) + pShaderShadow->EnableSRGBWrite( true ); + + if( !bExtractGreenAlpha && !bDX8 ) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + if ( bDX8 ) // bind on 2nd sampelr so we can lerp + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + + if ( bDX8 && bAdditive2ndTexture ) + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + if ( bUseRampTexture && ( !bDX8 ) ) + { + BindTexture( SHADER_SAMPLER1, RAMPTEXTURE, FRAME ); + } + + if ( bDepthBlend ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + + LoadViewportTransformScaledIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10 ); + + int nOrientation = params[ORIENTATION]->GetIntValue(); + nOrientation = clamp( nOrientation, 0, 2 ); + + // We need these only when screen-orienting + if ( nOrientation == 0 ) + { + LoadModelViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 ); + LoadProjectionMatrixIntoVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 ); + } + + if ( bZoomSeq2 ) + { + float flZScale=1.0/(params[ZOOMANIMATESEQ2]->GetFloatValue()); + float C0[4]={ 0.5*(1.0+flZScale), flZScale, 0, 0 }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, C0, + ARRAYSIZE(C0)/4 ); + } + + // set fade constants in vsconsts 8 and 9 + float flMaxDistance = params[MAXDISTANCE]->GetFloatValue(); + float flStartFade = max( 1.0, flMaxDistance - params[FARFADEINTERVAL]->GetFloatValue() ); + + float VC0[8]={ params[MINSIZE]->GetFloatValue(), params[MAXSIZE]->GetFloatValue(), + params[STARTFADESIZE]->GetFloatValue(), params[ENDFADESIZE]->GetFloatValue(), + flStartFade, 1.0/(flMaxDistance-flStartFade), + 0,0 }; + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, VC0, ARRAYSIZE(VC0)/4 ); + + pShaderAPI->SetDepthFeatheringPixelShaderConstant( 2, params[DEPTHBLENDSCALE]->GetFloatValue() ); + + float C0[4]={ params[ADDBASETEXTURE2]->GetFloatValue(), + params[OVERBRIGHTFACTOR]->GetFloatValue(), + params[ADDSELF]->GetFloatValue(), + 0.0f }; + + if ( bDX8 && ( !bAdditive2ndTexture ) ) // deal with 0..1 limit for pix shader constants + { + C0[2] *= 0.25; + C0[1] *= 0.25; + } + + pShaderAPI->SetPixelShaderConstant( 0, C0, ARRAYSIZE(C0)/4 ); + + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { +#if SUPPORT_DX8 + if ( nSplineType ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( splinecard_vs11 ); + SET_DYNAMIC_VERTEX_SHADER( splinecard_vs11 ); + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( spritecard_vs11 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( ORIENTATION, nOrientation ); + SET_DYNAMIC_VERTEX_SHADER( spritecard_vs11 ); + } +#endif + } + else + { + if ( nSplineType ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( splinecard_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( splinecard_vs20 ); + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( spritecard_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( ORIENTATION, nOrientation ); + SET_DYNAMIC_VERTEX_SHADER( spritecard_vs20 ); + } + } + } + Draw( ); +} +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/spritecard_ps11.fxc b/sp/src/materialsystem/stdshaders/spritecard_ps11.fxc new file mode 100644 index 00000000..624362cb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/spritecard_ps11.fxc @@ -0,0 +1,72 @@ +// STATIC: "ADDBASETEXTURE2" "0..1" +// STATIC: "ADDSELF" "0..1" +// STATIC: "USEALPHAASRGB" "0..1" +// SKIP: $USEALPHAASRGB && $ADDSELF +// SKIP: $USEALPHAASRGB && $ADDBASETEXTURE2 + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD1; + float4 argbcolor : COLOR; + float4 blendfactor0 : TEXCOORD2; +#if ADDBASETEXTURE2 + float2 texCoord2 : TEXCOORD3; +#endif + float4 vScreenPos : TEXCOORD7; +}; + +sampler BaseTextureSampler : register( s0 ); + +#if ADDBASETEXTURE2 +sampler BaseTextureSampler2 : register( s3 ); +#endif + +sampler BaseTextureSampler1 : register( s1 ); +const float4 g_Parameters : register( c0 ); +const float4 g_ColorPowers : register( c1 ); + +#define fAdditiveBlendWeight g_Parameters.x +#define fOverbrightFactor g_Parameters.y +#define fAdditiveSelfBlendWeight g_Parameters.z +#define fSoftParticleBlendScale g_Parameters.w + +#pragma warning( disable : 4707 4704 ) +float4 main( PS_INPUT i ) : COLOR +{ + // Sample frames from texture 0 +#if ( ! ADDSELF ) && ( ! ADDBASETEXTURE2 ) + float4 baseTex0 = tex2D( BaseTextureSampler, i.texCoord0 ); + float4 baseTex1 = tex2D( BaseTextureSampler1, i.texCoord1 ); + float4 blended_rgb = lerp( baseTex0, baseTex1, i.blendfactor0.x ); +#else + float4 blended_rgb = tex2D( BaseTextureSampler, i.texCoord0 ); +#endif +#if USEALPHAASRGB + blended_rgb.rgb = blended_rgb.a; +#endif + +#if ADDBASETEXTURE2 + blended_rgb.a *= i.argbcolor.a; + + // In this case, we don't really want to pre-multiply by alpha + float4 color2 = tex2D( BaseTextureSampler2, i.texCoord2 ); + blended_rgb.rgb *= blended_rgb.a; + blended_rgb.rgb += fOverbrightFactor * fAdditiveBlendWeight * i.argbcolor.a * color2; + blended_rgb.rgb *= 2 * i.argbcolor.rgb; +#else +#if ADDSELF + blended_rgb.a *= i.argbcolor.a; + blended_rgb.rgb *= blended_rgb.a; + blended_rgb.rgb += fOverbrightFactor * 8 * fAdditiveSelfBlendWeight * blended_rgb; + blended_rgb.rgb *= 2 * i.argbcolor.rgb; +#else + blended_rgb *= i.argbcolor; +#endif +#endif + return blended_rgb; +} + diff --git a/sp/src/materialsystem/stdshaders/spritecard_ps2x.fxc b/sp/src/materialsystem/stdshaders/spritecard_ps2x.fxc new file mode 100644 index 00000000..1281d33a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/spritecard_ps2x.fxc @@ -0,0 +1,194 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "DUALSEQUENCE" "0..1" +// STATIC: "SEQUENCE_BLEND_MODE" "0..2" +// STATIC: "ADDBASETEXTURE2" "0..1" +// STATIC: "MAXLUMFRAMEBLEND1" "0..1" +// STATIC: "MAXLUMFRAMEBLEND2" "0..1" +// STATIC: "EXTRACTGREENALPHA" "0..1" +// STATIC: "COLORRAMP" "0..1" +// STATIC: "ANIMBLEND" "0..1" +// STATIC: "ADDSELF" "0..1" +// STATIC: "DEPTHBLEND" "0..1" [ps20b] + +#define COMBINE_MODE_AVERAGE 0 +#define COMBINE_MODE_USE_FIRST_AS_ALPHA_MASK_ON_SECOND 1 +#define COMBINE_MODE_USE_FIRST_OVER_SECOND 2 + +#define HDRTYPE HDR_TYPE_NONE +#include "common_ps_fxc.h" + +const float4 g_Parameters : register( c0 ); +const float4 g_DepthFeatheringConstants : register( c2 ); + +#define fAdditiveBlendWeight g_Parameters.x +#define fOverbrightFactor g_Parameters.y +#define fAdditiveSelfBlendWeight g_Parameters.z + +struct PS_INPUT +{ + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD1; + float4 argbcolor : COLOR; + float4 blendfactor0 : TEXCOORD2; +#if ADDBASETEXTURE2 + float2 texCoord2 : TEXCOORD3; +#endif +#if EXTRACTGREENALPHA + float4 blendfactor1 : TEXCOORD4; +#endif + +#if DUALSEQUENCE + float2 vSeq2TexCoord0 : TEXCOORD5; + float2 vSeq2TexCoord1 : TEXCOORD6; +#endif + +#if defined( REVERSE_DEPTH_ON_X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD7; +#else + float4 vScreenPos : TEXCOORD7; +#endif +}; + +sampler BaseTextureSampler : register( s0 ); +sampler ColorRampSampler : register( s1 ); +sampler DepthSampler : register( s2 ); + +float4 main( PS_INPUT i ) : COLOR +{ + bool bMaxLumFrameBlend1 = MAXLUMFRAMEBLEND1 ? true : false; + bool bMaxLumFrameBlend2 = MAXLUMFRAMEBLEND2 ? true : false; + bool bExtractGreenAlpha = EXTRACTGREENALPHA ? true : false; + bool bAddBaseTexture2 = ADDBASETEXTURE2 ? true : false; + bool bDualSequence = DUALSEQUENCE ? true : false; + bool bColorRamp = COLORRAMP ? true : false; +#ifdef DEPTHBLEND + bool bDepthBlend = DEPTHBLEND ? true : false; +#endif + int nSequenceBlendMode = SEQUENCE_BLEND_MODE; + + // Sample frames from texture 0 + float4 baseTex0 = tex2D( BaseTextureSampler, i.texCoord0 ); + + float4 baseTex1 = tex2D( BaseTextureSampler, i.texCoord1 ); + + // Blend by default (may override with bMaxLumFrameBlend1 or bExtractGreenAlpha) +#if ANIMBLEND + float4 blended_rgb = lerp( baseTex0, baseTex1, i.blendfactor0.x ); +#else + float4 blended_rgb = baseTex0; +#endif + + if ( bMaxLumFrameBlend1 ) + { + // Blend between animation frames based upon max luminance + float lum0 = dot( float3(.3, .59, .11), baseTex0.rgb * (1-i.blendfactor0.x)); + float lum1 = dot( float3(.3, .59, .11), baseTex1.rgb * i.blendfactor0.x); + + if ( lum0 > lum1 ) + blended_rgb = baseTex0; + else + blended_rgb = baseTex1; + } + else if( bExtractGreenAlpha ) + { +#if EXTRACTGREENALPHA + // Weight Green/Alphas from the two frames for a scalar result + blended_rgb = dot( baseTex0, i.blendfactor0 ) + dot( baseTex1, i.blendfactor1 ); +#endif + } + +#if DUALSEQUENCE + if ( bDualSequence ) + { + baseTex0 = tex2D( BaseTextureSampler, i.vSeq2TexCoord0 ); + baseTex1 = tex2D( BaseTextureSampler, i.vSeq2TexCoord1 ); + + // Blend by default (may override with bMaxLumFrameBlend2) + float4 rgb2 = lerp( baseTex0, baseTex1, i.blendfactor0.z ); + + if ( bMaxLumFrameBlend2 ) + { + // blend between animation frames based upon max luminance + float tlum0 = dot( float3(.3, .59, .11), baseTex0.rgb * (1-i.blendfactor0.x)); + float tlum1 = dot( float3(.3, .59, .11), baseTex1.rgb * i.blendfactor0.x); + + if ( tlum0 > tlum1 ) + rgb2 = baseTex0; + else + rgb2 = baseTex1; + } + + if ( nSequenceBlendMode == COMBINE_MODE_AVERAGE ) + { + blended_rgb = 0.5 * ( blended_rgb + rgb2 ); + } + else if ( nSequenceBlendMode == COMBINE_MODE_USE_FIRST_AS_ALPHA_MASK_ON_SECOND ) + { + blended_rgb.rgb = rgb2.rgb; + } + else if ( nSequenceBlendMode == COMBINE_MODE_USE_FIRST_OVER_SECOND ) + { + blended_rgb.rgb = lerp( blended_rgb.rgb, rgb2.rgb, rgb2.a ); + } + } // bDualSequence +#endif + + // Optional color ramp + if ( bColorRamp ) + { + blended_rgb.rgb = tex2D( ColorRampSampler, float2( blended_rgb.r, blended_rgb.g ) ); + } + + // Overbright + blended_rgb.rgb *= fOverbrightFactor; + + //Soft Particles FTW +# if (DEPTHBLEND == 1) +# if defined( _X360 ) + float fDepthBlend = DepthFeathering( DepthSampler, i.vScreenPos_ReverseZ.xy / i.vScreenPos_ReverseZ.w, i.vScreenPos_ReverseZ.z, i.vScreenPos_ReverseZ.w, g_DepthFeatheringConstants ); +# else + float fDepthBlend = DepthFeathering( DepthSampler, i.vScreenPos.xy / i.vScreenPos.w, i.vScreenPos.z, i.vScreenPos.w, g_DepthFeatheringConstants ); +# endif + i.argbcolor.a *= fDepthBlend; +# endif + + // Premultiply the alpha for a ONE:INVALPHA blend +#if ADDBASETEXTURE2 + if ( bAddBaseTexture2 ) + { + blended_rgb.a *= i.argbcolor.a; + + // In this case, we don't really want to pre-multiply by alpha + if ( !bColorRamp ) + { + blended_rgb.rgb *= blended_rgb.a; + } + + if ( bExtractGreenAlpha ) + { + blended_rgb.rgb += fAdditiveBlendWeight * i.argbcolor.a * blended_rgb.rgb; + } + else + { + blended_rgb.rgb += fOverbrightFactor * fAdditiveBlendWeight * i.argbcolor.a * tex2D( BaseTextureSampler, i.texCoord2 ); + } + + blended_rgb.rgb *= i.argbcolor.rgb; + } + else +#endif + { +#if ADDSELF + blended_rgb.a *= i.argbcolor.a; + blended_rgb.rgb *= blended_rgb.a; + blended_rgb.rgb += fOverbrightFactor * fAdditiveSelfBlendWeight * i.argbcolor.a * blended_rgb; + blended_rgb.rgb *= i.argbcolor.rgb; +#else + blended_rgb *= i.argbcolor; +#endif + } + + return FinalOutput( blended_rgb, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/sp/src/materialsystem/stdshaders/spritecard_vsxx.fxc b/sp/src/materialsystem/stdshaders/spritecard_vsxx.fxc new file mode 100644 index 00000000..6f670101 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/spritecard_vsxx.fxc @@ -0,0 +1,347 @@ +// STATIC: "ZOOM_ANIMATE_SEQ2" "0..1" [vs20] +// STATIC: "DUALSEQUENCE" "0..1" [vs20] +// STATIC: "EXTRACTGREENALPHA" "0..1" [vs20] + +// STATIC: "ZOOM_ANIMATE_SEQ2" "0..0" [vs11] +// STATIC: "DUALSEQUENCE" "0..0" [vs11] +// STATIC: "EXTRACTGREENALPHA" "0..0" [vs11] + +// STATIC: "USE_INSTANCING" "0..1" [vs20] +// DYNAMIC: "ORIENTATION" "0..2" + + +#include "common_vs_fxc.h" + +const float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0); +const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3); + +#if ZOOM_ANIMATE_SEQ2 +const float4 ScaleParms : register(SHADER_SPECIFIC_CONST_7); +#define OLDFRM_SCALE_START (ScaleParms.x) +#define OLDFRM_SCALE_END (ScaleParms.y) +#endif + +const float4 SizeParms : register(SHADER_SPECIFIC_CONST_8); +const float4 SizeParms2 : register(SHADER_SPECIFIC_CONST_9); +const float4 ViewportTransformScaled : register(SHADER_SPECIFIC_CONST_10); + +#define MINIMUM_SIZE_FACTOR (SizeParms.x) +#define MAXIMUM_SIZE_FACTOR (SizeParms.y) + +#define START_FADE_SIZE_FACTOR (SizeParms.z) +#define END_FADE_SIZE_FACTOR (SizeParms.w) + +// alpha fade w/ distance +#define START_FAR_FADE ( SizeParms2.x ) +#define FAR_FADE_FACTOR ( SizeParms2.y ) // alpha = 1-min(1,max(0, (dist-start_fade)*factor)) + +// Define stuff for instancing on 360 +#if ( defined( _X360 ) && defined( SHADER_MODEL_VS_2_0 ) ) +#define CONST_PC +#define VERTEX_INDEX_PARAM_360 ,int Index:INDEX +#define DO_INSTANCING 1 +#else +#define CONST_PC const +#define VERTEX_INDEX_PARAM_360 +#endif + + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vTint : COLOR; + float4 vPos : POSITION; + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vParms : TEXCOORD2; // frame blend, rot, radius, yaw + // FIXME: remove this vertex element for (USE_INSTANCING == 1), need to shuffle the following elements down + float2 vCornerID : TEXCOORD3; // 0,0 1,0 1,1 0,1 + float4 vTexCoord2 : TEXCOORD4; +#if DUALSEQUENCE + float4 vSeq2TexCoord0 : TEXCOORD5; + float4 vSeq2TexCoord1 : TEXCOORD6; + float4 vParms1 : TEXCOORD7; // second frame blend, ?,?,? +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; + + float2 texCoord0 : TEXCOORD0; + float2 texCoord1 : TEXCOORD1; + float4 argbcolor : COLOR; + float4 blendfactor0 : TEXCOORD2; + float2 texCoord2 : TEXCOORD3; +#if !defined( SHADER_MODEL_VS_1_1 ) + float4 blendfactor1 : TEXCOORD4; // for extracting green/alpha +#endif +#if DUALSEQUENCE + float2 vSeq2TexCoord0 : TEXCOORD5; + float2 vSeq2TexCoord1 : TEXCOORD6; +#endif + +#if defined( _X360 ) + float4 vScreenPos_ReverseZ : TEXCOORD7; +#else + float4 vScreenPos : TEXCOORD7; +#endif +}; + +#define BLENDFACTOR v.vParms.x +#define ROTATION v.vParms.y +#define RADIUS v.vParms.z +#define YAW (v.vParms.w) + +#if ( ZOOM_ANIMATE_SEQ2 ) +float getlerpscaled( float l_in, float s0, float s1, float ts ) +{ + l_in = 2.0*(l_in-.5); + l_in *= lerp(s0,s1,ts); + return 0.5+0.5*l_in; +} + +float getlerpscale_for_old_frame( float l_in, float ts ) +{ + return getlerpscaled( l_in, OLDFRM_SCALE_START, OLDFRM_SCALE_END, ts); +} + +float getlerpscale_for_new_frame( float l_in, float ts ) +{ + return getlerpscaled( l_in, 1.0, OLDFRM_SCALE_START, ts ); +} +#endif // ZOOM_ANIMATE_SEQ2 + +#ifdef DO_INSTANCING +void InstancedVertexRead( inout VS_INPUT v, int index ) +{ + // Duplicate each VB vertex 4 times (and generate vCornerID - the only thing that varies per-corner) + float4 vTint; + float4 vPos; + float4 vTexCoord0; + float4 vTexCoord1; + float4 vParms; + float4 vTexCoord2; + float4 vSeq_TexCoord0; // NOTE: April XDK compiler barfs on var names which have a number in the middle! (i.e. vSeq2TexCoord0) + float4 vSeq_TexCoord1; + float4 vParms1; + + int spriteIndex = index / 4; + int cornerIndex = index - 4*spriteIndex; + asm + { + vfetch vTint, spriteIndex, color0; + vfetch vPos, spriteIndex, position0; + vfetch vTexCoord0, spriteIndex, texcoord0; + vfetch vTexCoord1, spriteIndex, texcoord1; + vfetch vParms, spriteIndex, texcoord2; + vfetch vTexCoord2, spriteIndex, texcoord4; +#if DUALSEQUENCE + vfetch vSeq_TexCoord0, spriteIndex, texcoord5; + vfetch vSeq_TexCoord1, spriteIndex, texcoord6; + vfetch vParms1, spriteIndex, texcoord7; +#endif + }; + + v.vTint = vTint; + v.vPos = vPos; + v.vTexCoord0 = vTexCoord0; + v.vTexCoord1 = vTexCoord1; + v.vParms = vParms; + v.vTexCoord2 = vTexCoord2; +#if DUALSEQUENCE + v.vSeq2TexCoord0 = vSeq_TexCoord0; + v.vSeq2TexCoord1 = vSeq_TexCoord1; + v.vParms1 = vParms1; +#endif + + // Compute vCornerID - order is: (0,0) (1,0) (1,1) (0,1) + // float2 IDs[4] = { {0,0}, {1,0}, {1,1}, {0,1} }; + // v.vCornerID.xy = IDs[ cornerIndex ]; + // This compiles to 2 ops on 360 (MADDs with abs/sat register read/write modifiers): + v.vCornerID.xy = float2( 1.5f, 0.0f ) + cornerIndex*float2( -1.0f, 1.0f ); + v.vCornerID.xy = saturate( float2(1.5f, -3.0f) + float2( -1.0f, 2.0f )*abs( v.vCornerID.xy ) ); +} +#endif + +VS_OUTPUT main( CONST_PC VS_INPUT v + VERTEX_INDEX_PARAM_360 ) +{ + VS_OUTPUT o; + +#ifdef DO_INSTANCING + if ( USE_INSTANCING ) + { + InstancedVertexRead( v, Index ); + } +#endif + +#if SHADER_MODEL_VS_1_1 + float4 tint = v.vTint; +#else + float4 tint = GammaToLinear( v.vTint ); +#endif + + float2 sc_yaw; + sincos( YAW, sc_yaw.y, sc_yaw.x ); + + float2 sc; + sincos( ROTATION, sc.y, sc.x ); + + float2 ix=2*v.vCornerID.xy-1; + float x1=dot(ix,sc); + float y1=sc.x*ix.y-sc.y*ix.x; + + float4 projPos; + float3 worldPos; + worldPos = mul4x3( v.vPos, cModel[0] ); + + float rad = RADIUS; + float3 v2p = ( worldPos - cEyePos ); + float l = length(v2p); + rad=max(rad, MINIMUM_SIZE_FACTOR * l); + // now, perform fade out +#ifndef SHADER_MODEL_VS_1_1 + if ( rad > START_FADE_SIZE_FACTOR * l ) + { + if ( rad > END_FADE_SIZE_FACTOR *l ) + { + tint = 0; + rad = 0; // cull so we emit 0-sized sprite + } + else + { + tint *= 1-(rad-START_FADE_SIZE_FACTOR*l)/(END_FADE_SIZE_FACTOR*l-START_FADE_SIZE_FACTOR*l); + } + } +#endif + + +#ifndef SHADER_MODEL_VS_1_1 + // perform far fade + float tscale = 1-min(1, max(0, (l-START_FAR_FADE)*FAR_FADE_FACTOR) ); + tint *= tscale; + + if ( tscale <= 0) + rad = 0; // cull so we emit 0-sized sprite +#endif + + rad=min(rad, MAXIMUM_SIZE_FACTOR * l); + +#if ORIENTATION == 0 + // Screen-aligned case + float3 viewPos; + viewPos = mul4x3( v.vPos, cModelView ); + + float3 disp=float3( -x1,y1,0); + float tmpx=disp.x*sc_yaw.x+disp.z*sc_yaw.y; + disp.z = disp.z*sc_yaw.x-disp.x*sc_yaw.y; + disp.x=tmpx; + + viewPos.xyz += disp * rad; + + projPos = mul( float4(viewPos, 1.0f), cProj ); +#endif + +#if ORIENTATION == 1 + // Z-aligned case + if (l > rad/2) + { + float3 up = float3(0,0,1); + float3 right = normalize(cross(up, v2p)); + float tmpx=right.x*sc_yaw.x+right.y*sc_yaw.y; + right.y = right.y*sc_yaw.x-right.x*sc_yaw.y; + right.x=tmpx; + + worldPos += (x1*rad)*right; + worldPos.z += (y1*rad)*up.z; + +#ifndef SHADER_MODEL_VS_1_1 + if (l < rad*2 ) + { + tint *= smoothstep(rad/2,rad,l); + } +#endif + + } + projPos = mul( float4(worldPos, 1.0f), cViewProj ); +#endif + +#if ORIENTATION == 2 + // aligned with z plane case - easy + float3 wpos=v.vPos+RADIUS*float3( y1,x1,0); + projPos = mul( float4(wpos, 1.0f), cModelViewProj ); +#endif + + o.blendfactor0 = float4( v.vParms.x, 0, 0, 0 ); + o.projPos = projPos; + o.texCoord0.x = lerp( v.vTexCoord0.z, v.vTexCoord0.x, v.vCornerID.x ); + o.texCoord0.y = lerp( v.vTexCoord0.w, v.vTexCoord0.y, v.vCornerID.y ); + o.texCoord1.x = lerp( v.vTexCoord1.z, v.vTexCoord1.x, v.vCornerID.x ); + o.texCoord1.y = lerp( v.vTexCoord1.w, v.vTexCoord1.y, v.vCornerID.y ); + o.texCoord2.x = lerp( v.vTexCoord2.z, v.vTexCoord2.x, v.vCornerID.x ); + o.texCoord2.y = lerp( v.vTexCoord2.w, v.vTexCoord2.y, v.vCornerID.y ); + +#if ( DUALSEQUENCE ) + float2 lerpold = v.vCornerID.xy; + float2 lerpnew = v.vCornerID.xy; + +#if ( ZOOM_ANIMATE_SEQ2 ) + lerpold.x = getlerpscale_for_old_frame( v.vCornerID.x, v.vParms1.x ); + lerpold.y = getlerpscale_for_old_frame( v.vCornerID.y, v.vParms1.x ); + lerpnew.x = getlerpscale_for_new_frame( v.vCornerID.x, v.vParms1.x ); + lerpnew.y = getlerpscale_for_new_frame( v.vCornerID.y, v.vParms1.x ); +#endif + + o.vSeq2TexCoord0.xy = lerp( v.vSeq2TexCoord0.zw, v.vSeq2TexCoord0.xy, lerpold.xy ); + o.vSeq2TexCoord1.xy = lerp( v.vSeq2TexCoord1.zw, v.vSeq2TexCoord1.xy, lerpnew.xy ); + + o.blendfactor0.z = v.vParms1.x; +#endif + + +#if !defined( SHADER_MODEL_VS_1_1 ) + + o.blendfactor1 = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + +#if ( EXTRACTGREENALPHA ) + // Input range Output range + if ( v.vParms.x < 0.25f ) // 0.0 .. 0.25 + { + o.blendfactor0.a = v.vParms.x * 2 + 0.5f; // 0.5 .. 1.0 + o.blendfactor0.g = 1 - o.blendfactor0.a; // 0.5 .. 0.0 + } + else if ( v.vParms.x < 0.75f ) // 0.25 .. 0.75 + { + o.blendfactor1.g = v.vParms.x * 2 - 0.5f; // 0.0 .. 1.0 + o.blendfactor0.a = 1 - o.blendfactor1.g; // 1.0 .. 0.0 + } + else // 0.75 .. 1.0 + { + o.blendfactor1.a = v.vParms.x * 2 - 1.5f; // 0.0 .. 0.5 + o.blendfactor1.g = 1 - o.blendfactor1.a; // 1.0 .. 0.5 + } +#endif + +#endif + + // Map projected position to the refraction texture + float2 vScreenPos; + vScreenPos.x = projPos.x; + vScreenPos.y = -projPos.y; // invert Y + vScreenPos = (vScreenPos + projPos.w) * 0.5f; + + // Need to also account for the viewport transform, which matters when rendering with mat_viewportscale != 1.0 + vScreenPos = (vScreenPos * ViewportTransformScaled.xy) + (projPos.w * ViewportTransformScaled.zw); + +#if defined( _X360 ) + o.vScreenPos_ReverseZ = float4(vScreenPos.x, vScreenPos.y, projPos.w - projPos.z, projPos.w ); +#else + o.vScreenPos = float4(vScreenPos.x, vScreenPos.y, projPos.z, projPos.w ); +#endif + + o.argbcolor = tint; + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/teeth.cpp b/sp/src/materialsystem/stdshaders/teeth.cpp new file mode 100644 index 00000000..a3168822 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth.cpp @@ -0,0 +1,578 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +#include "teeth_vs20.inc" +#include "teeth_flashlight_vs20.inc" +#include "teeth_bump_vs20.inc" +#include "teeth_ps20.inc" +#include "teeth_ps20b.inc" +#include "teeth_flashlight_ps20.inc" +#include "teeth_flashlight_ps20b.inc" +#include "teeth_bump_ps20.inc" +#include "teeth_bump_ps20b.inc" + +#ifndef _X360 +#include "teeth_vs30.inc" +#include "teeth_ps30.inc" +#include "teeth_bump_vs30.inc" +#include "teeth_bump_ps30.inc" +#include "teeth_flashlight_vs30.inc" +#include "teeth_flashlight_ps30.inc" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX9 ) + +extern ConVar r_flashlight_version2; +BEGIN_VS_SHADER( Teeth_DX9, "Help for Teeth_DX9" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "100", "phong exponent" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is teeth in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[INTRO]->IsDefined() ) + { + params[INTRO]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 || g_pConfig->bSoftwareLighting ) + { + return "Teeth_dx8"; + } + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + + if( params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + } + + void DrawUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression ) + { + bool hasBump = params[BUMPMAP]->IsTexture(); + + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base map + + int flags = VERTEX_POSITION | VERTEX_NORMAL; + int nTexCoordCount = 1; + int userDataSize = 0; + + if ( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Bump map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // Normalization sampler for per-pixel lighting + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false ); + userDataSize = 4; // tangent S + } + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + if ( hasBump ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( teeth_bump_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( teeth_bump_vs20 ); + + // ps_2_b version which does phong + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps20b ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_bump_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_bump_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_bump_ps30 ); + SET_STATIC_PIXEL_SHADER( teeth_bump_ps30 ); + } +#endif + } + else + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( teeth_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( teeth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_ps20b ); + SET_STATIC_PIXEL_SHADER( teeth_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_ps30 ); + SET_STATIC_PIXEL_SHADER( teeth_ps30 ); + } +#endif + } + + // On DX9, do sRGB + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + if ( hasBump ) + { + BindTexture( SHADER_SAMPLER1, BUMPMAP ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE ); + pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY ); + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + + LightState_t lightState; + pShaderAPI->GetDX9LightState( &lightState ); + + pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); + vEyePos_SpecExponent[3] = 0.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); + + if ( hasBump ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_bump_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( teeth_bump_vs20 ); + + // ps_2_b version which does Phong + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + Vector4D vSpecExponent; + vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue(); + + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_bump_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_bump_vs30 ); + + Vector4D vSpecExponent; + vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_bump_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_bump_ps30 ); + } +#endif + } + else + { + // For non-bumped case, ambient cube is computed in the vertex shader + SetAmbientCubeDynamicStateVertexShader(); + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER( teeth_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_ps30 ); + } +#endif + } + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, timeVec, 1 ); + } + } + Draw(); + } + + void DrawFlashlight( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression ) + { + SHADOW_STATE + { + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base map + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); // Flashlight spot + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + + // Additive blend the teeth, lit by the flashlight + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + s_pShaderShadow->EnableBlending( true ); + + // Set stream format (note that this shader supports compression) + int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + int nShadowFilterMode = 0; + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); // shadow depth map + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER2 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // shadow noise + + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_STATIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 ); + SET_STATIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + } +#endif + // On DX9, do sRGB + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBWrite( true ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + + // State for spotlight projection, attenuation etc + SetFlashlightVertexShaderConstants( false, -1, false, -1, true ); + + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + bool bFlashlightShadows = g_pHardwareConfig->SupportsPixelShaders_2_b() ? state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ) : false; + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + BindTexture( SHADER_SAMPLER2, pFlashlightDepthTexture, 0 ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_SHADOW_NOISE_2D ); + } + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, lighting.Base() ); + + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR ); + + BindTexture( SHADER_SAMPLER1, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 ); + + pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 ); // steps on rim boost + + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 ); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState( flashlightState ); + tweaks[1] = ShadowAttenFromState( flashlightState ); + HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 ); + + float vFlashlightPos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( vFlashlightPos ); + pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vFlashlightPos, 1 ); + + if ( IsX360() ) + { + pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps20 ); + } + } +#ifndef _X360 + else + { + SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( teeth_flashlight_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( teeth_flashlight_ps30 ); + } +#endif + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, timeVec, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + if ( !hasFlashlight || ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawUsingVertexShader( params, pShaderAPI, pShaderShadow, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState(); + } + } + if( hasFlashlight ) + { + DrawFlashlight( params, pShaderAPI, pShaderShadow, vertexCompression ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/teeth_bump_ps2x.fxc b/sp/src/materialsystem/stdshaders/teeth_bump_ps2x.fxc new file mode 100644 index 00000000..72e43a10 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_bump_ps2x.fxc @@ -0,0 +1,101 @@ +//====== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "shader_constant_register_map.h" + +const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE ); +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); +PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total + +sampler BaseTextureSampler : register( s0 ); +sampler BumpTextureSampler : register( s1 ); +sampler NormalizeSampler : register( s2 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 worldVertToEyeVector_Darkening : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + + + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + +#define worldVertToEyeVector i.worldVertToEyeVector_Darkening.xyz +#define fDarkening i.worldVertToEyeVector_Darkening.w + +#endif + + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vLightAtten = float4( i.lightAtten01, i.lightAtten23 ); + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float3 worldSpaceNormal, tangentSpaceNormal = float3(0, 0, 1); + float fSpecExp = g_EyePos_SpecExponent.w; + + float4 normalTexel = tex2D( BumpTextureSampler, i.baseTexCoord ); + tangentSpaceNormal = 2.0f * normalTexel.xyz - 1.0f; + worldSpaceNormal = normalize( mul( i.tangentSpaceTranspose, tangentSpaceNormal ) ); + + // If the exponent passed in as a constant is zero, use the value from the map as the exponent + if ( fSpecExp == 0 ) + fSpecExp = 1.0f * ( 1.0f - normalTexel.w ) + 150.0f * normalTexel.w; + + // Summation of diffuse illumination from all local lights + float3 diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, + bAmbientLight, vLightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, true, + false, 0, false, NormalizeSampler ); + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + + float3 vDummy, specularLighting; + + // Summation of specular from all local lights + PixelShaderDoSpecularLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, fSpecExp, normalize(worldVertToEyeVector), + vLightAtten, nNumLights, cLightInfo, + false, 1.0f, false, NormalizeSampler, 1.0f, false, 1.0f, + + // Outputs + specularLighting, vDummy ); + + // Specular plus diffuse, all darkened as a function of mouth openness + float3 result = (specularLighting * baseSample.a + baseSample.rgb * diffuseLighting) * fDarkening; + +#else + float3 result = baseSample.rgb * diffuseLighting * i.worldVertToEyeVector_Darkening.w; +#endif + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( float4(result, 1.0f), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/sp/src/materialsystem/stdshaders/teeth_bump_vs20.fxc b/sp/src/materialsystem/stdshaders/teeth_bump_vs20.fxc new file mode 100644 index 00000000..1dd834b5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_bump_vs20.fxc @@ -0,0 +1,152 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== + +// STATIC: "INTRO" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_0 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_1 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + float4 vUserData : TANGENT; // Sign for cross product in w + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float4 worldVertToEyeVector_Darkening : TEXCOORD1; + float3x3 tangentSpaceTranspose : TEXCOORD2; + // second row : TEXCOORD3; + // third row : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), + vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + +#if INTRO + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, worldTangentS, worldTangentT ); +#endif + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos, vProjPos.z ); +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, vProjPos, g_FogType ); +#endif + // Needed for specular + o.worldVertToEyeVector_Darkening.xyz = cEyePos - worldPos; + + // Special darkening of lights for mouth open/close + o.worldVertToEyeVector_Darkening.w = cTeethLighting.w * saturate( dot( worldNormal, cTeethLighting.xyz ) );; + + // Scalar light attenuation (mouth darkening applied in pixel shader) +#if defined( SHADER_MODEL_VS_2_0 ) && ( !USE_STATIC_CONTROL_FLOW ) + o.lightAtten01.xy = float2(0,0); + o.lightAtten23.xy = float2(0,0); + #if ( NUM_LIGHTS > 0 ) + o.lightAtten01.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten01.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten23.x = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.lightAtten23.y = GetVertexAttenForLight( worldPos, 3, false ); + #endif +#else + o.lightAtten01.x = GetVertexAttenForLight( worldPos, 0, true ); + o.lightAtten01.y = GetVertexAttenForLight( worldPos, 1, true ); + o.lightAtten23.x = GetVertexAttenForLight( worldPos, 2, true ); + o.lightAtten23.y = GetVertexAttenForLight( worldPos, 3, true ); +#endif + + o.baseTexCoord = v.vTexCoord0; + + // Tangent space transform + o.tangentSpaceTranspose[0] = float3( worldTangentS.x, worldTangentT.x, worldNormal.x ); + o.tangentSpaceTranspose[1] = float3( worldTangentS.y, worldTangentT.y, worldNormal.y ); + o.tangentSpaceTranspose[2] = float3( worldTangentS.z, worldTangentT.z, worldNormal.z ); + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/teeth_dx6.cpp b/sp/src/materialsystem/stdshaders/teeth_dx6.cpp new file mode 100644 index 00000000..8c097f6a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_dx6.cpp @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX6 ) + +BEGIN_VS_SHADER( Teeth_DX6, + "Help for Teeth_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + } + + void DrawUsingSoftwareLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + } + else + { + DrawUsingSoftwareLighting( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/teeth_dx8.cpp b/sp/src/materialsystem/stdshaders/teeth_dx8.cpp new file mode 100644 index 00000000..d91626d8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_dx8.cpp @@ -0,0 +1,116 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "BaseVSShader.h" + +#include "teeth.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Teeth, Teeth_DX8 ) + +BEGIN_VS_SHADER( Teeth_DX8, "Help for Teeth_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ILLUMFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "Amount to darken or brighten the teeth" ) + SHADER_PARAM( FORWARD, SHADER_PARAM_TYPE_VEC3, "[1 0 0]", "Forward direction vector for teeth lighting" ) + SHADER_PARAM( INTRO, SHADER_PARAM_TYPE_BOOL, "0", "is teeth in the ep1 intro" ) + SHADER_PARAM( ENTITYORIGIN, SHADER_PARAM_TYPE_VEC3,"0.0","center if the model in world space" ) + SHADER_PARAM( WARPPARAM, SHADER_PARAM_TYPE_FLOAT,"0.0","animation param between 0 and 1" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[INTRO]->IsDefined() ) + { + params[INTRO]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + if ( IsPC() && ( g_pHardwareConfig->GetDXSupportLevel() < 80 || g_pConfig->bSoftwareLighting ) ) + { + return "Teeth_dx6"; + } + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + } + + void DrawUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL, 1, 0, 0 ); + teeth_Static_Index vshIndex; + vshIndex.SetHALF_LAMBERT( IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + vshIndex.SetINTRO( params[INTRO]->GetIntValue() != 0 ); + pShaderShadow->SetVertexShader( "Teeth", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "VertexLitTexture_Overbright2" ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetAmbientCubeDynamicStateVertexShader(); + + Vector4D lighting; + params[FORWARD]->GetVecValue( lighting.Base(), 3 ); + lighting[3] = params[ILLUMFACTOR]->GetFloatValue(); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() ); + + teeth_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetLIGHT_COMBO( pShaderAPI->GetCurrentLightCombo() ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( params[INTRO]->GetIntValue() ) + { + float curTime = params[WARPPARAM]->GetFloatValue(); + float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime }; + Assert( params[ENTITYORIGIN]->IsDefined() ); + params[ENTITYORIGIN]->GetVecValue( timeVec, 3 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, timeVec, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + bool hasFlashlight = UsingFlashlight( params ); + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, false, false, 0, -1, -1, + // Optional parameters, specific to teeth: + true, FORWARD, ILLUMFACTOR ); + } + else + { + DrawUsingVertexShader( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc b/sp/src/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc new file mode 100644 index 00000000..7ef61872 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_flashlight_ps2x.fxc @@ -0,0 +1,66 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +#include "common_flashlight_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); +sampler SpotSampler : register( s1 ); +sampler FlashlightDepthSampler : register( s2 ); +sampler RandomRotationSampler : register( s3 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float3 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); +const float3 g_FlashlightPos : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); +const float4 g_FlashlightAtten : register( PSREG_FLASHLIGHT_ATTENUATION ); +const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +const float4 g_ShadowTweaks : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; // Base texture coordinates + float4 spotTexCoord : TEXCOORD1; // Spotlight texture coordinates + float3 vertAtten : TEXCOORD2; // Distance/spot attenuation + float4 projPos : TEXCOORD3; // Projective space position + float3 worldPos : TEXCOORD4; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ +#if defined( SHADER_MODEL_PS_2_0 ) + float3 result = tex2Dproj( SpotSampler, i.spotTexCoord.xyzw ); +#else + float3 vProjCoords = i.spotTexCoord.xyz / i.spotTexCoord.w; + float3 result = tex2D( SpotSampler, vProjCoords ); +#endif + + result *= cFlashlightColor.rgb; + +#if FLASHLIGHTSHADOWS && ( defined( SHADER_MODEL_PS_2_B ) || defined( SHADER_MODEL_PS_3_0 ) ) + result *= DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, i.projPos.xy / i.projPos.z, FLASHLIGHTDEPTHFILTERMODE, g_ShadowTweaks, true ); +#endif + result *= 0.35f; // Without this, unshadowed teeth always seem to glow + + result *= i.vertAtten; // Distance atten, NdotL and forward vector + + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + result *= baseSample.rgb; // Multiply by base map and diffuse + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z ); + return FinalOutput( float4( result, baseSample.a ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR ); +} + diff --git a/sp/src/materialsystem/stdshaders/teeth_flashlight_vs20.fxc b/sp/src/materialsystem/stdshaders/teeth_flashlight_vs20.fxc new file mode 100644 index 00000000..8c5ce4c5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_flashlight_vs20.fxc @@ -0,0 +1,149 @@ +//======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== + +// STATIC: "INTRO" "0..1" + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cFlashlightPosition : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cSpotlightProj1 : register( SHADER_SPECIFIC_CONST_1 ); +const float4 cSpotlightProj2 : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cSpotlightProj3 : register( SHADER_SPECIFIC_CONST_3 ); +const float4 cSpotlightProj4 : register( SHADER_SPECIFIC_CONST_4 ); +const float4 cFlashlighAtten : register( SHADER_SPECIFIC_CONST_5 ); // const, linear, quadratic & farZ + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_8 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_9 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; // Base texture coordinates + float4 spotTexCoord : TEXCOORD1; // Spotlight texture coordinates + float3 vertAtten : TEXCOORD2; // Distance/spot attenuation + float4 vProjPos : TEXCOORD3; // Projective space position + float3 worldPos : TEXCOORD4; // Necessary for pixel fog +}; + + +float RemapValClamped_01( float val, float A, float B ) +{ + float cVal = (val - A) / (B - A); + cVal = saturate( cVal ); + return cVal; +} + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Normalize the flexed normal + vNormal.xyz = normalize( vNormal.xyz ); + + // Transform the position + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, dummy, dummy ); +#endif + + // Transform into projection space + o.projPos = mul( float4( worldPos, 1 ), cViewProj ); + o.worldPos = worldPos.xyz; + o.vProjPos = o.projPos; +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, o.projPos, g_FogType ); +#endif + // Spotlight texture coordinates + o.spotTexCoord.x = dot( cSpotlightProj1, float4(worldPos, 1) ); + o.spotTexCoord.y = dot( cSpotlightProj2, float4(worldPos, 1) ); + o.spotTexCoord.z = dot( cSpotlightProj3, float4(worldPos, 1) ); + o.spotTexCoord.w = dot( cSpotlightProj4, float4(worldPos, 1) ); + + // Compute vector to light + float3 vWorldPosToLightVector = cFlashlightPosition.xyz - worldPos; + + float3 vDistAtten = float3(1, 1, 1); + vDistAtten.z = dot( vWorldPosToLightVector, vWorldPosToLightVector ); + vDistAtten.y = rsqrt( vDistAtten.z ); + + float flDist = vDistAtten.z * vDistAtten.y; // Distance to light + vDistAtten.z = 1.0f / vDistAtten.z; // 1 / distsquared + + float fFarZ = cFlashlighAtten.w; + + float NdotL = saturate( dot( worldNormal, normalize( vWorldPosToLightVector ) ) ); + + float endFalloffFactor = RemapValClamped_01( flDist, fFarZ, 0.6 * fFarZ ); + o.vertAtten.xyz = endFalloffFactor * dot( vDistAtten, cFlashlighAtten.xyz ); + + // Final attenuation from flashlight only... + float linearAtten = NdotL * dot( vDistAtten, cFlashlighAtten.xyz ) * endFalloffFactor; + + // Forward vector + float3 vForward = cTeethLighting.xyz; + float fIllumFactor = cTeethLighting.w; + + // Modulate flashlight by mouth darkening + o.vertAtten = linearAtten * fIllumFactor * saturate( dot( worldNormal, vForward ) ); + + o.baseTexCoord = v.vTexCoord0; + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/teeth_ps2x.fxc b/sp/src/materialsystem/stdshaders/teeth_ps2x.fxc new file mode 100644 index 00000000..4893f9aa --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_ps2x.fxc @@ -0,0 +1,48 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps30][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] + + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "common_ps_fxc.h" +#include "shader_constant_register_map.h" + +sampler BaseTextureSampler : register( s0 ); + +const float4 g_FogParams : register( PSREG_FOG_PARAMS ); +const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float3 vertAtten : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 baseSample = tex2D( BaseTextureSampler, i.baseTexCoord ); + + float4 result; + result.xyz = baseSample.xyz * i.vertAtten; + result.a = baseSample.a; + + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + return FinalOutput( result, fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} diff --git a/sp/src/materialsystem/stdshaders/teeth_vs20.fxc b/sp/src/materialsystem/stdshaders/teeth_vs20.fxc new file mode 100644 index 00000000..9a9ab045 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/teeth_vs20.fxc @@ -0,0 +1,127 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== + +// STATIC: "INTRO" "0..1" +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "vortwarp_vs20_helper.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cTeethLighting : register( SHADER_SPECIFIC_CONST_0 ); +#if INTRO +const float4 const4 : register( SHADER_SPECIFIC_CONST_1 ); +#define g_Time const4.w +#define modelOrigin const4.xyz +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_6 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_7 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + +struct VS_OUTPUT +{ + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + float2 baseTexCoord : TEXCOORD0; + float3 vertAtten : TEXCOORD1; + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + + float4 vPosition = v.vPos; + float3 vNormal; + DecompressVertex_Normal( v.vNormal, vNormal ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz, vNormal ); +#endif + + // Normalize the flexed normal + vNormal.xyz = normalize( vNormal.xyz ); + + // Transform the position + float3 worldPos, worldNormal; + SkinPositionAndNormal( g_bSkinning, vPosition, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal ); + +#if INTRO + float3 dummy = float3( 0.0f, 0.0f, 0.0f ); + WorldSpaceVertexProcess( g_Time, modelOrigin, worldPos, worldNormal, dummy, dummy ); +#endif + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); +#if !defined( _X360 ) + // Set fixed-function fog factor + o.fog = CalcFog( worldPos, vProjPos, g_FogType ); +#endif + + // Compute lighting +#if ( USE_STATIC_CONTROL_FLOW ) || defined ( SHADER_MODEL_VS_3_0 ) + float3 linearColor = DoLighting( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, false ); +#else + float3 linearColor = DoLightingUnrolled( worldPos, worldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, false, NUM_LIGHTS ); +#endif + + // Forward vector + float3 vForward = cTeethLighting.xyz; + float fIllumFactor = cTeethLighting.w; + + // Darken by forward dot normal and illumination factor + linearColor *= fIllumFactor * saturate( dot( worldNormal, vForward ) ); + + o.vertAtten = linearColor; + o.baseTexCoord = v.vTexCoord0; + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_basetimesdetail.psh b/sp/src/materialsystem/stdshaders/unlitgeneric_basetimesdetail.psh new file mode 100644 index 00000000..8f9139df --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_basetimesdetail.psh @@ -0,0 +1,24 @@ +ps.1.1 +def c0,0,0,0,.1 +def c1,0,0,0,.1 +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +; tc3 - detail texcoords +; +; c3 = outline color +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t3 ; detail mask + +mul r1,t0,t3 ; multiply + +mov r0.rgb, c3 ; color = outline color +;add r0.a, r1.a, c0.a +;cnd r0.rgb, r0.a, r0, r1 ; if ( alpha+c0 > 0.5 ) color = outline, else color = base +sub r0.a, r1.a, c1.a +cnd r0.rgb, r0.a, r1, r0 ; if ( alpha -c1 > 0.5) color=base diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_dx6.cpp b/sp/src/materialsystem/stdshaders/unlitgeneric_dx6.cpp new file mode 100644 index 00000000..fc8bdf47 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_dx6.cpp @@ -0,0 +1,310 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( UnlitGeneric, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( MonitorScreen, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( ParticleSphere, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( Predator, Predator_DX60 ) +DEFINE_FALLBACK_SHADER( Predator_DX60, UnlitGeneric_DX6 ) +DEFINE_FALLBACK_SHADER( WindowImposter, WindowImposter_DX60 ) +DEFINE_FALLBACK_SHADER( WindowImposter_DX60, UnlitGeneric_DX6 ) + +BEGIN_SHADER( UnlitGeneric_DX6, + "Help for UnlitGeneric_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No texture means no env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + // the second texture (if there is one) + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + SET_FLAGS(MATERIAL_VAR_ENVMAPSPHERE); + + if (params[ENVMAPMASK]->IsDefined()) + { + LoadTexture( ENVMAPMASK ); + } + } + } + + int GetDrawFlagsPass1(IMaterialVar** params, bool doDetail) + { + int flags = SHADER_DRAW_POSITION; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + if (params[BASETEXTURE]->IsTexture()) + flags |= SHADER_DRAW_TEXCOORD0; + if (doDetail) + flags |= SHADER_DRAW_TEXCOORD1; + return flags; + } + + void SetDetailShadowState(IShaderShadow* pShaderShadow) + { + // Specifically choose overbright2, will cause mod2x here + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 2.0f ); + } + + void SetDetailDymamicState(IShaderShadow* pShaderShadow) + { + BindTexture( SHADER_SAMPLER1, DETAIL, FRAME ); + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE1, BASETEXTURETRANSFORM, DETAILSCALE ); + } + + void DrawAdditiveNonTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + SetModulationShadowState(); + SetAdditiveBlendingShadowState( ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToBlack(); + } + DYNAMIC_STATE + { + SetModulationDynamicState(); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + } + Draw( ); + } + + void DrawAdditiveTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + SetModulationShadowState(); + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + SetModulationDynamicState(); + } + Draw( ); + } + + void DrawNonTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + SetModulationShadowState(); + SetNormalBlendingShadowState( ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToFogColor(); + } + DYNAMIC_STATE + { + SetModulationDynamicState(); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + } + Draw( ); + } + + void DrawTextured( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doDetail ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + SetModulationShadowState(); + SetNormalBlendingShadowState( BASETEXTURE, true ); + if (doDetail) + SetDetailShadowState(pShaderShadow); + pShaderShadow->DrawFlags( GetDrawFlagsPass1(params, doDetail) ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + if (doDetail) + SetDetailDymamicState(pShaderShadow); + SetModulationDynamicState(); + } + Draw( ); + } + + SHADER_DRAW + { + bool isTextureDefined = params[BASETEXTURE]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR); + bool doFirstPass = isTextureDefined || hasVertexColor || (!params[ENVMAP]->IsTexture()); + + if (doFirstPass) + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + if( params[ALPHATESTREFERENCE]->IsDefined() && params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + } + + if (IS_FLAG_SET(MATERIAL_VAR_ADDITIVE)) + { + if (!isTextureDefined) + { + bool hasDetailTexture = params[DETAIL]->IsTexture(); + DrawAdditiveNonTextured( params, pShaderAPI, pShaderShadow, hasDetailTexture ); + } + else + { + // We can't do detail in a single pass if we're also + // colormodulating and have vertex color + bool hasDetailTexture = params[DETAIL]->IsTexture(); + bool isModulating = IsColorModulating() || IsAlphaModulating(); + bool onePassDetail = hasDetailTexture && (!hasVertexColor || !isModulating); + DrawAdditiveTextured( params, pShaderAPI, pShaderShadow, onePassDetail ); + if (hasDetailTexture && !onePassDetail) + { + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + } + } + else + { + if (!isTextureDefined) + { + bool hasDetailTexture = params[DETAIL]->IsTexture(); + DrawNonTextured( params, pShaderAPI, pShaderShadow, hasDetailTexture ); + } + else + { + // We can't do detail in a single pass if we're also + // colormodulating and have vertex color + bool hasDetailTexture = params[DETAIL]->IsTexture(); + bool isModulating = IsColorModulating() || IsAlphaModulating(); + bool onePassDetail = hasDetailTexture && (!hasVertexColor || !isModulating); + DrawTextured( params, pShaderAPI, pShaderShadow, onePassDetail ); + if (hasDetailTexture && !onePassDetail) + { + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + } + } + } + + SHADOW_STATE + { + // Disable mod2x used by detail + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + } + + // Second pass... + if (params[ENVMAP]->IsTexture() && + (!doFirstPass || IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) ) + { + if (doFirstPass || IS_FLAG_SET(MATERIAL_VAR_ADDITIVE)) + { + FixedFunctionAdditiveMaskedEnvmapPass( ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + else + { + FixedFunctionMaskedEnvmapPass( ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_dx8.cpp b/sp/src/materialsystem/stdshaders/unlitgeneric_dx8.cpp new file mode 100644 index 00000000..19d0e169 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_dx8.cpp @@ -0,0 +1,72 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( UnlitGeneric, UnlitGeneric_DX8 ) + +BEGIN_VS_SHADER( UnlitGeneric_DX8, + "Help for UnlitGeneric_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && !g_pHardwareConfig->SupportsVertexAndPixelShaders()) + { + return "UnlitGeneric_DX6"; + } + return 0; + } + + SHADER_INIT_PARAMS() + { + InitParamsUnlitGeneric_DX8( + BASETEXTURE, DETAILSCALE, ENVMAPOPTIONAL, + ENVMAP, ENVMAPTINT, ENVMAPMASKSCALE, + DETAILBLENDMODE ); + } + + SHADER_INIT + { + InitUnlitGeneric_DX8( BASETEXTURE, DETAIL, ENVMAP, ENVMAPMASK ); + } + + SHADER_DRAW + { + VertexShaderUnlitGenericPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, + DETAIL, DETAILSCALE, true, ENVMAP, ENVMAPFRAME, ENVMAPMASK, + ENVMAPMASKFRAME, ENVMAPMASKSCALE, ENVMAPTINT, ALPHATESTREFERENCE, + DETAILBLENDMODE, + OUTLINE, OUTLINECOLOR, OUTLINESTART0, OUTLINEEND1, SEPARATEDETAILUVS ); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_dx9.cpp b/sp/src/materialsystem/stdshaders/unlitgeneric_dx9.cpp new file mode 100644 index 00000000..b57474a8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_dx9.cpp @@ -0,0 +1,200 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" + +extern ConVar r_flashlight_version2; + +BEGIN_VS_SHADER( UnlitGeneric, "Help for UnlitGeneric" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.7", "" ) + SHADER_PARAM( VERTEXALPHATEST, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( HDRCOLORSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "hdr color scale" ) + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "2D map for warping specular" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + + SHADER_PARAM( SELFILLUMMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "If we bind a texture here, it overrides base alpha (if any) for self illum" ) + + SHADER_PARAM( DISTANCEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use distance-coded alpha generated from hi-res texture by vtex.") + SHADER_PARAM( DISTANCEALPHAFROMDETAIL, SHADER_PARAM_TYPE_BOOL, "0", "Take the distance-coded alpha mask from the detail texture.") + + SHADER_PARAM( SOFTEDGES, SHADER_PARAM_TYPE_BOOL, "0", "Enable soft edges to distance coded textures.") + SHADER_PARAM( SCALEEDGESOFTNESSBASEDONSCREENRES, SHADER_PARAM_TYPE_BOOL, "0", "Scale the size of the soft edges based upon resolution. 1024x768 = nominal.") + SHADER_PARAM( EDGESOFTNESSSTART, SHADER_PARAM_TYPE_FLOAT, "0.6", "Start value for soft edges for distancealpha."); + SHADER_PARAM( EDGESOFTNESSEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "End value for soft edges for distancealpha."); + + SHADER_PARAM( GLOW, SHADER_PARAM_TYPE_BOOL, "0", "Enable glow/shadow for distance coded textures.") + SHADER_PARAM( GLOWCOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outter glow for distance coded line art." ) + SHADER_PARAM( GLOWALPHA, SHADER_PARAM_TYPE_FLOAT, "1", "Base glow alpha amount for glows/shadows with distance alpha." ) + SHADER_PARAM( GLOWSTART, SHADER_PARAM_TYPE_FLOAT, "0.7", "start value for glow/shadow") + SHADER_PARAM( GLOWEND, SHADER_PARAM_TYPE_FLOAT, "0.5", "end value for glow/shadow") + SHADER_PARAM( GLOWX, SHADER_PARAM_TYPE_FLOAT, "0", "texture offset x for glow mask.") + SHADER_PARAM( GLOWY, SHADER_PARAM_TYPE_FLOAT, "0", "texture offset y for glow mask.") + + SHADER_PARAM( OUTLINE, SHADER_PARAM_TYPE_BOOL, "0", "Enable outline for distance coded textures.") + SHADER_PARAM( OUTLINECOLOR, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "color of outline for distance coded images." ) + SHADER_PARAM( OUTLINEALPHA, SHADER_PARAM_TYPE_FLOAT, "0.0", "alpha value for outline") + SHADER_PARAM( OUTLINESTART0, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer start value for outline") + SHADER_PARAM( OUTLINESTART1, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner start value for outline") + SHADER_PARAM( OUTLINEEND0, SHADER_PARAM_TYPE_FLOAT, "0.0", "inner end value for outline") + SHADER_PARAM( OUTLINEEND1, SHADER_PARAM_TYPE_FLOAT, "0.0", "outer end value for outline") + SHADER_PARAM( SCALEOUTLINESOFTNESSBASEDONSCREENRES, SHADER_PARAM_TYPE_BOOL, "0", "Scale the size of the soft part of the outline based upon resolution. 1024x768 = nominal.") + + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_BOOL, "0", "Use texcoord1 for detail texture" ) + + SHADER_PARAM( GAMMACOLORREAD, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of color texture read." ) + SHADER_PARAM( LINEARWRITE, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of shader results." ) + + SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries" ) + SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) + SHADER_PARAM( RECEIVEFLASHLIGHT, SHADER_PARAM_TYPE_INTEGER, "0", "Forces this material to receive flashlights." ) + + END_SHADER_PARAMS + + void SetupVars( VertexLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = -1; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = -1; + info.m_nBumpFrame = -1; + info.m_nBumpTransform = -1; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nVertexAlphaTest = VERTEXALPHATEST; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nHDRColorScale = HDRCOLORSCALE; + info.m_nPhongExponent = -1; + info.m_nPhongExponentTexture = -1; + info.m_nDiffuseWarpTexture = -1; + info.m_nPhongWarpTexture = -1; + info.m_nPhongBoost = -1; + info.m_nPhongFresnelRanges = -1; + info.m_nPhong = -1; + info.m_nPhongTint = -1; + info.m_nPhongAlbedoTint = -1; + info.m_nSelfIllumEnvMapMask_Alpha = -1; + info.m_nAmbientOnly = -1; + info.m_nBaseMapAlphaPhongMask = -1; + info.m_nEnvmapFresnel = -1; + info.m_nSelfIllumMask = -1; + + info.m_nDistanceAlpha = DISTANCEALPHA; + info.m_nDistanceAlphaFromDetail = DISTANCEALPHAFROMDETAIL; + info.m_nSoftEdges = SOFTEDGES; + info.m_nEdgeSoftnessStart = EDGESOFTNESSSTART; + info.m_nEdgeSoftnessEnd = EDGESOFTNESSEND; + info.m_nScaleEdgeSoftnessBasedOnScreenRes = SCALEEDGESOFTNESSBASEDONSCREENRES; + + info.m_nGlow = GLOW; + info.m_nGlowColor = GLOWCOLOR; + info.m_nGlowAlpha = GLOWALPHA; + info.m_nGlowStart = GLOWSTART; + info.m_nGlowEnd = GLOWEND; + info.m_nGlowX = GLOWX; + info.m_nGlowY = GLOWY; + + info.m_nOutline = OUTLINE; + info.m_nOutlineColor = OUTLINECOLOR; + info.m_nOutlineAlpha = OUTLINEALPHA; + info.m_nOutlineStart0 = OUTLINESTART0; + info.m_nOutlineStart1 = OUTLINESTART1; + info.m_nOutlineEnd0 = OUTLINEEND0; + info.m_nOutlineEnd1 = OUTLINEEND1; + info.m_nScaleOutlineSoftnessBasedOnScreenRes = SCALEOUTLINESOFTNESSBASEDONSCREENRES; + + info.m_nSeparateDetailUVs = SEPARATEDETAILUVS; + + info.m_nLinearWrite = LINEARWRITE; + info.m_nGammaColorRead = GAMMACOLORREAD; + + info.m_nDepthBlend = DEPTHBLEND; + info.m_nDepthBlendScale = DEPTHBLENDSCALE; + info.m_nReceiveFlashlight = RECEIVEFLASHLIGHT; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, false, vars ); + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "UnlitGeneric_DX8"; + } + return 0; + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, false, vars ); + } + + SHADER_DRAW + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + + bool bNewFlashlightPath = IsX360() || ( r_flashlight_version2.GetInt() != 0 ); + if ( ( pShaderShadow == NULL ) && ( pShaderAPI != NULL ) && !bNewFlashlightPath && pShaderAPI->InFlashlightMode() ) // Not snapshotting && flashlight pass + { + Draw( false ); + } + else + { + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, false, vars, vertexCompression, pContextDataPtr ); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_inc.vsh b/sp/src/materialsystem/stdshaders/unlitgeneric_inc.vsh new file mode 100644 index 00000000..ac2abb7e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_inc.vsh @@ -0,0 +1,142 @@ +#include "macros.vsh" + +;------------------------------------------------------------------------------ +; $SHADER_SPECIFIC_CONST_0-$SHADER_SPECIFIC_CONST_1 = Base texture transform +; $SHADER_SPECIFIC_CONST_2-$SHADER_SPECIFIC_CONST_3 = Mask texture transform +; $SHADER_SPECIFIC_CONST_4-$SHADER_SPECIFIC_CONST_5 = Detail texture transform +;------------------------------------------------------------------------------ + +sub UnlitGeneric +{ + local( $detail ) = shift; + local( $envmap ) = shift; + local( $envmapcameraspace ) = shift; + local( $envmapsphere ) = shift; + local( $vertexcolor ) = shift; + local( $separatedetailuvs ) = shift; + + local( $worldPos, $worldNormal, $projPos, $reflectionVector ); + + ;------------------------------------------------------------------------------ + ; Vertex blending + ;------------------------------------------------------------------------------ + &AllocateRegister( \$worldPos ); + if( $envmap ) + { + &AllocateRegister( \$worldNormal ); + &SkinPositionAndNormal( $worldPos, $worldNormal ); + } + else + { + &SkinPosition( $worldPos ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to proj space + ;------------------------------------------------------------------------------ + + &AllocateRegister( \$projPos ); + + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + mov oPos, $projPos + + ;------------------------------------------------------------------------------ + ; Fog + ;------------------------------------------------------------------------------ + &CalcFog( $worldPos, $projPos ); + &FreeRegister( \$projPos ); + + if( !$envmap ) + { + &FreeRegister( \$worldPos ); + } + + ;------------------------------------------------------------------------------ + ; Texture coordinates (use world-space normal for envmap, tex transform for mask) + ;------------------------------------------------------------------------------ + dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 + dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT0.zw, $cZero + } + + if( $envmap ) + { + if( $envmapcameraspace ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + + ; transform reflection vector into view space + dp3 oT1.x, $reflectionVector, $cViewModel0 + dp3 oT1.y, $reflectionVector, $cViewModel1 + dp3 oT1.z, $reflectionVector, $cViewModel2 + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT1.w, $cZero + } + + &FreeRegister( \$reflectionVector ); + } + elsif( $envmapsphere ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + &ComputeSphereMapTexCoords( $reflectionVector, "oT1" ); + + &FreeRegister( \$reflectionVector ); + } + else + { + &ComputeReflectionVector( $worldPos, $worldNormal, "oT1" ); + } + + ; envmap mask + dp4 oT2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + dp4 oT2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT2.zw, $cZero + } + + &FreeRegister( \$worldPos ); + &FreeRegister( \$worldNormal ); + } + + if( $detail ) + { + if ( $separatedetailuvs ) + { + mov oT3, $vTexCoord1 + } + else + { + dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 + dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + } + + if ( $g_x360 ) + { + ; must write xyzw to match read in pixelshader + mov oT3.zw, $cZero + } + } + + if( $vertexcolor ) + { + ; Modulation color + mul oD0, $vColor, $cModulationColor + } + else + { + ; Modulation color + mov oD0, $cModulationColor + } +} diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_lightingonly_vs11.fxc b/sp/src/materialsystem/stdshaders/unlitgeneric_lightingonly_vs11.fxc new file mode 100644 index 00000000..dcbd43a2 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_lightingonly_vs11.fxc @@ -0,0 +1,47 @@ +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + + float4 vDiffuse : COLOR0; + + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + + o.vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + + o.fogFactorW = CalcFog( worldPos, o.vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + o.vDiffuse = 1.0f; + + return o; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps11.fxc b/sp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps11.fxc new file mode 100644 index 00000000..e3970e87 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps11.fxc @@ -0,0 +1,9 @@ +struct PS_INPUT +{ + float4 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return i.vColor0; +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc b/sp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc new file mode 100644 index 00000000..e4fffb83 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_notexture_ps2x.fxc @@ -0,0 +1,14 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#include "common_ps_fxc.h" + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return FinalOutput( i.vColor0, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_ps11.fxc b/sp/src/materialsystem/stdshaders/unlitgeneric_ps11.fxc new file mode 100644 index 00000000..071d666c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_ps11.fxc @@ -0,0 +1,12 @@ +sampler TextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord0 : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return i.vColor0 * tex2D( TextureSampler, i.vTexCoord0 ); +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_ps2x.fxc b/sp/src/materialsystem/stdshaders/unlitgeneric_ps2x.fxc new file mode 100644 index 00000000..1620638f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_ps2x.fxc @@ -0,0 +1,19 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +#include "common_ps_fxc.h" + +sampler TextureSampler : register( s0 ); + +struct PS_INPUT +{ + float4 vColor0 : COLOR0; + float2 vTexCoord0 : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float4 result = i.vColor0 * tex2D( TextureSampler, i.vTexCoord0 ); + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_vs11.vsh b/sp/src/materialsystem/stdshaders/unlitgeneric_vs11.vsh new file mode 100644 index 00000000..b165fa7a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_vs11.vsh @@ -0,0 +1,23 @@ +vs.1.1 + +# STATIC: "DETAIL" "0..1" +# STATIC: "ENVMAP" "0..1" +# STATIC: "ENVMAPCAMERASPACE" "0..0" +# STATIC: "ENVMAPSPHERE" "0..1" +# STATIC: "VERTEXCOLOR" "0..1" +# STATIC: "SEPARATEDETAILUVS" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" + +# can't have envmapshere or envmapcameraspace without envmap +# SKIP: !$ENVMAP && ( $ENVMAPSPHERE || $ENVMAPCAMERASPACE ) + +# can't have both envmapsphere and envmapcameraspace +# SKIP: $ENVMAPSPHERE && $ENVMAPCAMERASPACE + +# SKIP: !$DETAIL && $SEPARATEDETAILUVS + + +#include "UnlitGeneric_inc.vsh" + +&UnlitGeneric( $DETAIL, $ENVMAP, $ENVMAPCAMERASPACE, $ENVMAPSPHERE, $VERTEXCOLOR, $SEPARATEDETAILUVS ); diff --git a/sp/src/materialsystem/stdshaders/unlitgeneric_vs20.fxc b/sp/src/materialsystem/stdshaders/unlitgeneric_vs20.fxc new file mode 100644 index 00000000..37249305 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/unlitgeneric_vs20.fxc @@ -0,0 +1,91 @@ +// STATIC: "VERTEXCOLOR" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +#include "common_vs_fxc.h" + +static const int g_FogType = DOWATERFOG; +static const bool g_bSkinning = SKINNING ? true : false; + +const float4 cBaseTextureTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +const float4 cMaskTextureTransform[2] : register( SHADER_SPECIFIC_CONST_2 ); +const float4 cDetailTextureTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); +const float4 g_vVertexColor : register( SHADER_SPECIFIC_CONST_6 ); + +struct VS_INPUT +{ + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + +#if VERTEXCOLOR + float4 vColor : COLOR0; +#endif + + float4 vTexCoord0 : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vTexCoord0 : TEXCOORD0; + float2 vTexCoord1 : TEXCOORD1; + float2 vTexCoord2 : TEXCOORD2; + float2 vTexCoord3 : TEXCOORD3; + + float4 vColor : COLOR0; + float4 fogFactorW : COLOR1; + +#if !defined( _X360 ) + float fog : FOG; +#endif + + float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float3 worldPos; + float3 worldNormal; + + //------------------------------------------------------------------------------ + // Vertex blending + //------------------------------------------------------------------------------ + SkinPosition( g_bSkinning, v.vPos, v.vBoneWeights, v.vBoneIndices, worldPos ); + + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.vProjPos = vProjPos; + vProjPos = dot( float4( worldPos, 1 ), cViewProjZ ); + o.worldPos_projPosZ = float4( worldPos.xyz, vProjPos.z ); + + //------------------------------------------------------------------------------ + // Fog + //------------------------------------------------------------------------------ + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + //------------------------------------------------------------------------------ + // Texture coord transforms + //------------------------------------------------------------------------------ + o.vTexCoord0 = mul( v.vTexCoord0, (float2x4)cBaseTextureTransform ); + o.vTexCoord3 = mul( v.vTexCoord0, (float2x4)cDetailTextureTransform ); + + o.vColor = cModulationColor; + +#if VERTEXCOLOR + // 0 or 1 for g_vVertexColor.x, eliminating a bool + o.vColor = lerp( o.vColor, o.vColor * v.vColor, g_vVertexColor.x ); +#endif + + return o; +} + + + diff --git a/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc new file mode 100644 index 00000000..7768f477 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_ps2x.fxc @@ -0,0 +1,350 @@ +//======= Copyright © 1996-2008, Valve Corporation, All rights reserved. ====== + +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "LIGHTWARPTEXTURE" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "SELFILLUMFRESNEL" "0..1" +// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..6" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "BLENDTINTBYBASEALPHA" "0..1" + +// DYNAMIC: "PIXELFOGTYPE" "0..1" [ps20] +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] [PC] + +// We don't use light combos when doing the flashlight +// SKIP: ( $FLASHLIGHT != 0 ) && ( $NUM_LIGHTS > 0 ) [PC] + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30] + +// SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 ) + +// Don't do diffuse warp on flashlight +// SKIP: ( $FLASHLIGHT == 1 ) && ( $LIGHTWARPTEXTURE == 1 ) [PC] + +// Only warp diffuse if we have it at all +// SKIP: ( $DIFFUSELIGHTING == 0 ) && ( $LIGHTWARPTEXTURE == 1 ) + +// Skip this since it blows ps20 instruction limits +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $LIGHTWARPTEXTURE == 1 ) + +// Only need self illum fresnel when self illum enabled +// SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 ) +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) [PC] +// SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUM == 1 ) [PC] +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $DETAILTEXTURE == 1 ) +// SKIP: ( $SELFILLUMFRESNEL == 1 ) && ( $NORMALMAPALPHAENVMAPMASK == 1 ) + +// BlendTintByBaseAlpha is incompatible with other interpretations of alpha +// SKIP: ($BLENDTINTBYBASEALPHA) && ($SELFILLUM) + +// Only _XBOX allows flashlight and cubemap in the current implementation +// SKIP: $FLASHLIGHT && $CUBEMAP [PC] + +// Meaningless combinations +// SKIP: $NORMALMAPALPHAENVMAPMASK && !$CUBEMAP + +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_EnvmapTint_TintReplaceFactor : register( c0 ); +const float4 g_DiffuseModulation : register( c1 ); +const float4 g_EnvmapContrast_ShadowTweaks : register( c2 ); +const float3 g_EnvmapSaturation : register( c3 ); +const float4 g_SelfIllumTint_and_BlendFactor : register( c4 ); +#define g_SelfIllumTint ( g_SelfIllumTint_and_BlendFactor.rgb) +#define g_DetailBlendFactor (g_SelfIllumTint_and_BlendFactor.w) + +const float3 cAmbientCube[6] : register( c5 ); + +// 11, 12 not used? +#if ( SELFILLUMFRESNEL == 1 ) + const float4 g_SelfIllumScaleBiasExpBrightness : register( c11 ); +#endif + +const float4 g_ShaderControls : register( c12 ); +#define g_fPixelFogType g_ShaderControls.x +#define g_fWriteDepthToAlpha g_ShaderControls.y +#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z + + +// 2 registers each - 6 registers total +PixelShaderLightInfo cLightInfo[3] : register( c13 ); // through c18 + +const float3 g_EyePos : register( c20 ); +const float4 g_FogParams : register( c21 ); + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const float3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler DetailSampler : register( s2 ); +sampler BumpmapSampler : register( s3 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler NormalizeSampler : register( s5 ); +sampler RandRotSampler : register( s6 ); // RandomRotation sampler +sampler FlashlightSampler : register( s7 ); +sampler ShadowDepthSampler : register( s8 ); // Flashlight shadow depth map sampler +sampler DiffuseWarpSampler : register( s9 ); // Lighting warp sampler (1D texture for diffuse lighting modification) + +struct PS_INPUT +{ + float4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0; + float3 lightAtten : TEXCOORD1; + float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3 vWorldNormal : TEXCOORD3; // World-space normal + float4 vWorldTangent : TEXCOORD4; +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float4 vProjPos : TEXCOORD5; +#else + float3 vWorldBinormal : TEXCOORD5; +#endif + float4 worldPos_projPosZ : TEXCOORD6; + float3 detailTexCoord_atten3 : TEXCOORD7; + float4 fogFactorW : COLOR1; + +#if defined( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; +#endif +#endif +}; + +// Calculate both types of Fog and lerp to get result +float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float fRangeFog = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w ); + float fHeightFog = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w ); + return lerp( fRangeFog, fHeightFog, fPixelFogType ); +} + +// Blend both types of Fog and lerp to get result +float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType ) +{ + pixelFogFactor = saturate( pixelFogFactor ); + float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + return lerp( fRangeResult, fHeightResult, fPixelFogType ); +} + +float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE, float fWriteDepthToDestAlpha, const float flProjZ ) +{ + float4 result = vShaderColor; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb *= LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb *= GAMMA_LIGHT_SCALE; + } + + result.a = lerp( result.a, DepthToDestAlpha( flProjZ ), fWriteDepthToDestAlpha ); + + result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType ); + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion + + return result; +} + +float4 main( PS_INPUT i ) : COLOR +{ + bool bCubemap = CUBEMAP ? true : false; + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bSelfIllumFresnel = SELFILLUMFRESNEL ? true : false; + bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bFlashlight = (FLASHLIGHT!=0) ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + int nNumLights = NUM_LIGHTS; + +#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float3 vWorldBinormal = cross( i.vWorldNormal.xyz, i.vWorldTangent.xyz ) * i.vWorldTangent.w; +#else + float3 vWorldBinormal = i.vWorldBinormal; +#endif + + // Unpack four light attenuations + float4 vLightAtten = float4( i.lightAtten, i.detailTexCoord_atten3.z ); + + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + +#if DETAILTEXTURE + float4 detailColor = tex2D( DetailSampler, i.detailTexCoord_atten3.xy ); + baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + + float specularFactor = 1.0f; + float4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); + float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; + + if ( bNormalMapAlphaEnvmapMask ) + specularFactor = normalTexel.a; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + + float3 worldSpaceNormal = float3( 0.0f, 0.0f, 1.0f ); + if ( bDiffuseLighting || bFlashlight || bCubemap || bSelfIllumFresnel ) + { + worldSpaceNormal = Vec3TangentToWorld( tangentSpaceNormal, i.vWorldNormal, i.vWorldTangent, vWorldBinormal ); +#if ( defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) + worldSpaceNormal = normalize( worldSpaceNormal ); +#else + worldSpaceNormal = NormalizeWithCubemap( NormalizeSampler, worldSpaceNormal ); +#endif + } + + if ( bDiffuseLighting ) + { + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, vLightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + false, 1.0f, bDoDiffuseWarp, DiffuseWarpSampler ); + } + + float3 albedo = baseColor; + if (bBlendTintByBaseAlpha) + { + float3 tintedColor = albedo * g_DiffuseModulation.rgb; + tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_EnvmapTint_TintReplaceFactor.w); + albedo = lerp(albedo, tintedColor, baseColor.a); + } + else + { + albedo = albedo * g_DiffuseModulation.rgb; + } + + float alpha = g_DiffuseModulation.a; + if ( !bSelfIllum && !bBlendTintByBaseAlpha ) + { + alpha *= baseColor.a; + } + + +#if FLASHLIGHT + if( bFlashlight ) + { + int nShadowSampleLevel = 0; + bool bDoShadows = false; + float2 vProjPos = float2(0, 0); +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = FLASHLIGHTSHADOWS; + vProjPos = i.vProjPos.xy / i.vProjPos.w; // Screen-space position for shadow map noise +#endif + +#if defined ( _X360 ) + float4 flashlightSpacePosition = i.flashlightSpacePos; +#else + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bDoShadows, false, vProjPos, false, g_EnvmapContrast_ShadowTweaks ); + +#if defined ( _X360 ) + diffuseLighting += flashlightColor; +#else + diffuseLighting = flashlightColor; +#endif + + } +#endif + + + float3 diffuseComponent = albedo * diffuseLighting; + + +#if !FLASHLIGHT || defined ( _X360 ) + if ( bSelfIllum ) + { + #if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file + // This will apply a fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look + #if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))) + float3 vVertexNormal = normalize( i.vWorldNormal.xyz ); + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, normalize( i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ) ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + + float3 selfIllumComponent = g_SelfIllumTint * albedo * g_SelfIllumScaleBiasExpBrightness.w; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a * saturate( flSelfIllumFresnel ) ); + #else + float3 vVertexNormal = i.vWorldNormal.xyz; + float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, ( i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ) ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y; + + float3 selfIllumComponent = g_SelfIllumTint * albedo * g_SelfIllumScaleBiasExpBrightness.w; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a * saturate( flSelfIllumFresnel ) ); + #endif + #else + float3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + #endif + } +#endif + + float3 specularLighting = float3( 0.0f, 0.0f, 0.0f ); +#if !FLASHLIGHT || defined ( _X360 ) + if( bCubemap ) + { + float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint_TintReplaceFactor.rgb; + float3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks ); + float3 greyScale = dot( specularLighting, float3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); + } +#endif + + float3 result = diffuseComponent + specularLighting; + +#if defined(SHADER_MODEL_PS_2_0) + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); +#else + float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); +#endif + +#if defined( SHADER_MODEL_PS_2_0 ) + #if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; + #endif +#else // 2b or higher + alpha = lerp( alpha, fogFactor, g_fPixelFogType * g_fWriteWaterFogToDestAlpha ); // Use the fog factor if it's height fog +#endif + +#if defined( SHADER_MODEL_PS_2_0 ) + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.worldPos_projPosZ.w ); +#else + return FinalOutputConst( float4( result.rgb, alpha ), fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.worldPos_projPosZ.w ); +#endif + +} + diff --git a/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc new file mode 100644 index 00000000..06afd956 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_bump_vs20.fxc @@ -0,0 +1,198 @@ +//======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ====== +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "USE_WITH_2B" "0..1" +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "FLASHLIGHT" "0..1" [XBOX] +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); // 0 & 1 +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); // 4 & 5 +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); // 6, 7, 8, 9 + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); + +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + float3 vTangentS : TANGENT; + float3 vTangentT : BINORMAL; + float4 vUserData : TANGENT; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + + +//----------------------------------------------------------------------------- +// Output vertex format +//----------------------------------------------------------------------------- +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPos : POSITION; +#if !defined( _X360 ) + float fog : FOG; +#endif + // Stuff that is seen by the pixel shader + + float4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0; + float3 lightAtten : TEXCOORD1; + float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD2; + float3 vWorldNormal : TEXCOORD3; // World-space normal + float4 vWorldTangent : TEXCOORD4; +#if USE_WITH_2B + float4 vProjPos : TEXCOORD5; +#else + float3 vWorldBinormal : TEXCOORD5; +#endif + float4 worldPos_projPosZ : TEXCOORD6; + float3 detailTexCoord_atten3 : TEXCOORD7; + float4 fogFactorW : COLOR1; + +#if defined( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD8; +#endif +}; + + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + float4 vPosition = v.vPos; + float3 vNormal; + float4 vTangent; + DecompressVertex_NormalTangent( v.vNormal, v.vUserData, vNormal, vTangent ); + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal, vTangent.xyz ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal, vTangent.xyz ); +#endif + + // Perform skinning + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace( g_bSkinning, vPosition, vNormal, vTangent, + v.vBoneWeights, v.vBoneIndices, worldPos, + worldNormal, worldTangentS, worldTangentT ); + + // Always normalize since flex path is controlled by runtime + // constant not a shader combo and will always generate the normalization + worldNormal = normalize( worldNormal ); + worldTangentS = normalize( worldTangentS ); + worldTangentT = normalize( worldTangentT ); + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + o.vWorldNormal.xyz = worldNormal.xyz; + o.vWorldTangent = float4( worldTangentS.xyz, vTangent.w ); // Propagate binormal sign in world tangent.w + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + +#if USE_WITH_2B + o.vProjPos = vProjPos; +#else + o.vWorldBinormal.xyz = worldTangentT.xyz; +#endif + + o.fogFactorW = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW; +#endif + + // Needed for water fog alpha and diffuse lighting + // FIXME: we shouldn't have to compute this all the time. + o.worldPos_projPosZ = float4( worldPos, vProjPos.z ); + + // Needed for cubemapping + parallax mapping + // FIXME: We shouldn't have to compute this all the time. + //o.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz = VSHADER_VECT_SCALE * (cEyePos - worldPos); + o.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz = normalize( cEyePos.xyz - worldPos.xyz ); + +#if defined( SHADER_MODEL_VS_2_0 ) && ( !USE_STATIC_CONTROL_FLOW ) + o.lightAtten.xyz = float3(0,0,0); + o.detailTexCoord_atten3.z = 0.0f; + #if ( NUM_LIGHTS > 0 ) + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, false ); + #endif + #if ( NUM_LIGHTS > 1 ) + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, false ); + #endif + #if ( NUM_LIGHTS > 2 ) + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, false ); + #endif + #if ( NUM_LIGHTS > 3 ) + o.detailTexCoord_atten3.z = GetVertexAttenForLight( worldPos, 3, false ); + #endif +#else + // Scalar light attenuation + o.lightAtten.x = GetVertexAttenForLight( worldPos, 0, true ); + o.lightAtten.y = GetVertexAttenForLight( worldPos, 1, true ); + o.lightAtten.z = GetVertexAttenForLight( worldPos, 2, true ); + o.detailTexCoord_atten3.z = GetVertexAttenForLight( worldPos, 3, true ); +#endif + + // Base texture coordinate transform + o.baseTexCoord2_tangentSpaceVertToEyeVectorXY.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord2_tangentSpaceVertToEyeVectorXY.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); + + // Detail texture coordinate transform + o.detailTexCoord_atten3.x = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.detailTexCoord_atten3.y = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); + +#if defined( _X360 ) && FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc new file mode 100644 index 00000000..1d1a47d0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc @@ -0,0 +1,484 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======// +// +//=============================================================================// +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "ENVMAPMASK" "0..1" +// STATIC: "BASEALPHAENVMAPMASK" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SELFILLUM_ENVMAPMASK_ALPHA" "0..1" +// STATIC: "DETAIL_BLEND_MODE" "0..9" +// STATIC: "SEAMLESS_BASE" "0..1" +// STATIC: "SEAMLESS_DETAIL" "0..1" +// STATIC: "DISTANCEALPHA" "0..1" +// STATIC: "DISTANCEALPHAFROMDETAIL" "0..1" +// STATIC: "SOFT_MASK" "0..1" +// STATIC: "OUTLINE" "0..1" +// STATIC: "OUTER_GLOW" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] +// STATIC: "DEPTHBLEND" "0..1" [ps20b] [ps30] +// STATIC: "BLENDTINTBYBASEALPHA" "0..1" +// STATIC: "SRGB_INPUT_ADAPTER" "0..1" [ps20b] +// STATIC: "CUBEMAP_SPHERE_LEGACY" "0..1" + +// DYNAMIC: "PIXELFOGTYPE" "0..1" [ps20] +// DYNAMIC: "LIGHTING_PREVIEW" "0..2" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] + +// detail blend mode 6 = ps20b only +// SKIP: $DETAIL_BLEND_MODE == 6 [ps20] + +// SKIP: ($DETAILTEXTURE == 0 ) && ( $DETAIL_BLEND_MODE != 0 ) +// SKIP: ($DETAILTEXTURE == 0 ) && ( $SEAMLESS_DETAIL ) +// SKIP: ($ENVMAPMASK || $SELFILLUM_ENVMAPMASK_ALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL) +// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK +// SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM +// SKIP: $SELFILLUM && $SELFILLUM_ENVMAPMASK_ALPHA +// SKIP: $SELFILLUM_ENVMAPMASK_ALPHA && (! $ENVMAPMASK) +// SKIP: $ENVMAPMASK && ($FLASHLIGHT || $FLASHLIGHTSHADOWS) [PC] +// SKIP: $BASEALPHAENVMAPMASK && ($SEAMLESS_BASE || $SEAMLESS_DETAIL) +// SKIP: ($DISTANCEALPHA == 0) && ($DISTANCEALPHAFROMDETAIL || $SOFT_MASK || $OUTLINE || $OUTER_GLOW) +// SKIP: ($DETAILTEXTURE == 0) && ($DISTANCEALPHAFROMDETAIL) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps30] + +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps20b] +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) [ps30] + +// DISTANCEALPHA-related skips +// SKIP: ($DISTANCEALPHA) && ($ENVMAPMASK || $BASEALPHAENVMAPMASK || $SELFILLUM || $SELFILLUM_ENVMAPMASK_ALPHA ) +// SKIP: ($DISTANCEALPHA) && ($SEAMLESS_BASE || $SEAMLESS_DETAIL || $CUBEMAP || $LIGHTING_PREVIEW ) +// SKIP: ($DISTANCEALPHA) && ($WRITEWATERFOGTODESTALPHA || $PIXELFOGTYPE || $FLASHLIGHT || $FLASHLIGHTSHADOWS || $SRGB_INPUT_ADAPTER ) + +// SKIP: $SEAMLESS_BASE && $SRGB_INPUT_ADAPTER +// SKIP: $SEAMLESS_BASE && ($BLENDTINTBYBASEALPHA ) + +// BlendTintByBaseAlpha is incompatible with other interpretations of alpha +// SKIP: ($BLENDTINTBYBASEALPHA) && ($SELFILLUM || (($DISTANCEALPHA) && ($DISTANCEALPHAFROMDETAIL == 0)) || $BASEALPHAENVMAPMASK) + +// Only _XBOX allows flashlight and cubemap in the current implementation +// SKIP: $FLASHLIGHT && $CUBEMAP [PC] + +// SKIP: $CUBEMAP_SPHERE_LEGACY && ($CUBEMAP == 0) + +#include "common_flashlight_fxc.h" +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_EnvmapTint_TintReplaceFactor : register( c0 ); +const float4 g_DiffuseModulation : register( c1 ); +const float4 g_EnvmapContrast_ShadowTweaks : register( c2 ); +const float4 g_EnvmapSaturation_SelfIllumMask : register( c3 ); +const float4 g_SelfIllumTint_and_BlendFactor : register( c4 ); + +const float4 g_ShaderControls : register( c12 ); +const float4 g_DepthFeatheringConstants : register( c13 ); + +const float4 g_EyePos : register( c20 ); +const float4 g_FogParams : register( c21 ); + +#define g_SelfIllumTint g_SelfIllumTint_and_BlendFactor.xyz +#define g_DetailBlendFactor g_SelfIllumTint_and_BlendFactor.w +#define g_EnvmapSaturation g_EnvmapSaturation_SelfIllumMask.xyz +#define g_SelfIllumMaskControl g_EnvmapSaturation_SelfIllumMask.w + +const float4 g_FlashlightAttenuationFactors : register( c22 ); +const HALF3 g_FlashlightPos : register( c23 ); +const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27 + + +sampler BaseTextureSampler : register( s0 ); +sampler EnvmapSampler : register( s1 ); +sampler DetailSampler : register( s2 ); +sampler EnvmapMaskSampler : register( s4 ); +sampler RandRotSampler : register( s6 ); // RandomRotation sampler +sampler FlashlightSampler : register( s7 ); +sampler ShadowDepthSampler : register( s8 ); // Flashlight shadow depth map sampler +sampler DepthSampler : register( s10 ); //depth buffer sampler for depth blending +sampler SelfIllumMaskSampler : register( s11 ); // selfillummask + +struct PS_INPUT +{ +#if SEAMLESS_BASE + HALF3 baseTexCoord : TEXCOORD0; // Base texture coordinate +#else + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +#endif +#if SEAMLESS_DETAIL + HALF3 detailTexCoord : TEXCOORD1; // Seamless texture coordinate +#else + HALF2 detailTexCoord : TEXCOORD1; // Detail texture coordinate +#endif + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + float3 worldVertToEyeVector : TEXCOORD3; // Necessary for reflection + float3 worldSpaceNormal : TEXCOORD4; // Necessary for cubemaps and flashlight + +#if defined ( _X360 ) +#if FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; +#endif +#endif + + float4 projPos : TEXCOORD6; + float4 worldPos_projPosZ : TEXCOORD7; + float4 fogFactorW : COLOR1; +#if SEAMLESS_BASE || SEAMLESS_DETAIL + float3 SeamlessWeights : COLOR0; // x y z projection weights +#endif +}; + +const float4 g_GlowParameters : register( c5 ); +const float4 g_GlowColor : register( c6 ); +#define GLOW_UV_OFFSET g_GlowParameters.xy +#define OUTER_GLOW_MIN_DVALUE g_GlowParameters.z +#define OUTER_GLOW_MAX_DVALUE g_GlowParameters.w +#define OUTER_GLOW_COLOR g_GlowColor + +#define g_fPixelFogType g_ShaderControls.x +#define g_fWriteDepthToAlpha g_ShaderControls.y +#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z +#define g_fVertexAlpha g_ShaderControls.w + + +const float4 g_DistanceAlphaParams : register( c7 ); +#define SOFT_MASK_MAX g_DistanceAlphaParams.x +#define SOFT_MASK_MIN g_DistanceAlphaParams.y + +const float4 g_OutlineColor : register( c8 ); +#define OUTLINE_COLOR g_OutlineColor + +const float4 g_OutlineParams : register( c9 ); +// these are ordered this way for optimal ps20 swizzling +#define OUTLINE_MIN_VALUE0 g_OutlineParams.x +#define OUTLINE_MAX_VALUE1 g_OutlineParams.y +#define OUTLINE_MAX_VALUE0 g_OutlineParams.z +#define OUTLINE_MIN_VALUE1 g_OutlineParams.w + +#if DETAILTEXTURE +const float3 g_DetailTint : register( c10 ); +#endif + + +// Calculate unified fog +float CalcPixelFogFactorConst( float fPixelFogType, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ ) +{ + float flDepthBelowWater = fPixelFogType*fogParams.y - flWorldPosZ; // above water = negative, below water = positive + float flDepthBelowEye = fPixelFogType*flEyePosZ - flWorldPosZ; // above eye = negative, below eye = positive + // if fPixelFogType == 0, then flDepthBelowWater == flDepthBelowEye and frac will be 1 + float frac = (flDepthBelowEye == 0) ? 1 : saturate(flDepthBelowWater/flDepthBelowEye); + return saturate( min(fogParams.z, flProjPosZ * fogParams.w * frac - fogParams.x) ); +} + +// Blend both types of Fog and lerp to get result +float3 BlendPixelFogConst( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, float fPixelFogType ) +{ + //float3 fRangeResult = lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog + //float3 fHeightResult = lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) ); + //return lerp( fRangeResult, fHeightResult, fPixelFogType ); + pixelFogFactor = lerp( pixelFogFactor*pixelFogFactor, pixelFogFactor, fPixelFogType ); + return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor ); +} + + +float4 FinalOutputConst( const float4 vShaderColor, float pixelFogFactor, float fPixelFogType, const int iTONEMAP_SCALE_TYPE, float fWriteDepthToDestAlpha, const float flProjZ ) +{ + float4 result = vShaderColor; + if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR ) + { + result.rgb *= LINEAR_LIGHT_SCALE; + } + else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA ) + { + result.rgb *= GAMMA_LIGHT_SCALE; + } + + result.a = lerp( result.a, DepthToDestAlpha( flProjZ ), fWriteDepthToDestAlpha ); + + result.rgb = BlendPixelFogConst( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, fPixelFogType ); + result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion + + return result; +} + + +#if LIGHTING_PREVIEW == 2 +LPREVIEW_PS_OUT main( PS_INPUT i ) : COLOR +#else +float4 main( PS_INPUT i ) : COLOR +#endif +{ + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bCubemap = CUBEMAP ? true : false; + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bHasNormal = bCubemap || bDiffuseLighting; + bool bEnvmapMask = ENVMAPMASK ? true : false; + bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bVertexColor = VERTEXCOLOR ? true : false; + bool bFlashlight = FLASHLIGHT ? true : false; + bool bBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA ? true : false; + + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); +#if SEAMLESS_BASE + baseColor = + i.SeamlessWeights.x * tex2D( BaseTextureSampler, i.baseTexCoord.yz )+ + i.SeamlessWeights.y * tex2D( BaseTextureSampler, i.baseTexCoord.zx )+ + i.SeamlessWeights.z * tex2D( BaseTextureSampler, i.baseTexCoord.xy ); +#else + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord.xy ); + +#if SRGB_INPUT_ADAPTER + baseColor.rgb = GammaToLinear( baseColor.rgb ); +#endif + +#endif // !SEAMLESS_BASE + + +#if DISTANCEALPHA && (DISTANCEALPHAFROMDETAIL == 0) + float distAlphaMask = baseColor.a; +#endif + + +#if DETAILTEXTURE +#if SEAMLESS_DETAIL + float4 detailColor = + i.SeamlessWeights.x * tex2D( DetailSampler, i.detailTexCoord.yz )+ + i.SeamlessWeights.y * tex2D( DetailSampler, i.detailTexCoord.zx )+ + i.SeamlessWeights.z * tex2D( DetailSampler, i.detailTexCoord.xy ); +#else + float4 detailColor = tex2D( DetailSampler, i.detailTexCoord.xy ); +#endif + detailColor.rgb *= g_DetailTint; + +#if DISTANCEALPHA && (DISTANCEALPHAFROMDETAIL == 1) + float distAlphaMask = detailColor.a; + detailColor.a = 1.0; // make tcombine treat as 1.0 +#endif + baseColor = + TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + +#if DISTANCEALPHA + // now, do all distance alpha effects + //if ( OUTLINE && ( distAlphaMask >= OUTLINE_MIN_VALUE0 ) && ( distAlphaMask <= OUTLINE_MAX_VALUE1 ) ) + //{ + // float oFactor=1.0; + // if ( distAlphaMask <= OUTLINE_MIN_VALUE1 ) + // { + // oFactor=smoothstep( OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, distAlphaMask ); + // } + // else + // { + // oFactor=smoothstep( OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, distAlphaMask ); + // } + // baseColor = lerp( baseColor, OUTLINE_COLOR, oFactor ); + //} + if ( OUTLINE ) + { + float4 oFactors = smoothstep(g_OutlineParams.xyzw, g_OutlineParams.wzyx, distAlphaMask ); + baseColor = lerp( baseColor, g_OutlineColor, oFactors.x * oFactors.y ); + } + + float mskUsed; + if ( SOFT_MASK ) + { + mskUsed = smoothstep( SOFT_MASK_MIN, SOFT_MASK_MAX, distAlphaMask ); + baseColor.a *= mskUsed; + } + else + { + mskUsed = distAlphaMask >= 0.5; + if (DETAILTEXTURE ) + baseColor.a *= mskUsed; + else + baseColor.a = mskUsed; + } + + + if ( OUTER_GLOW ) + { +#if DISTANCEALPHAFROMDETAIL + float4 glowTexel = tex2D( DetailSampler, i.detailTexCoord.xy+GLOW_UV_OFFSET ); +#else + float4 glowTexel = tex2D( BaseTextureSampler, i.baseTexCoord.xy+GLOW_UV_OFFSET ); +#endif + float4 glowc = OUTER_GLOW_COLOR*smoothstep( OUTER_GLOW_MIN_DVALUE, OUTER_GLOW_MAX_DVALUE, glowTexel.a ); + baseColor = lerp( glowc, baseColor, mskUsed ); + } + +#endif // DISTANCEALPHA + + float3 specularFactor = 1.0f; + float4 envmapMaskTexel; + if( bEnvmapMask ) + { + envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord.xy ); + specularFactor *= envmapMaskTexel.xyz; + } + + if( bBaseAlphaEnvmapMask ) + { + specularFactor *= 1.0 - baseColor.a; // this blows! + } + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + if( bDiffuseLighting || bVertexColor && !( bVertexColor && bDiffuseLighting ) ) + { + diffuseLighting = i.color.rgb; + } + + float3 albedo = baseColor; + if (bBlendTintByBaseAlpha) + { + float3 tintedColor = albedo * g_DiffuseModulation.rgb; + tintedColor = lerp(tintedColor, g_DiffuseModulation.rgb, g_EnvmapTint_TintReplaceFactor.w); + albedo = lerp(albedo, tintedColor, baseColor.a); + } + else + { + albedo = albedo * g_DiffuseModulation.rgb; + } + + float alpha = g_DiffuseModulation.a; + if ( !bBaseAlphaEnvmapMask && !bSelfIllum && !bBlendTintByBaseAlpha ) + { + alpha *= baseColor.a; + } + + + if( bFlashlight ) + { + int nShadowSampleLevel = 0; + bool bDoShadows = false; +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = true; +#endif + +#if defined ( _X360 ) + float4 flashlightSpacePosition = i.flashlightSpacePos; +#else + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + // We want the N.L to happen on the flashlight pass, but can't afford it on ps20 + bool bUseWorldNormal = true; +#if ( defined( SHADER_MODEL_PS_2_0 ) && ( DETAILTEXTURE ) ) + bUseWorldNormal = false; +#endif + float3 flashlightColor = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + i.worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler, + RandRotSampler, nShadowSampleLevel, bDoShadows, false, i.projPos.xy / i.projPos.w, false, g_EnvmapContrast_ShadowTweaks, bUseWorldNormal ); + +#if defined ( _X360 ) + diffuseLighting += flashlightColor; +#else + diffuseLighting = flashlightColor; +#endif + } + + if( bVertexColor && bDiffuseLighting ) + { + albedo *= i.color.rgb; + } + + alpha = lerp( alpha, alpha * i.color.a, g_fVertexAlpha ); + + float3 diffuseComponent = albedo * diffuseLighting; + +#if DETAILTEXTURE + diffuseComponent = + TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_DetailBlendFactor ); +#endif + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + +#if !FLASHLIGHT || defined ( _X360 ) + #if SELFILLUM_ENVMAPMASK_ALPHA + // range of alpha: + // 0 - 0.125 = lerp(diffuse,selfillum,alpha*8) + // 0.125-1.0 = selfillum*(1+alpha-0.125)*8 (over bright glows) + HALF3 selfIllumComponent = g_SelfIllumTint * albedo; + half Adj_Alpha=8*envmapMaskTexel.a; + diffuseComponent=( max( 0, 1-Adj_Alpha ) * diffuseComponent) + Adj_Alpha * selfIllumComponent; + #else + if ( bSelfIllum ) + { + float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord.xy ); + vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl ); + diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint * albedo, vSelfIllumMask ); + } + #endif + + if( bCubemap ) + { +#if CUBEMAP_SPHERE_LEGACY + HALF3 reflectVect = normalize(CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector.xyz )); + + specularLighting = 0.5 * tex2D( EnvmapSampler, float2(reflectVect.x, reflectVect.y) ) * g_DiffuseModulation.rgb * diffuseLighting; +#else + HALF3 reflectVect = CalcReflectionVectorUnnormalized( i.worldSpaceNormal, i.worldVertToEyeVector.xyz ); + + specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ); + specularLighting *= specularFactor; + specularLighting *= g_EnvmapTint_TintReplaceFactor.rgb; + HALF3 specularLightingSquared = specularLighting * specularLighting; + specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast_ShadowTweaks ); + HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) ); + specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation ); +#endif + } +#endif + + HALF3 result = diffuseComponent + specularLighting; + +#if LIGHTING_PREVIEW +# if LIGHTING_PREVIEW == 1 + float dotprod=0.7+0.25*dot(i.worldSpaceNormal,normalize(float3(1,2,-.5))); + return FinalOutput( float4( dotprod*albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); +# else + LPREVIEW_PS_OUT ret; + ret.flags=float4(1,1,1,1); + ret.color=float4( albedo.xyz, alpha ); + ret.normal=float4(i.worldSpaceNormal,alpha); + ret.position=float4(i.worldPos_projPosZ.xyz, alpha); + return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +# endif +#else + +# if (DEPTHBLEND == 1) + { + float2 vScreenPos; + vScreenPos.x = i.projPos.x; + vScreenPos.y = -i.projPos.y; + vScreenPos = (vScreenPos + i.projPos.w) * 0.5f; + alpha *= DepthFeathering( DepthSampler, vScreenPos / i.projPos.w, i.projPos.w - i.projPos.z, i.projPos.w, g_DepthFeatheringConstants ); + } +# endif + +#if defined( SHADER_MODEL_PS_2_0 ) + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.projPos.z ); + #if (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = lerp( alpha, fogFactor, g_fWriteWaterFogToDestAlpha ); + #endif + return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.projPos.z ); +#else // 2b or higher + float fogFactor = CalcPixelFogFactorConst( g_fPixelFogType, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.projPos.z ); + alpha = lerp( alpha, fogFactor, g_fWriteWaterFogToDestAlpha ); // Use the fog factor if it's height fog + return FinalOutputConst( float4( result.rgb, alpha ), fogFactor, g_fPixelFogType, TONEMAP_SCALE_LINEAR, g_fWriteDepthToAlpha, i.projPos.z ); +#endif + +#endif +} + diff --git a/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc new file mode 100644 index 00000000..9db6f864 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_vs20.fxc @@ -0,0 +1,249 @@ +//======= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====== + +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "CUBEMAP" "0..1" +// STATIC: "HALFLAMBERT" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SEAMLESS_BASE" "0..1" +// STATIC: "SEAMLESS_DETAIL" "0..1" +// STATIC: "SEPARATE_DETAIL_UVS" "0..1" +// STATIC: "DECAL" "0..1" [vs30] +// STATIC: "USE_STATIC_CONTROL_FLOW" "0..1" [vs20] +// STATIC: "DONT_GAMMA_CONVERT_VERTEX_COLOR" "0..1" +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DYNAMIC_LIGHT" "0..1" +// DYNAMIC: "STATIC_LIGHT" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" [PC] +// DYNAMIC: "LIGHTING_PREVIEW" "0..0" [XBOX] +// DYNAMIC: "MORPHING" "0..1" [vs30] +// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] + +// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo +// SKIP: $USE_STATIC_CONTROL_FLOW && ( $NUM_LIGHTS > 0 ) [vs20] +// SKIP: ($SEPARATE_DETAIL_UVS) && ($SEAMLESS_DETAIL) +// SKIP: ($DONT_GAMMA_CONVERT_VERTEX_COLOR && ( ! $VERTEXCOLOR ) ) +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +static const bool g_bVertexColor = VERTEXCOLOR ? true : false; +static const bool g_bCubemap = CUBEMAP ? true : false; +static const bool g_bFlashlight = FLASHLIGHT ? true : false; +static const bool g_bHalfLambert = HALFLAMBERT ? true : false; +#if (defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL) +static const bool g_bDecalOffset = true; +#else +static const bool g_bDecalOffset = false; +#endif + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_0 ); +#if SEAMLESS_DETAIL || SEAMLESS_BASE +const float cSeamlessScale : register( SHADER_SPECIFIC_CONST_2); +#define SEAMLESS_SCALE cSeamlessScale.x +#endif + +const float4 cDetailTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_4 ); + +#if defined ( _X360 ) +const float4x4 g_FlashlightWorldToTexture : register( SHADER_SPECIFIC_CONST_6 ); // 6, 7, 8, 9 +#endif + +#ifdef SHADER_MODEL_VS_3_0 +// NOTE: cMorphTargetTextureDim.xy = target dimensions, +// cMorphTargetTextureDim.z = 4tuples/morph +const float3 cMorphTargetTextureDim : register( SHADER_SPECIFIC_CONST_10 ); +const float4 cMorphSubrect : register( SHADER_SPECIFIC_CONST_11 ); +sampler2D morphSampler : register( D3DVERTEXTEXTURESAMPLER0, s0 ); +#endif + +struct VS_INPUT +{ + // This is all of the stuff that we ever use. + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vColor : COLOR0; + float3 vSpecular : COLOR1; + // make these float2's and stick the [n n 0 1] in the dot math. + float4 vTexCoord0 : TEXCOORD0; + float4 vTexCoord1 : TEXCOORD1; + float4 vTexCoord2 : TEXCOORD2; + float4 vTexCoord3 : TEXCOORD3; + + // Position and normal/tangent deltas + float3 vPosFlex : POSITION1; + float3 vNormalFlex : NORMAL1; +#ifdef SHADER_MODEL_VS_3_0 + float vVertexID : POSITION2; +#endif +}; + + +struct VS_OUTPUT +{ + float4 projPos : POSITION; // Projection-space position +#if !defined( _X360 ) + float fog : FOG; +#endif + +#if SEAMLESS_BASE + HALF3 SeamlessTexCoord : TEXCOORD0; // Base texture x/y/z (indexed by swizzle) +#else + HALF2 baseTexCoord : TEXCOORD0; // Base texture coordinate +#endif +#if SEAMLESS_DETAIL + HALF3 SeamlessDetailTexCoord : TEXCOORD1; // Detail texture coordinate +#else + HALF2 detailTexCoord : TEXCOORD1; // Detail texture coordinate +#endif + float4 color : TEXCOORD2; // Vertex color (from lighting or unlit) + +#if CUBEMAP || _X360 + float3 worldVertToEyeVector : TEXCOORD3; // Necessary for cubemaps +#endif + + float3 worldSpaceNormal : TEXCOORD4; // Necessary for cubemaps and flashlight + +#if defined ( _X360 ) && FLASHLIGHT + float4 flashlightSpacePos : TEXCOORD5; +#endif + + float4 vProjPos : TEXCOORD6; + float4 worldPos_ProjPosZ : TEXCOORD7; + float4 fogFactorW : COLOR1; +#if SEAMLESS_DETAIL || SEAMLESS_BASE + float3 SeamlessWeights : COLOR0; // x y z projection weights +#endif + +}; + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + bool bDynamicLight = DYNAMIC_LIGHT ? true : false; + bool bStaticLight = STATIC_LIGHT ? true : false; + bool bDoLighting = !g_bVertexColor && (bDynamicLight || bStaticLight); + + float4 vPosition = v.vPos; + float3 vNormal = 0; + if ( bDoLighting || FLASHLIGHT || SEAMLESS_BASE || SEAMLESS_DETAIL || LIGHTING_PREVIEW || g_bDecalOffset || CUBEMAP ) + { + // The vertex only contains valid normals if they are actually needed (fetching them when absent makes D3D complain) + DecompressVertex_Normal( v.vNormal, vNormal ); + } + +#if SEAMLESS_BASE || SEAMLESS_DETAIL + // compute blend weights in rgb + float3 NNormal=normalize( vNormal ); + o.SeamlessWeights.xyz = NNormal * NNormal; // sums to 1. +#endif + +#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING + ApplyMorph( v.vPosFlex, v.vNormalFlex, vPosition.xyz, vNormal ); +#else + ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, + v.vVertexID, v.vTexCoord2, vPosition.xyz, vNormal ); +#endif + + // Perform skinning + float3 worldNormal, worldPos; + SkinPositionAndNormal( + g_bSkinning, + vPosition, vNormal, + v.vBoneWeights, v.vBoneIndices, + worldPos, worldNormal ); + + if ( !g_bVertexColor ) + { + worldNormal = normalize( worldNormal ); + } + +#if defined( SHADER_MODEL_VS_3_0 ) && MORPHING && DECAL + // Avoid z precision errors + worldPos += worldNormal * 0.05f * v.vTexCoord2.z; +#endif + + o.worldSpaceNormal = worldNormal; + + // Transform into projection space + float4 vProjPos = mul( float4( worldPos, 1 ), cViewProj ); + o.projPos = vProjPos; + vProjPos.z = dot( float4( worldPos, 1 ), cViewProjZ ); + + o.vProjPos = vProjPos; + o.fogFactorW.w = CalcFog( worldPos, vProjPos, g_FogType ); +#if !defined( _X360 ) + o.fog = o.fogFactorW.w; +#endif + o.worldPos_ProjPosZ.xyz = worldPos.xyz; + o.worldPos_ProjPosZ.w = vProjPos.z; + + // Needed for cubemaps +#if CUBEMAP + o.worldVertToEyeVector.xyz = VSHADER_VECT_SCALE * (cEyePos - worldPos); +#endif + +#if !defined (_X360) && FLASHLIGHT + o.color = float4( 0.0f, 0.0f, 0.0f, 0.0f ); +#else + if ( g_bVertexColor ) + { + // Assume that this is unlitgeneric if you are using vertex color. + o.color.rgb = ( DONT_GAMMA_CONVERT_VERTEX_COLOR ) ? v.vColor.rgb : GammaToLinear( v.vColor.rgb ); + o.color.a = v.vColor.a; + } + else + { + #if ( ( USE_STATIC_CONTROL_FLOW ) || defined ( SHADER_MODEL_VS_3_0 ) ) + { + o.color.xyz = DoLighting( worldPos, worldNormal, v.vSpecular, bStaticLight, bDynamicLight, g_bHalfLambert ); + } + #else + { + o.color.xyz = DoLightingUnrolled( worldPos, worldNormal, v.vSpecular, bStaticLight, bDynamicLight, g_bHalfLambert, NUM_LIGHTS ); + } + #endif + } +#endif + + +#if SEAMLESS_BASE + o.SeamlessTexCoord.xyz = SEAMLESS_SCALE * v.vPos.xyz; +#else + // Base texture coordinates + o.baseTexCoord.x = dot( v.vTexCoord0, cBaseTexCoordTransform[0] ); + o.baseTexCoord.y = dot( v.vTexCoord0, cBaseTexCoordTransform[1] ); +#endif + +#if SEAMLESS_DETAIL + // FIXME: detail texcoord as a 2d xform doesn't make much sense here, so I just do enough so + // that scale works. More smartness could allow 3d xform. + o.SeamlessDetailTexCoord.xyz = (SEAMLESS_SCALE*cDetailTexCoordTransform[0].x) * v.vPos.xyz; +#else + // Detail texture coordinates + // FIXME: This shouldn't have to be computed all the time. + o.detailTexCoord.x = dot( v.vTexCoord0, cDetailTexCoordTransform[0] ); + o.detailTexCoord.y = dot( v.vTexCoord0, cDetailTexCoordTransform[1] ); +#endif + +#if SEPARATE_DETAIL_UVS + o.detailTexCoord.xy = v.vTexCoord1.xy; +#endif + +#if LIGHTING_PREVIEW + float dot=0.5+0.5*worldNormal*float3(0.7071,0.7071,0); + o.color.xyz=float3(dot,dot,dot); +#endif + +#if defined ( _X360 ) && FLASHLIGHT + o.flashlightSpacePos = mul( float4( worldPos, 1.0f ), g_FlashlightWorldToTexture ); +#endif + + return o; +} + + diff --git a/sp/src/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc b/sp/src/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc new file mode 100644 index 00000000..52812637 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlit_lighting_only_ps2x.fxc @@ -0,0 +1,68 @@ +//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ====== + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "DIFFUSELIGHTING" "0..1" +// STATIC: "HALFLAMBERT" "0..1" + +// DYNAMIC: "AMBIENT_LIGHT" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..2" [ps20] +// DYNAMIC: "NUM_LIGHTS" "0..4" [ps20b] + +#define HDRTYPE HDR_TYPE_NONE +#include "common_vertexlitgeneric_dx9.h" + +const float4 g_OverbrightFactor : register( c4 ); +const float3 cAmbientCube[6] : register( c6 ); + +PixelShaderLightInfo cLightInfo[3] : register(c13); + +sampler BumpmapSampler : register( s0 ); +sampler NormalizeSampler : register( s1 ); + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + // detail textures and bumpmaps are mutually exclusive so that we have enough texcoords. + float2 detailOrBumpTexCoord : TEXCOORD1; + // bump mapping and a separate envmap mask texture are mutually exclusive. + float2 envmapMaskTexCoord : TEXCOORD2; + float3 worldVertToEyeVector : TEXCOORD3; + float3x3 tangentSpaceTranspose : TEXCOORD4; + float4 worldPos_projPosZ : TEXCOORD5; + float2 lightAtten01 : TEXCOORD6; + float2 lightAtten23 : TEXCOORD7; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDiffuseLighting = DIFFUSELIGHTING ? true : false; + bool bHalfLambert = HALFLAMBERT ? true : false; + bool bAmbientLight = AMBIENT_LIGHT ? true : false; + int nNumLights = NUM_LIGHTS; + + float4 vLightAtten = float4( i.lightAtten01, i.lightAtten23 ); + + float3 tangentSpaceNormal = float3( 0.0f, 0.0f, 1.0f ); + float4 normalTexel = 1.0f; + float4 baseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); + + normalTexel = tex2D( BumpmapSampler, i.detailOrBumpTexCoord ); + tangentSpaceNormal = 2.0f * normalTexel - 1.0f; + + float3 diffuseLighting = float3( 1.0f, 1.0f, 1.0f ); + if( bDiffuseLighting ) + { + float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal ); + float3 staticLightingColor = float3( 0.0f, 0.0f, 0.0f ); + diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal, + float3( 0.0f, 0.0f, 0.0f ), false, bAmbientLight, + vLightAtten, cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + false, 0, false, NormalizeSampler ); + // multiply by .5 since we want a 50% (in gamma space) reflective surface) + diffuseLighting *= pow( 0.5f, 2.2f ); + } + + return FinalOutput( float4( diffuseLighting, 1.0f ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE ); +} + diff --git a/sp/src/materialsystem/stdshaders/vertexlit_notexture.psh b/sp/src/materialsystem/stdshaders/vertexlit_notexture.psh new file mode 100644 index 00000000..8b550bde --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlit_notexture.psh @@ -0,0 +1,13 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +mov r0, v0 +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_basealphamaskedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_basealphamaskedenvmap.psh new file mode 100644 index 00000000..5faa681d --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_basealphamaskedenvmap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask (in alpha channel) + +mul r0, t0, c3 ; base times modulation +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailbasealphamaskedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailbasealphamaskedenvmap.psh new file mode 100644 index 00000000..ab653f19 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailbasealphamaskedenvmap.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask (in alpha channel) +tex t3 ; detail texture + +mul r0, t0, c3 ; base times modulation +mul_x2 r0.rgb, r0, t3 ; detail texture +mul r1, t1, 1-t2.a ; Envmap * mask (in alpha channel) +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailenvmap.psh new file mode 100644 index 00000000..ac030f0a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailenvmap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t3 ; detail texture + +mul r0, t0, c3 ; base times modulation +mul_x2 r0.rgb, r0, t3 ; detail texture +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailmaskedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailmaskedenvmap.psh new file mode 100644 index 00000000..51873a08 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailmaskedenvmap.psh @@ -0,0 +1,21 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask +tex t3 ; detail texture + +mul r0, t0, c3 ; Base times modulation +mul_x2 r0.rgb, r0, t3 ; detail texture +mul r1, t1, t2 ; Envmap * mask +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedenvmap.psh new file mode 100644 index 00000000..44dee8d4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedenvmap.psh @@ -0,0 +1,28 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +tex t1 +tex t3 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedmaskedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedmaskedenvmap.psh new file mode 100644 index 00000000..4be599ca --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_detailselfilluminatedmaskedenvmap.psh @@ -0,0 +1,29 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask +tex t3 ; Detail + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul_x2 r0.rgb, r0, t3 ; detail texture + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx6.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx6.cpp new file mode 100644 index 00000000..8ecd111f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx6.cpp @@ -0,0 +1,421 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX6 ) + +BEGIN_SHADER( VertexLitGeneric_DX6, + "Help for VertexLitGeneric_DX6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No envmap uses mode 0, it's one less pass + // Also, if multipass = 0, then go to mode 0 also + if ( ( !params[ENVMAP]->IsDefined() ) || + ( !IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ENVMAPMODE ); + } + + // Vertex color requires mode 1 + if ( IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPMODE ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if ( IS_FLAG_SET(MATERIAL_VAR_DECAL) ) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_SOFTWARE_LIGHTING ); + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + } + + int GetDrawFlagsPass1(IMaterialVar** params) + { + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_COLOR; + if (params[BASETEXTURE]->IsTexture()) + flags |= SHADER_DRAW_TEXCOORD0; + return flags; + } + + void DrawVertexLightingOnly( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + + SetModulationShadowState(); + SetDefaultBlendingShadowState( ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetModulationDynamicState(); + } + Draw(); + } + + void MultiplyByVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + // FIXME: How to deal with texture alpha?? + + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, false ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + + // NOTE: We're not doing lightmapping here, but we want to use the + // same blend mode as we used for lightmapping + pShaderShadow->EnableBlending( true ); + SingleTextureLightmapBlendMode(); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + + // This here will perform color = vertex light * (cc alpha) + 1 * (1 - cc alpha) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_BLEND_CONSTANTALPHA, + SHADER_TEXARG_VERTEXCOLOR, SHADER_TEXARG_CONSTANTCOLOR ); + + // Alpha isn't used, it doesn't matter what we set it to. + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_NONE, SHADER_TEXARG_NONE ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR ); + FogToOOOverbright(); + } + DYNAMIC_STATE + { + // Put the alpha in the color channel to modulate the color down.... + float alpha = GetAlpha(); + pShaderAPI->Color4f( OO_OVERBRIGHT, OO_OVERBRIGHT, OO_OVERBRIGHT, alpha ); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( false ); + } + } + + + //----------------------------------------------------------------------------- + // Used by mode 1 + //----------------------------------------------------------------------------- + + void DrawBaseTimesVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Base times vertex lighting, no vertex color + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + + // Independenly configure alpha and color + + // Color = Color mod * Vertex Light * Tex (x2) + // Alpha = Constant Alpha * Tex Alpha (no tex alpha if self illum == 1) + // Can't have color modulation here + pShaderShadow->EnableConstantColor( IsColorModulating() ); + + // Independenly configure alpha and color + pShaderShadow->EnableAlphaPipe( true ); + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) ); + + if (!IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && !IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, true ); + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetModulationDynamicState(); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableAlphaPipe( false ); + } + } + + //----------------------------------------------------------------------------- + // Envmap times vertex lighting, no vertex color + //----------------------------------------------------------------------------- + + void DrawEnvmapTimesVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + int materialVarFlags = params[FLAGS]->GetIntValue(); + + // alpha test + pShaderShadow->EnableAlphaTest( false ); + + int flags = SetShadowEnvMappingState( ENVMAPMASK ) | SHADER_DRAW_COLOR; + bool hasEnvMapMask = params[ENVMAPMASK]->IsTexture(); + + pShaderShadow->OverbrightValue( hasEnvMapMask ? + SHADER_TEXTURE_STAGE1 : SHADER_TEXTURE_STAGE0, OVERBRIGHT ); + + // Independenly configure alpha and color + + // Color = Env map * Vertex Light * Envmapmask (x2) + // Alpha = Constant Alpha * Vertex light alpha * Env Map mask Alpha + pShaderShadow->EnableConstantColor( IsColorModulating() ); + + pShaderShadow->EnableAlphaPipe( true ); + pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + pShaderShadow->EnableVertexAlpha( (materialVarFlags & MATERIAL_VAR_VERTEXALPHA) != 0 ); + if (hasEnvMapMask) + pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, true ); + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { + SetDynamicEnvMappingState( ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + Draw(); + + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( false ); + pShaderShadow->EnableAlphaPipe( false ); + } + } + + void DrawMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + bool texDefined = params[BASETEXTURE]->IsTexture(); + bool envDefined = params[ENVMAP]->IsTexture(); +// bool maskDefined = params[ENVMAPMASK]->IsTexture(); + + // Pass 1 : Base + env + + // FIXME: Could make it 1 pass for base + env, if it wasn't + // for the envmap tint. So this is 3 passes for now.... + + // If it's base + mask * env, gotta do that in 2 passes + // Gotta do funky stuff to fade out self-illuminated stuff + bool hasEnvMapTint = !IsWhite(ENVMAPTINT); + + // Special case, can do in one pass + if (!hasEnvMapTint && !texDefined && !IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) && + !IsColorModulating() ) + { + DrawEnvmapTimesVertexLighting( params, pShaderAPI, pShaderShadow ); + return; + } + + if (texDefined) + { + FixedFunctionBaseTimesDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + else + { + FixedFunctionMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + + // We can get here if multipass isn't set if we specify a vertex color + if ( IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) + { + if ( texDefined && envDefined ) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + + // Pass 2 : * vertex lighting + MultiplyByVertexLighting( params, pShaderAPI, pShaderShadow ); + + // FIXME: We could add it to the lightmap + // Draw the selfillum pass (blows away envmap at self-illum points) + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + + void DrawMode0( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // Pass 1 : Base * lightmap or just lightmap + if ( params[BASETEXTURE]->IsTexture() ) + { + DrawBaseTimesVertexLighting( params, pShaderAPI, pShaderShadow ); + + // Detail map + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Draw the selfillum pass + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + else + { + DrawVertexLightingOnly( params, pShaderAPI, pShaderShadow ); + + // Detail map + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + + // Pass 2 : Masked environment map + if ( params[ENVMAP]->IsTexture() && + (IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) ) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + } + + SHADER_DRAW + { + bool useMode1 = IS_FLAG_SET(MATERIAL_VAR_ENVMAPMODE); + if (!useMode1) + { + // Base * Vertex Lighting + env + DrawMode0( params, pShaderAPI, pShaderShadow ); + } + else + { + // ( Base + env ) * Vertex Lighting + DrawMode1( params, pShaderAPI, pShaderShadow ); + } + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx7.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx7.cpp new file mode 100644 index 00000000..7a114a56 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx7.cpp @@ -0,0 +1,413 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX7 ) +DEFINE_FALLBACK_SHADER( Skin_DX9, VertexLitGeneric_DX7 ) + +BEGIN_SHADER( VertexLitGeneric_DX7, + "Help for VertexLitGeneric_DX7" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ); + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 70) + return "VertexLitGeneric_DX6"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + } + + void DrawBaseTimesVertexColor( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + pShaderShadow->EnableCustomPixelPipe( true ); + + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_VERTEXCOLOR ); + + // Get alpha from the texture so that alpha blend and alpha test work properly. + bool bTextureIsTranslucent = TextureIsTranslucent( BASETEXTURE, true ); + if ( bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + } + else + { + if ( IsAlphaModulating() ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_ONE, SHADER_TEXARG_NONE ); + } + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_NORMAL | SHADER_DRAW_TEXCOORD0; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + + if ( IsAlphaModulating() || IsColorModulating() ) + { + pShaderShadow->CustomTextureStages( 2 ); + + if ( IsColorModulating() ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + + // Get alpha from the texture so that alpha blend and alpha test work properly. + if ( IsAlphaModulating() && bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + } + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetModulationDynamicState(); + } + Draw(); + } + + void DrawVertexColorNoBase( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + pShaderShadow->EnableCustomPixelPipe( true ); + + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_ONE, SHADER_TEXARG_VERTEXCOLOR ); + + int flags = SHADER_DRAW_POSITION; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + } + DYNAMIC_STATE + { +// SetModulationDynamicState(); + } + Draw(); + } + + void DrawBaseTimesBakedVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + // alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ); + + // base + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + int flags = SHADER_DRAW_POSITION; + if (params[BASETEXTURE]->IsTexture()) + { + flags |= SHADER_DRAW_TEXCOORD1; + } + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_SPECULARCOLOR, SHADER_TEXARG_TEXTURE ); + + // Get alpha from the texture so that alpha blend and alpha test work properly. + bool bTextureIsTranslucent = TextureIsTranslucent( BASETEXTURE, true ); + if ( bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_NONE ); + } + else + { + if ( IsAlphaModulating() ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_ONE, SHADER_TEXARG_NONE ); + } + } + + if ( IsAlphaModulating() || IsColorModulating() ) + { + pShaderShadow->CustomTextureStages( 2 ); + + if ( IsColorModulating()) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + + // Get alpha from the texture so that alpha blend and alpha test work properly. + if ( IsAlphaModulating() && bTextureIsTranslucent ) + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + } + } + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + DYNAMIC_STATE + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE1, BASETEXTURETRANSFORM ); + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetModulationDynamicState(); + } + Draw(); + } + + void DrawBakedVertexLightingNoBase( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + SHADOW_STATE + { + int flags = SHADER_DRAW_POSITION; + pShaderShadow->DrawFlags( flags ); + DefaultFog(); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 1 ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_SPECULARCOLOR, SHADER_TEXARG_NONE ); + + // Alpha isn't used, it doesn't matter what we set it to. + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_NONE, SHADER_TEXARG_NONE ); + } + DYNAMIC_STATE + { + } + Draw(); + } + + SHADER_DRAW + { + bool bBakedLighting = IS_FLAG2_SET( MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING ); + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + return; + } + // Pass 1 : Base * lightmap or just lightmap + if ( params[BASETEXTURE]->IsTexture() ) + { + // Draw base times lighting. + // Lighting is either sent down per vertex from the app, or it's in the second + // stream as color values. + if( bBakedLighting ) + { + DrawBaseTimesBakedVertexLighting( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawBaseTimesVertexColor( params, pShaderAPI, pShaderShadow ); + } + + // Detail map + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + + // Draw the selfillum pass + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) ) + { + FixedFunctionSelfIlluminationPass( + SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT ); + } + } + else + { + if( bBakedLighting ) + { + DrawBakedVertexLightingNoBase( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawVertexColorNoBase( params, pShaderAPI, pShaderShadow ); + } + + FixedFunctionMultiplyByDetailPass( + BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE ); + } + + + // Pass 2 : Masked environment map + if ( params[ENVMAP]->IsTexture() && (IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) ) + { + FixedFunctionAdditiveMaskedEnvmapPass( + ENVMAP, ENVMAPMASK, BASETEXTURE, + ENVMAPFRAME, ENVMAPMASKFRAME, FRAME, + BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT ); + } + + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx8.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx8.cpp new file mode 100644 index 00000000..31addf42 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx8.cpp @@ -0,0 +1,807 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "vertexlitgeneric_vs11.inc" +#include "vertexlitgeneric_selfillumonly.inc" +#include "emissive_scroll_blended_pass_helper.h" +#include "flesh_interior_blended_pass_helper.h" +#include "cloak_blended_pass_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX8 ) +DEFINE_FALLBACK_SHADER( Skin_DX9, VertexLitGeneric_DX8 ) + +BEGIN_VS_SHADER( VertexLitGeneric_DX8, + "Help for VertexLitGeneric" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" ) + SHADER_PARAM( FORCEBUMP, SHADER_PARAM_TYPE_BOOL, "0", "0 == Do bumpmapping if the card says it can handle it. 1 == Always do bumpmapping." ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + // Color Replacement Pass + SHADER_PARAM( BLENDTINTBYBASEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use the base alpha to blend in the $color modulation") + SHADER_PARAM( BLENDTINTCOLOROVERBASE, SHADER_PARAM_TYPE_FLOAT, "0", "blend between tint acting as a multiplication versus a replace" ) + + END_SHADER_PARAMS + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + // Delete these lines if not bump mapping! + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = EMISSIVEBLENDBASETEXTURE; + info.m_nFlowTexture = -1; // Not used in DX8 + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + info.m_nTime = TIME; + } + + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + // We don't want no stinking bump mapping on models in dx8. + // Wait a minute! We want specular bump. .need to make that work by itself. +// params[BUMPMAP]->SetUndefined(); +// if( IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) ) +// { +// CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); +// params[ENVMAP]->SetUndefined(); +// } + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + + if( !params[ENVMAPTINT]->IsDefined() ) + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + + if( !params[DETAILSCALE]->IsDefined() ) + params[DETAILSCALE]->SetFloatValue( 4.0f ); + + if( !params[DETAILBLENDFACTOR]->IsDefined() ) + params[DETAILBLENDFACTOR]->SetFloatValue( 1.0f ); + + if( !params[DETAILBLENDMODE]->IsDefined() ) + params[DETAILBLENDMODE]->SetFloatValue( 0 ); + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + + if( !params[ENVMAPSATURATION]->IsDefined() ) + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + + if( !params[ENVMAPFRAME]->IsDefined() ) + params[ENVMAPFRAME]->SetIntValue( 0 ); + + if( !params[BUMPFRAME]->IsDefined() ) + params[BUMPFRAME]->SetIntValue( 0 ); + + if( !params[ALPHATESTREFERENCE]->IsDefined() ) + params[ALPHATESTREFERENCE]->SetFloatValue( 0.0f ); + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + // If a bumpmap is defined but an envmap isn't, then ignore the bumpmap. + // It was meant to be used with diffuse + if ( !params[ENVMAP]->IsDefined() ) + { + params[BUMPMAP]->SetUndefined(); + } + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + + // Color Replacement Pass + if ( !params[BLENDTINTBYBASEALPHA]->IsDefined() ) + { + params[BLENDTINTBYBASEALPHA]->SetIntValue(0); + } + + if ( !params[BLENDTINTCOLOROVERBASE]->IsDefined() ) + { + params[BLENDTINTCOLOROVERBASE]->SetFloatValue(0); + } + } + + SHADER_FALLBACK + { + if ( IsPC() ) + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 70) + return "VertexLitGeneric_DX6"; + + if ( g_pHardwareConfig->GetDXSupportLevel() < 80) + return "VertexLitGeneric_DX7"; + + if ( g_pHardwareConfig->PreferReducedFillrate() ) + return "VertexLitGeneric_NoBump_DX8"; + } + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + if (g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined()) + { + LoadBumpMap( BUMPMAP ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + LoadCubeMap( ENVMAP ); + } + else + { + LoadTexture( ENVMAP ); + } + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + { + LoadTexture( ENVMAPMASK ); + } + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + } + + inline const char *GetUnbumpedPixelShaderName( IMaterialVar** params, bool bSkipEnvmap ) + { + static char const* s_pPixelShaders[] = + { + "VertexLitGeneric_EnvmapV2", + "VertexLitGeneric_SelfIlluminatedEnvmapV2", + + "VertexLitGeneric_BaseAlphaMaskedEnvmapV2", + "VertexLitGeneric_SelfIlluminatedEnvmapV2", + + // Env map mask + "VertexLitGeneric_MaskedEnvmapV2", + "VertexLitGeneric_SelfIlluminatedMaskedEnvmapV2", + + "VertexLitGeneric_MaskedEnvmapV2", + "VertexLitGeneric_SelfIlluminatedMaskedEnvmapV2", + + // Detail + "VertexLitGeneric_DetailEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedEnvmapV2", + + "VertexLitGeneric_DetailBaseAlphaMaskedEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedEnvmapV2", + + // Env map mask + "VertexLitGeneric_DetailMaskedEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedMaskedEnvmapV2", + + "VertexLitGeneric_DetailMaskedEnvmapV2", + "VertexLitGeneric_DetailSelfIlluminatedMaskedEnvmapV2", + }; + + if ( !params[BASETEXTURE]->IsTexture() ) + { + if (params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + if (!params[ENVMAPMASK]->IsTexture()) + { + return "VertexLitGeneric_EnvmapNoTexture"; + } + else + { + return "VertexLitGeneric_MaskedEnvmapNoTexture"; + } + } + else + { + if ( params[DETAIL]->IsTexture() ) + { + return "VertexLitGeneric_DetailNoTexture"; + } + else + { + return "VertexLitGeneric_NoTexture"; + } + } + } + else + { + if ( params[BLENDTINTBYBASEALPHA]->GetIntValue() ) + { + return "VertexLitGeneric_BlendTint"; + } + else if ( params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + int pshIndex = 0; + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + pshIndex |= 0x1; + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pshIndex |= 0x2; + if (params[ENVMAPMASK]->IsTexture()) + pshIndex |= 0x4; + if (params[DETAIL]->IsTexture()) + pshIndex |= 0x8; + return s_pPixelShaders[pshIndex]; + } + else + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + { + if ( params[DETAIL]->IsTexture() ) + return "VertexLitGeneric_DetailSelfIlluminated"; + else + return "VertexLitGeneric_SelfIlluminated"; + } + else if ( params[DETAIL]->IsTexture() ) + { + switch( params[DETAILBLENDMODE]->GetIntValue() ) + { + case 0: + return "VertexLitGeneric_Detail"; + + case 1: // additive modes + return "VertexLitGeneric_Detail_Additive"; + + case 5: + case 6: + return "VertexLitGeneric_Detail_Additive_selfillum"; + break; + + default: + return "VertexLitGeneric_Detail_LerpBase"; + } + } + else + { + return "VertexLitGeneric"; + } + } + } + } + + void DrawUnbumpedUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bSkipEnvmap ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + if ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + + // FIXME: We could enable this, but we'd never get it working on dx7 or lower + // FIXME: This isn't going to work until we make more vertex shaders that + // pass the vertex color and alpha values through. +#if 0 + if ( IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) || IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ) ) + fmt |= VERTEX_COLOR; +#endif + + if (params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + // envmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // envmapmask on stage 2 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + } + + if (params[BASETEXTURE]->IsTexture()) + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetDefaultBlendingShadowState( ENVMAPMASK, false ); + } + + if ( params[DETAIL]->IsTexture()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // Set up the vertex shader index. + vertexlitgeneric_vs11_Static_Index vshIndex; + vshIndex.SetHALF_LAMBERT( IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) ); + //vshIndex.SetDETAIL( params[DETAIL]->IsTexture() ); + if( params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + vshIndex.SetENVMAP( true ); + vshIndex.SetENVMAPCAMERASPACE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ); + if( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ) + { + vshIndex.SetENVMAPSPHERE( false ); + } + else + { + vshIndex.SetENVMAPSPHERE( IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ) ); + } + } + else + { + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + } + pShaderShadow->SetVertexShader( "vertexlitgeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetUnbumpedPixelShaderName( params, bSkipEnvmap ); + pShaderShadow->SetPixelShader( pshName ); + DefaultFog(); + pShaderShadow->EnableAlphaWrites( true ); + } + DYNAMIC_STATE + { + if (params[BASETEXTURE]->IsTexture()) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + +// if (params[ENVMAP]->IsTexture()) + if (params[ENVMAP]->IsTexture() && !bSkipEnvmap ) + { + BindTexture( SHADER_SAMPLER1, ENVMAP, ENVMAPFRAME ); + + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + if (params[ENVMAPMASK]->IsTexture() ) + BindTexture( SHADER_SAMPLER2, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || + IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + SetEnvMapTintPixelShaderDynamicState( 2, ENVMAPTINT, -1 ); + } + + if ( params[DETAIL]->IsTexture()) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + } + + SetAmbientCubeDynamicStateVertexShader(); + SetModulationPixelShaderDynamicState( 3 ); + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + + if ( params[DETAIL]->IsTexture() && ( ! IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) ) ) + { + float c1[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c1[0] = c1[1] = c1[2] = c1[3] = params[DETAILBLENDFACTOR]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, c1, 1 ); + } + + if ( params[BLENDTINTBYBASEALPHA]->GetIntValue() ) + { + float c1[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c1[0] = c1[1] = c1[2] = c1[3] = params[BLENDTINTCOLOROVERBASE]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 1, c1 ); + } + + vertexlitgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 ); + vshIndex.SetLIGHT_COMBO( pShaderAPI->GetCurrentLightCombo() ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + if( pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA ) ) + { + pShaderAPI->SetPixelShaderIndex( 0 ); + } + else + { + // write 255 to alpha if we aren't told to write depth to dest alpha (We don't ever actually write depth to dest alpha in dx8) + pShaderAPI->SetPixelShaderIndex( 1 ); + float c4[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + pShaderAPI->SetPixelShaderConstant( 4, c4, 1 ); + } + } + Draw(); + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( false/*disabled! no effect*/ && params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + // There is some strangeness in DX8 when trying to skip the main pass, so leave this alone for now + //bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + // FLASHLIGHTFIXME: need to make these the same. + bool hasFlashlight = UsingFlashlight( params ); + bool bBump = g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsTexture(); + + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, false, false, 0, -1, -1 ); + } + else if( bBump ) + { + bool bSkipEnvmap = true; + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bSkipEnvmap ); + + // specular pass + bool bBlendSpecular = true; + if( params[ENVMAP]->IsTexture() ) + { + DrawModelBumpedSpecularLighting( BUMPMAP, BUMPFRAME, ENVMAP, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, BUMPTRANSFORM, bBlendSpecular ); + } + } + else + { + bool bSkipEnvmap = false; + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bSkipEnvmap ); + } + } + else + { + // Skip this pass! + Draw( false ); + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// Version that doesn't do bumpmapping +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( VertexLitGeneric_NoBump_DX8, VertexLitGeneric_DX8, + "Help for VertexLitGeneric_NoBump_DX8" ) + + SHADER_FALLBACK + { + if (g_pConfig->bSoftwareLighting) + return "VertexLitGeneric_DX6"; + + if (!g_pHardwareConfig->SupportsVertexAndPixelShaders()) + return "VertexLitGeneric_DX7"; + + return 0; + } + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + if ( !g_pConfig->UseBumpmapping() ) + return false; + + if ( !params[BUMPMAP]->IsDefined() ) + return false; + + return ( params[FORCEBUMP]->GetIntValue() != 0 ); + } + +END_INHERITED_SHADER + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp new file mode 100644 index 00000000..47105813 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp @@ -0,0 +1,520 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=====================================================================================// + +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "emissive_scroll_blended_pass_helper.h" +#include "cloak_blended_pass_helper.h" +#include "flesh_interior_blended_pass_helper.h" +#include "weapon_sheen_pass_helper.h" + + +BEGIN_VS_SHADER( VertexLitGeneric, "Help for VertexLitGeneric" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( COMPRESS, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "compression wrinklemap" ) + SHADER_PARAM( STRETCH, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "expansion wrinklemap" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "envmap frame number" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPCOMPRESS, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "compression bump map" ) + SHADER_PARAM( BUMPSTRETCH, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "expansion bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( SELFILLUM_ENVMAPMASK_ALPHA, SHADER_PARAM_TYPE_FLOAT,"0.0","defines that self illum value comes from env map mask alpha" ) + SHADER_PARAM( SELFILLUMFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "Self illum fresnel" ) + SHADER_PARAM( SELFILLUMFRESNELMINMAXEXP, SHADER_PARAM_TYPE_VEC4, "0", "Self illum fresnel min, max, exp" ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( FLASHLIGHTNOLAMBERT, SHADER_PARAM_TYPE_BOOL, "0", "Flashlight pass sets N.L=1.0" ) + + // Debugging term for visualizing ambient data on its own + SHADER_PARAM( AMBIENTONLY, SHADER_PARAM_TYPE_INTEGER, "0", "Control drawing of non-ambient light ()" ) + + SHADER_PARAM( PHONGEXPONENT, SHADER_PARAM_TYPE_FLOAT, "5.0", "Phong exponent for local specular lights" ) + SHADER_PARAM( PHONGTINT, SHADER_PARAM_TYPE_VEC3, "5.0", "Phong tint for local specular lights" ) + SHADER_PARAM( PHONGALBEDOTINT, SHADER_PARAM_TYPE_BOOL, "1.0", "Apply tint by albedo (controlled by spec exponent texture" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "1D ramp texture for tinting scalar diffuse term" ) + SHADER_PARAM( PHONGWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "warp the specular term" ) + SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) + SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) + SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) + SHADER_PARAM( BASEMAPALPHAPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "indicates that there is no normal map and that the phong mask is in base alpha" ) + SHADER_PARAM( INVERTPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "invert the phong mask (0=full phong, 1=no phong)" ) + SHADER_PARAM( ENVMAPFRESNEL, SHADER_PARAM_TYPE_FLOAT, "0", "Degree to which Fresnel should be applied to env map" ) + SHADER_PARAM( SELFILLUMMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "If we bind a texture here, it overrides base alpha (if any) for self illum" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + SHADER_PARAM( DETAILTEXTURETRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$detail texcoord transform" ) + + // Rim lighting terms + SHADER_PARAM( RIMLIGHT, SHADER_PARAM_TYPE_BOOL, "0", "enables rim lighting" ) + SHADER_PARAM( RIMLIGHTEXPONENT, SHADER_PARAM_TYPE_FLOAT, "4.0", "Exponent for rim lights" ) + SHADER_PARAM( RIMLIGHTBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Boost for rim lights" ) + SHADER_PARAM( RIMMASK, SHADER_PARAM_TYPE_BOOL, "0", "Indicates whether or not to use alpha channel of exponent texture to mask the rim term" ) + + // Seamless mapping scale + SHADER_PARAM( SEAMLESS_BASE, SHADER_PARAM_TYPE_BOOL, "0", "whether to apply seamless mapping to the base texture. requires a smooth model." ) + SHADER_PARAM( SEAMLESS_DETAIL, SHADER_PARAM_TYPE_BOOL, "0", "where to apply seamless mapping to the detail texture." ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "the scale for the seamless mapping. # of repetions of texture per inch." ) + + // Emissive Scroll Pass + SHADER_PARAM( EMISSIVEBLENDENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable emissive blend pass" ) + SHADER_PARAM( EMISSIVEBLENDBASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDSCROLLVECTOR, SHADER_PARAM_TYPE_VEC2, "[0.11 0.124]", "Emissive scroll vec" ) + SHADER_PARAM( EMISSIVEBLENDSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "1.0", "Emissive blend strength" ) + SHADER_PARAM( EMISSIVEBLENDTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "self-illumination map" ) + SHADER_PARAM( EMISSIVEBLENDTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( EMISSIVEBLENDFLOWTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow map" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + + // Cloak Pass + SHADER_PARAM( CLOAKPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables cloak render in a second pass" ) + SHADER_PARAM( CLOAKFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( CLOAKCOLORTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Cloak color tint" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + + // Weapon Sheen Pass + SHADER_PARAM( SHEENPASSENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enables weapon sheen render in a second pass" ) + SHADER_PARAM( SHEENMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "sheenmap" ) + SHADER_PARAM( SHEENMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "sheenmap mask" ) + SHADER_PARAM( SHEENMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( SHEENMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "sheenmap tint" ) + SHADER_PARAM( SHEENMAPMASKSCALEX, SHADER_PARAM_TYPE_FLOAT, "1", "X Scale the size of the map mask to the size of the target" ) + SHADER_PARAM( SHEENMAPMASKSCALEY, SHADER_PARAM_TYPE_FLOAT, "1", "Y Scale the size of the map mask to the size of the target" ) + SHADER_PARAM( SHEENMAPMASKOFFSETX, SHADER_PARAM_TYPE_FLOAT, "0", "X Offset of the mask relative to model space coords of target" ) + SHADER_PARAM( SHEENMAPMASKOFFSETY, SHADER_PARAM_TYPE_FLOAT, "0", "Y Offset of the mask relative to model space coords of target" ) + SHADER_PARAM( SHEENMAPMASKDIRECTION, SHADER_PARAM_TYPE_INTEGER, "0", "The direction the sheen should move (length direction of weapon) XYZ, 0,1,2" ) + SHADER_PARAM( SHEENINDEX, SHADER_PARAM_TYPE_INTEGER, "0", "Index of the Effect Type (Color Additive, Override etc...)" ) + + // Flesh Interior Pass + SHADER_PARAM( FLESHINTERIORENABLED, SHADER_PARAM_TYPE_BOOL, "0", "Enable Flesh interior blend pass" ) + SHADER_PARAM( FLESHINTERIORTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh color texture" ) + SHADER_PARAM( FLESHINTERIORNOISETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh noise texture" ) + SHADER_PARAM( FLESHBORDERTEXTURE1D, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh border 1D texture" ) + SHADER_PARAM( FLESHNORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh normal texture" ) + SHADER_PARAM( FLESHSUBSURFACETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh subsurface texture" ) + SHADER_PARAM( FLESHCUBETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Flesh cubemap texture" ) + SHADER_PARAM( FLESHBORDERNOISESCALE, SHADER_PARAM_TYPE_FLOAT, "1.5", "Flesh Noise UV scalar for border" ) + SHADER_PARAM( FLESHDEBUGFORCEFLESHON, SHADER_PARAM_TYPE_BOOL, "0", "Flesh Debug full flesh" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHEFFECTCENTERRADIUS4, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0.001]", "Flesh effect center and radius" ) + SHADER_PARAM( FLESHSUBSURFACETINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Subsurface Color" ) + SHADER_PARAM( FLESHBORDERWIDTH, SHADER_PARAM_TYPE_FLOAT, "0.3", "Flesh border" ) + SHADER_PARAM( FLESHBORDERSOFTNESS, SHADER_PARAM_TYPE_FLOAT, "0.42", "Flesh border softness (> 0.0 && <= 0.5)" ) + SHADER_PARAM( FLESHBORDERTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Flesh border Color" ) + SHADER_PARAM( FLESHGLOBALOPACITY, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh global opacity" ) + SHADER_PARAM( FLESHGLOSSBRIGHTNESS, SHADER_PARAM_TYPE_FLOAT, "0.66", "Flesh gloss brightness" ) + SHADER_PARAM( FLESHSCROLLSPEED, SHADER_PARAM_TYPE_FLOAT, "1.0", "Flesh scroll speed" ) + + SHADER_PARAM( SEPARATEDETAILUVS, SHADER_PARAM_TYPE_BOOL, "0", "Use texcoord1 for detail texture" ) + SHADER_PARAM( LINEARWRITE, SHADER_PARAM_TYPE_INTEGER, "0", "Disables SRGB conversion of shader results." ) + SHADER_PARAM( DEPTHBLEND, SHADER_PARAM_TYPE_INTEGER, "0", "fade at intersection boundaries. Only supported without bumpmaps" ) + SHADER_PARAM( DEPTHBLENDSCALE, SHADER_PARAM_TYPE_FLOAT, "50.0", "Amplify or reduce DEPTHBLEND fading. Lower values make harder edges." ) + + SHADER_PARAM( BLENDTINTBYBASEALPHA, SHADER_PARAM_TYPE_BOOL, "0", "Use the base alpha to blend in the $color modulation") + SHADER_PARAM( BLENDTINTCOLOROVERBASE, SHADER_PARAM_TYPE_FLOAT, "0", "blend between tint acting as a multiplication versus a replace" ) + END_SHADER_PARAMS + + void SetupVars( VertexLitGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nWrinkle = COMPRESS; + info.m_nStretch = STRETCH; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nNormalWrinkle = BUMPCOMPRESS; + info.m_nNormalStretch = BUMPSTRETCH; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nAlphaTestReference = ALPHATESTREFERENCE; + info.m_nFlashlightNoLambert = FLASHLIGHTNOLAMBERT; + + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nSelfIllumEnvMapMask_Alpha = SELFILLUM_ENVMAPMASK_ALPHA; + info.m_nSelfIllumFresnel = SELFILLUMFRESNEL; + info.m_nSelfIllumFresnelMinMaxExp = SELFILLUMFRESNELMINMAXEXP; + + info.m_nAmbientOnly = AMBIENTONLY; + info.m_nPhongExponent = PHONGEXPONENT; + info.m_nPhongExponentTexture = PHONGEXPONENTTEXTURE; + info.m_nPhongTint = PHONGTINT; + info.m_nPhongAlbedoTint = PHONGALBEDOTINT; + info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; + info.m_nPhongWarpTexture = PHONGWARPTEXTURE; + info.m_nPhongBoost = PHONGBOOST; + info.m_nPhongFresnelRanges = PHONGFRESNELRANGES; + info.m_nPhong = PHONG; + info.m_nBaseMapAlphaPhongMask = BASEMAPALPHAPHONGMASK; + info.m_nEnvmapFresnel = ENVMAPFRESNEL; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTextureTransform = DETAILTEXTURETRANSFORM; + + // Rim lighting parameters + info.m_nRimLight = RIMLIGHT; + info.m_nRimLightPower = RIMLIGHTEXPONENT; + info.m_nRimLightBoost = RIMLIGHTBOOST; + info.m_nRimMask = RIMMASK; + + // seamless + info.m_nSeamlessScale = SEAMLESS_SCALE; + info.m_nSeamlessDetail = SEAMLESS_DETAIL; + info.m_nSeamlessBase = SEAMLESS_BASE; + + info.m_nSeparateDetailUVs = SEPARATEDETAILUVS; + + info.m_nLinearWrite = LINEARWRITE; + info.m_nDetailTint = DETAILTINT; + info.m_nInvertPhongMask = INVERTPHONGMASK; + + info.m_nDepthBlend = DEPTHBLEND; + info.m_nDepthBlendScale = DEPTHBLENDSCALE; + + info.m_nSelfIllumMask = SELFILLUMMASK; + info.m_nBlendTintByBaseAlpha = BLENDTINTBYBASEALPHA; + info.m_nTintReplacesBaseColor = BLENDTINTCOLOROVERBASE; + } + + // Cloak Pass + void SetupVarsCloakBlendedPass( CloakBlendedPassVars_t &info ) + { + info.m_nCloakFactor = CLOAKFACTOR; + info.m_nCloakColorTint = CLOAKCOLORTINT; + info.m_nRefractAmount = REFRACTAMOUNT; + + // Delete these lines if not bump mapping! + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + // Weapon Sheen Pass + void SetupVarsWeaponSheenPass( WeaponSheenPassVars_t &info ) + { + info.m_nSheenMap = SHEENMAP; + info.m_nSheenMapMask = SHEENMAPMASK; + info.m_nSheenMapMaskFrame = SHEENMAPMASKFRAME; + info.m_nSheenMapTint = SHEENMAPTINT; + info.m_nSheenMapMaskScaleX = SHEENMAPMASKSCALEX; + info.m_nSheenMapMaskScaleY = SHEENMAPMASKSCALEY; + info.m_nSheenMapMaskOffsetX = SHEENMAPMASKOFFSETX; + info.m_nSheenMapMaskOffsetY = SHEENMAPMASKOFFSETY; + info.m_nSheenMapMaskDirection = SHEENMAPMASKDIRECTION; + info.m_nSheenIndex = SHEENINDEX; + + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + } + + bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( bCheckSpecificToThisFrame == false ) // For setting model flag at load time + return true; + else if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag2 in case the base material still needs it + } + if ( params[SHEENPASSENABLED]->GetIntValue() ) // If material supports weapon sheen + return true; + + // Check flag2 if not drawing cloak pass + return IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); + } + + bool IsTranslucent( IMaterialVar **params ) const + { + if ( params[CLOAKPASSENABLED]->GetIntValue() ) // If material supports cloaking + { + if ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) // Per-frame check + return true; + // else, not cloaking this frame, so check flag in case the base material still needs it + } + + // Check flag if not drawing cloak pass + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); + } + + // Emissive Scroll Pass + void SetupVarsEmissiveScrollBlendedPass( EmissiveScrollBlendedPassVars_t &info ) + { + info.m_nBlendStrength = EMISSIVEBLENDSTRENGTH; + info.m_nBaseTexture = EMISSIVEBLENDBASETEXTURE; + info.m_nFlowTexture = EMISSIVEBLENDFLOWTEXTURE; + info.m_nEmissiveTexture = EMISSIVEBLENDTEXTURE; + info.m_nEmissiveTint = EMISSIVEBLENDTINT; + info.m_nEmissiveScrollVector = EMISSIVEBLENDSCROLLVECTOR; + info.m_nTime = TIME; + } + + // Flesh Interior Pass + void SetupVarsFleshInteriorBlendedPass( FleshInteriorBlendedPassVars_t &info ) + { + info.m_nFleshTexture = FLESHINTERIORTEXTURE; + info.m_nFleshNoiseTexture = FLESHINTERIORNOISETEXTURE; + info.m_nFleshBorderTexture1D = FLESHBORDERTEXTURE1D; + info.m_nFleshNormalTexture = FLESHNORMALTEXTURE; + info.m_nFleshSubsurfaceTexture = FLESHSUBSURFACETEXTURE; + info.m_nFleshCubeTexture = FLESHCUBETEXTURE; + + info.m_nflBorderNoiseScale = FLESHBORDERNOISESCALE; + info.m_nflDebugForceFleshOn = FLESHDEBUGFORCEFLESHON; + info.m_nvEffectCenterRadius1 = FLESHEFFECTCENTERRADIUS1; + info.m_nvEffectCenterRadius2 = FLESHEFFECTCENTERRADIUS2; + info.m_nvEffectCenterRadius3 = FLESHEFFECTCENTERRADIUS3; + info.m_nvEffectCenterRadius4 = FLESHEFFECTCENTERRADIUS4; + + info.m_ncSubsurfaceTint = FLESHSUBSURFACETINT; + info.m_nflBorderWidth = FLESHBORDERWIDTH; + info.m_nflBorderSoftness = FLESHBORDERSOFTNESS; + info.m_ncBorderTint = FLESHBORDERTINT; + info.m_nflGlobalOpacity = FLESHGLOBALOPACITY; + info.m_nflGlossBrightness = FLESHGLOSSBRIGHTNESS; + info.m_nflScrollSpeed = FLESHSCROLLSPEED; + + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitParamsVertexLitGeneric_DX9( this, params, pMaterialName, true, vars ); + + // Cloak Pass + if ( !params[CLOAKPASSENABLED]->IsDefined() ) + { + params[CLOAKPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitParamsCloakBlendedPass( this, params, pMaterialName, info ); + } + + // Sheen Pass + if ( !params[SHEENPASSENABLED]->IsDefined() ) + { + params[SHEENPASSENABLED]->SetIntValue( 0 ); + } + else if ( params[SHEENPASSENABLED]->GetIntValue() ) + { + WeaponSheenPassVars_t info; + SetupVarsWeaponSheenPass( info ); + InitParamsWeaponSheenPass( this, params, pMaterialName, info ); + } + + // Emissive Scroll Pass + if ( !params[EMISSIVEBLENDENABLED]->IsDefined() ) + { + params[EMISSIVEBLENDENABLED]->SetIntValue( 0 ); + } + else if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitParamsEmissiveScrollBlendedPass( this, params, pMaterialName, info ); + } + + // Flesh Interior Pass + if ( !params[FLESHINTERIORENABLED]->IsDefined() ) + { + params[FLESHINTERIORENABLED]->SetIntValue( 0 ); + } + else if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitParamsFleshInteriorBlendedPass( this, params, pMaterialName, info ); + } + } + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 70) + return "VertexLitGeneric_DX6"; + + if (g_pHardwareConfig->GetDXSupportLevel() < 80) + return "VertexLitGeneric_DX7"; + + if (g_pHardwareConfig->GetDXSupportLevel() < 90) + return "VertexLitGeneric_DX8"; + + return 0; + } + + SHADER_INIT + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + InitVertexLitGeneric_DX9( this, params, true, vars ); + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + InitCloakBlendedPass( this, params, info ); + } + + // TODO : Only do this if we're in range of the camera + // Weapon Sheen + if ( params[SHEENPASSENABLED]->GetIntValue() ) + { + WeaponSheenPassVars_t info; + SetupVarsWeaponSheenPass( info ); + InitWeaponSheenPass( this, params, info ); + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + InitEmissiveScrollBlendedPass( this, params, info ); + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + InitFleshInteriorBlendedPass( this, params, info ); + } + } + + SHADER_DRAW + { + // Skip the standard rendering if cloak pass is fully opaque + bool bDrawStandardPass = true; + if ( params[CLOAKPASSENABLED]->GetIntValue() && ( pShaderShadow == NULL ) ) // && not snapshotting + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + if ( CloakBlendedPassIsFullyOpaque( params, info ) ) + { + bDrawStandardPass = false; + } + } + + // Standard rendering pass + if ( bDrawStandardPass ) + { + VertexLitGeneric_DX9_Vars_t vars; + SetupVars( vars ); + DrawVertexLitGeneric_DX9( this, params, pShaderAPI, pShaderShadow, true, vars, vertexCompression, pContextDataPtr ); + } + else + { + // Skip this pass! + Draw( false ); + } + + // Weapon sheen pass + // only if doing standard as well (don't do it if cloaked) + if ( params[SHEENPASSENABLED]->GetIntValue() ) + { + WeaponSheenPassVars_t info; + SetupVarsWeaponSheenPass( info ); + if ( ( pShaderShadow != NULL ) || ( bDrawStandardPass && ShouldDrawMaterialSheen( params, info ) ) ) + { + DrawWeaponSheenPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else + { + // Skip this pass! + Draw( false ); + } + } + + // Cloak Pass + if ( params[CLOAKPASSENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( ( params[CLOAKFACTOR]->GetFloatValue() > 0.0f ) && ( params[CLOAKFACTOR]->GetFloatValue() < 1.0f ) ) ) + { + CloakBlendedPassVars_t info; + SetupVarsCloakBlendedPass( info ); + DrawCloakBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Emissive Scroll Pass + if ( params[EMISSIVEBLENDENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( params[EMISSIVEBLENDSTRENGTH]->GetFloatValue() > 0.0f ) ) + { + EmissiveScrollBlendedPassVars_t info; + SetupVarsEmissiveScrollBlendedPass( info ); + DrawEmissiveScrollBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + + // Flesh Interior Pass + if ( params[FLESHINTERIORENABLED]->GetIntValue() ) + { + // If ( snapshotting ) or ( we need to draw this frame ) + if ( ( pShaderShadow != NULL ) || ( true ) ) + { + FleshInteriorBlendedPassVars_t info; + SetupVarsFleshInteriorBlendedPass( info ); + DrawFleshInteriorBlendedPass( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } + else // We're not snapshotting and we don't need to draw this frame + { + // Skip this pass! + Draw( false ); + } + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx95_helper.h b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx95_helper.h new file mode 100644 index 00000000..3736bfe8 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx95_helper.h @@ -0,0 +1,71 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VERTEXLITGENERIC_DX95_HELPER_H +#define VERTEXLITGENERIC_DX95_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VertexLitGeneric_DX95_Vars_t +{ + VertexLitGeneric_DX95_Vars_t() { memset( this, 0xFF, sizeof(VertexLitGeneric_DX95_Vars_t) ); } + + int m_nBaseTexture; + int m_nBaseTextureFrame; + int m_nBaseTexture2; + int m_nBaseTextureFrame2; + int m_nBaseTexture3; + int m_nBaseTextureFrame3; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nSelfIllumTint; + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nBumpFrame; + int m_nBumpmap2; + int m_nBumpFrame2; + int m_nBumpMask; + int m_nBumpmap3; + int m_nBumpFrame3; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nAlphaTestReference; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + int m_nSelfIllumEnvMapMask_Alpha; + +}; + +void InitParamsVertexLitGeneric_DX95( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX95_Vars_t &info ); +void InitVertexLitGeneric_DX95( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX95_Vars_t &info ); +void DrawVertexLitGeneric_DX95( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bVertexLitGeneric, VertexLitGeneric_DX95_Vars_t &info ); + + +#endif // VERTEXLITGENERIC_DX95_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp new file mode 100644 index 00000000..b1f49eab --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp @@ -0,0 +1,1434 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +#include "BaseVSShader.h" +#include "vertexlitgeneric_dx9_helper.h" +#include "skin_dx9_helper.h" + +#include "VertexLit_and_unlit_Generic_vs20.inc" +#include "VertexLit_and_unlit_Generic_bump_vs20.inc" + +#include "vertexlit_and_unlit_generic_ps20.inc" +#include "vertexlit_and_unlit_generic_ps20b.inc" +#include "vertexlit_and_unlit_generic_bump_ps20.inc" +#include "vertexlit_and_unlit_generic_bump_ps20b.inc" + +#ifndef _X360 +#include "vertexlit_and_unlit_generic_vs30.inc" +#include "vertexlit_and_unlit_generic_ps30.inc" +#include "vertexlit_and_unlit_generic_bump_vs30.inc" +#include "vertexlit_and_unlit_generic_bump_ps30.inc" +#endif + +#include "commandbuilder.h" +#include "convar.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); +static ConVar r_lightwarpidentity( "r_lightwarpidentity","0", FCVAR_CHEAT ); + + +static inline bool WantsSkinShader( IMaterialVar** params, const VertexLitGeneric_DX9_Vars_t &info ) +{ + if ( info.m_nPhong == -1) // Don't use skin without Phong + return false; + + if ( params[info.m_nPhong]->GetIntValue() == 0 ) // Don't use skin without Phong turned on + return false; + + if ( ( info.m_nDiffuseWarpTexture != -1 ) && params[info.m_nDiffuseWarpTexture]->IsTexture() ) // If there's Phong and diffuse warp do skin + return true; + + if ( ( info.m_nBaseMapAlphaPhongMask != -1 ) && params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 1 ) + { + if ( info.m_nBumpmap == -1 ) // Don't use without a bump map + return false; + + if ( !params[info.m_nBumpmap]->IsTexture() ) // Don't use if the texture isn't specified + return false; + } + + return true; +} + +int g_nSnapShots; + +//----------------------------------------------------------------------------- +// Initialize shader parameters +//----------------------------------------------------------------------------- +void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ) +{ + InitIntParam( info.m_nPhong, params, 0 ); + + InitFloatParam( info.m_nAlphaTestReference, params, 0.0f ); + InitIntParam( info.m_nVertexAlphaTest, params, 0 ); + + InitIntParam( info.m_nFlashlightNoLambert, params, 0 ); + + if ( info.m_nDetailTint != -1 && !params[info.m_nDetailTint]->IsDefined() ) + { + params[info.m_nDetailTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if ( info.m_nEnvmapTint != -1 && !params[info.m_nEnvmapTint]->IsDefined() ) + { + params[info.m_nEnvmapTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + InitIntParam( info.m_nEnvmapFrame, params, 0 ); + InitIntParam( info.m_nBumpFrame, params, 0 ); + InitFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + InitIntParam( info.m_nReceiveFlashlight, params, 0 ); + + InitFloatParam( info.m_nDetailScale, params, 4.0f ); + + if ( (info.m_nBlendTintByBaseAlpha != -1) && (!params[info.m_nBlendTintByBaseAlpha]->IsDefined()) ) + { + params[info.m_nBlendTintByBaseAlpha]->SetIntValue( 0 ); + } + + InitFloatParam( info.m_nTintReplacesBaseColor, params, 0 ); + + if ( (info.m_nSelfIllumTint != -1) && (!params[info.m_nSelfIllumTint]->IsDefined()) ) + { + params[info.m_nSelfIllumTint]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + + if ( WantsSkinShader( params, info ) ) + { + if ( !g_pHardwareConfig->SupportsPixelShaders_2_b() || !g_pConfig->UsePhong() ) + { + params[info.m_nPhong]->SetIntValue( 0 ); + } + else + { + InitParamsSkin_DX9( pShader, params, pMaterialName, info ); + return; + } + } + + // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture + if ( info.m_nFlashlightTexture != -1 ) + { + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + } + + // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping. + if ( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() && + params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() ); + } + + // This shader can be used with hw skinning + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + + if ( bVertexLitGeneric ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT ); + } + else + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + InitIntParam( info.m_nEnvmapMaskFrame, params, 0 ); + InitFloatParam( info.m_nEnvmapContrast, params, 0.0 ); + InitFloatParam( info.m_nEnvmapSaturation, params, 1.0f ); + InitFloatParam( info.m_nSeamlessScale, params, 0.0 ); + + // handle line art parms + InitFloatParam( info.m_nEdgeSoftnessStart, params, 0.5 ); + InitFloatParam( info.m_nEdgeSoftnessEnd, params, 0.5 ); + InitFloatParam( info.m_nGlowAlpha, params, 1.0 ); + InitFloatParam( info.m_nOutlineAlpha, params, 1.0 ); + + // No texture means no self-illum or env mask in base alpha + if ( info.m_nBaseTexture != -1 && !params[info.m_nBaseTexture]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + if( ( (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) + // we don't need a tangent space if we have envmap without bumpmap + // || ( info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() ) + ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) // diffuse warp goes down bump path... + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + else // no tangent space needed + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + } + + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + if ( hasNormalMapAlphaEnvmapMask ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ) && info.m_nBumpmap != -1 && + params[info.m_nBumpmap]->IsDefined() && !hasNormalMapAlphaEnvmapMask ) + { + Warning( "material %s has a normal map and $basealphaenvmapmask. Must use $normalmapalphaenvmapmask to get specular.\n\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() ) + { + params[info.m_nEnvmapMask]->SetUndefined(); + if ( !hasNormalMapAlphaEnvmapMask ) + { + Warning( "material %s has a normal map and an envmapmask. Must use $normalmapalphaenvmapmask.\n\n", pMaterialName ); + params[info.m_nEnvmap]->SetUndefined(); + } + } + + // If mat_specular 0, then get rid of envmap + if ( !g_pConfig->UseSpecular() && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() && params[info.m_nBaseTexture]->IsDefined() ) + { + params[info.m_nEnvmap]->SetUndefined(); + } + + InitFloatParam( info.m_nHDRColorScale, params, 1.0f ); + + InitIntParam( info.m_nLinearWrite, params, 0 ); + InitIntParam( info.m_nGammaColorRead, params, 0 ); + + InitIntParam( info.m_nDepthBlend, params, 0 ); + InitFloatParam( info.m_nDepthBlendScale, params, 50.0f ); +} + + +//----------------------------------------------------------------------------- +// Initialize shader +//----------------------------------------------------------------------------- + +void InitVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ) +{ + // both detailed and bumped = needs skin shader (for now) + bool bNeedsSkinBecauseOfDetail = false; + + //bool bHasBump = ( info.m_nBumpmap != -1 ) && params[info.m_nBumpmap]->IsTexture(); + //if ( bHasBump ) + //{ + // if ( ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsDefined() ) + // bNeedsSkinBecauseOfDetail = true; + //} + + if ( bNeedsSkinBecauseOfDetail || + ( info.m_nPhong != -1 && + params[info.m_nPhong]->GetIntValue() && + g_pHardwareConfig->SupportsPixelShaders_2_b() ) ) + { + InitSkin_DX9( pShader, params, info ); + return; + } + + if ( info.m_nFlashlightTexture != -1 ) + { + pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB ); + } + + bool bIsBaseTextureTranslucent = false; + if ( info.m_nBaseTexture != -1 && params[info.m_nBaseTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture, ( info.m_nGammaColorRead != -1 ) && ( params[info.m_nGammaColorRead]->GetIntValue() == 1 ) ? 0 : TEXTUREFLAGS_SRGB ); + + if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) + { + bIsBaseTextureTranslucent = true; + } + } + + bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsDefined(); + + // No alpha channel in any of the textures? No self illum or envmapmask + if ( !bIsBaseTextureTranslucent ) + { + bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + // Can still be self illum with no base alpha if using one of these alternate modes + if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + } + + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() ) + { + int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue(); + if ( nDetailBlendMode == 0 ) //Mod2X + pShader->LoadTexture( info.m_nDetail ); + else + pShader->LoadTexture( info.m_nDetail, TEXTUREFLAGS_SRGB ); + } + + if ( g_pConfig->UseBumpmapping() ) + { + if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() ) + { + pShader->LoadBumpMap( info.m_nBumpmap ); + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + else if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ); + } + } + + // Don't alpha test if the alpha channel is used for other purposes + if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + if ( info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsDefined() ) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + else + { + pShader->LoadTexture( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + + if ( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + } + if ( info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsDefined() ) + { + pShader->LoadTexture( info.m_nEnvmapMask ); + } + + if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() ) + { + pShader->LoadTexture( info.m_nDiffuseWarpTexture ); + } + + if ( bHasSelfIllumMask ) + { + pShader->LoadTexture( info.m_nSelfIllumMask ); + } +} + +class CVertexLitGeneric_DX9_Context : public CBasePerMaterialContextData +{ +public: + CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut; + +}; + + +//----------------------------------------------------------------------------- +// Draws the shader +//----------------------------------------------------------------------------- +static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, + bool bVertexLitGeneric, bool bHasFlashlight, + VertexLitGeneric_DX9_Vars_t &info, + VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr ) + +{ + CVertexLitGeneric_DX9_Context *pContextData = reinterpret_cast< CVertexLitGeneric_DX9_Context *> ( *pContextDataPtr ); + +/*^*/ // printf("\t\t>DrawVertexLitGeneric_DX9_Internal\n"); + + bool bHasBump = IsTextureSet( info.m_nBumpmap, params ); +#if !defined( _X360 ) + bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); +#endif + + bool hasDiffuseLighting = bVertexLitGeneric; +/*^*/ // printf("\t\t[%d] bVertexLitGeneric\n",(int)bVertexLitGeneric); + + if ( IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + bHasFlashlight = false; + } + + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + bool bHasDiffuseWarp = (!bHasFlashlight || IsX360() ) && hasDiffuseLighting && (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture(); + + + //bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL ); + bool bFlashlightNoLambert = false; + if ( ( info.m_nFlashlightNoLambert != -1 ) && params[info.m_nFlashlightNoLambert]->GetIntValue() ) + { + bFlashlightNoLambert = true; + } + + bool bAmbientOnly = IsBoolSet( info.m_nAmbientOnly, params ); + + float fBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 ); + bool bHasDetailTexture = IsTextureSet( info.m_nDetail, params ); + int nDetailBlendMode = bHasDetailTexture ? GetIntParam( info.m_nDetailTextureCombineMode, params ) : 0; + int nDetailTranslucencyTexture = -1; + + if ( bHasDetailTexture ) + { + if ( ( nDetailBlendMode == 6 ) && ( ! (g_pHardwareConfig->SupportsPixelShaders_2_b() ) ) ) + { + nDetailBlendMode = 5; // skip fancy threshold blending if ps2.0 + } + if ( ( nDetailBlendMode == 3 ) || ( nDetailBlendMode == 8 ) || ( nDetailBlendMode == 9 ) ) + nDetailTranslucencyTexture = info.m_nDetail; + } + + bool bBlendTintByBaseAlpha = IsBoolSet( info.m_nBlendTintByBaseAlpha, params ); + float fTintReplaceFactor = GetFloatParam( info.m_nTintReplacesBaseColor, params, 0.0 ); + + BlendType_t nBlendType; + bool bHasBaseTexture = IsTextureSet( info.m_nBaseTexture, params ); + if ( bHasBaseTexture ) + { + // if base alpha is used for tinting, ignore the base texture for computing translucency + nBlendType = pShader->EvaluateBlendRequirements( bBlendTintByBaseAlpha ? -1 : info.m_nBaseTexture, true, nDetailTranslucencyTexture ); + } + else + { + nBlendType = pShader->EvaluateBlendRequirements( info.m_nEnvmapMask, false ); + } + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && (!bHasFlashlight || IsX360() ); //dest alpha is free for special use + + bool bHasEnvmap = (!bHasFlashlight || IsX360() ) && info.m_nEnvmap != -1 && params[info.m_nEnvmap]->IsTexture(); + + + bool bHasVertexColor = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool bHasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); +/*^*/ // printf("\t\t[%d] bHasVertexColor\n",(int)bHasVertexColor); +/*^*/ // printf("\t\t[%d] bHasVertexAlpha\n",(int)bHasVertexAlpha); + + if ( pShader->IsSnapshotting() || (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) + { +/*^*/ // printf("\t\t[1] snapshotting=%d pContextData=%08x pContextData->m_bMaterialVarsChanged=%d \n",(int)pShader->IsSnapshotting(), (int)pContextData, pContextData ? (int)pContextData->m_bMaterialVarsChanged : -1 ); + bool bSeamlessBase = IsBoolSet( info.m_nSeamlessBase, params ); + bool bSeamlessDetail = IsBoolSet( info.m_nSeamlessDetail, params ); + bool bDistanceAlpha = IsBoolSet( info.m_nDistanceAlpha, params ); + bool bHasSelfIllum = (!bHasFlashlight || IsX360() ) && IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + bool bHasEnvmapMask = (!bHasFlashlight || IsX360() ) && info.m_nEnvmapMask != -1 && params[info.m_nEnvmapMask]->IsTexture(); + bool bHasSelfIllumFresnel = ( !IsTextureSet( info.m_nDetail, params ) ) && ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 ); + + bool bHasSelfIllumMask = bHasSelfIllum && IsTextureSet( info.m_nSelfIllumMask, params ); + bool hasSelfIllumInEnvMapMask = + ( info.m_nSelfIllumEnvMapMask_Alpha != -1 ) && + ( params[info.m_nSelfIllumEnvMapMask_Alpha]->GetFloatValue() != 0.0 ) ; + + if ( pShader->IsSnapshotting() ) + { +/*^*/ // printf("\t\t[2] snapshotting...\n"); + + bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + + + if ( info.m_nVertexAlphaTest != -1 && params[info.m_nVertexAlphaTest]->GetIntValue() > 0 ) + { + bHasVertexAlpha = true; + } + + // look at color and alphamod stuff. + // Unlit generic never uses the flashlight + if ( bHasSelfIllumFresnel ) + { + CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ); + hasNormalMapAlphaEnvmapMask = false; + } + + bool bHasEnvmap = (!bHasFlashlight || IsX360() ) && ( info.m_nEnvmap != -1 ) && params[info.m_nEnvmap]->IsTexture(); + bool bHasLegacyEnvSphereMap = bHasEnvmap && IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE); + bool bHasNormal = bVertexLitGeneric || bHasEnvmap || bHasFlashlight || bSeamlessBase || bSeamlessDetail; + if ( IsPC() ) + { + // On PC, LIGHTING_PREVIEW requires normals (they won't use much memory - unlitgeneric isn't used on many models) + bHasNormal = true; + } + + bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ); + // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + + if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() ); + } + + int nShadowFilterMode = 0; + if ( bHasFlashlight ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + if ( !IsX360() ) + { + if (params[info.m_nBaseTexture]->IsTexture()) + { + pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true ); + } + else + { + pShader->SetAdditiveBlendingShadowState( info.m_nEnvmapMask, false ); + } + + if ( bIsAlphaTested ) + { + // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to + // be the same on both the regular pass and the flashlight pass. + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->EnableBlending( true ); + pShaderShadow->EnableDepthWrites( false ); + } + else + { + pShader->SetBlendingShadowState( nBlendType ); + } + } + else + { + pShader->SetBlendingShadowState( nBlendType ); + } + + unsigned int flags = VERTEX_POSITION; + if ( bHasNormal ) + { + flags |= VERTEX_NORMAL; + } +/*^*/ // printf("\t\t[%1d] VERTEX_NORMAL\n",(flags&VERTEX_NORMAL)!=0); + + int userDataSize = 0; + bool bSRGBInputAdapter = false; + + // basetexture + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + if ( bHasBaseTexture ) + { + if ( ( info.m_nGammaColorRead != -1 ) && ( params[info.m_nGammaColorRead]->GetIntValue() == 1 ) ) + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false ); + else + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + // If we're on OSX GL on a crappy OS which can't do sRGB from render targets, check to see if we're reading from one... + if ( IsOSX() && !g_pHardwareConfig->CanDoSRGBReadFromRTs() ) + { + ITexture *pBaseTexture = params[info.m_nBaseTexture]->GetTextureValue(); + if ( pBaseTexture && pBaseTexture->IsRenderTarget() ) + { + bSRGBInputAdapter = true; + } + } + } + + if ( bHasEnvmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + } + } + if ( bHasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); // Depth texture + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER8 ); + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Noise map + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Flashlight cookie + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true ); + userDataSize = 4; // tangent S + } + + if ( bHasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + if ( nDetailBlendMode != 0 ) //Not Mod2X + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + } + + if ( bHasBump || bHasDiffuseWarp ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + userDataSize = 4; // tangent S + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + } + if ( bHasEnvmapMask ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + + if ( bHasVertexColor || bHasVertexAlpha ) + { + flags |= VERTEX_COLOR; + } +/*^*/ // printf("\t\t[%1d] VERTEX_COLOR\n",(flags&VERTEX_COLOR)!=0); +/*^*/ // printf("\t\t[%1d] VERTEX_COLOR_STREAM_1\n",(flags&VERTEX_COLOR_STREAM_1)!=0); + + + if( bHasDiffuseWarp && (!bHasFlashlight || IsX360() ) && !bHasSelfIllumFresnel ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); // Diffuse warp texture + } + + if ( (info.m_nDepthBlend != -1) && (params[info.m_nDepthBlend]->GetIntValue()) ) + { + if( bHasBump ) + Warning( "DEPTHBLEND not supported by bump mapped variations of vertexlitgeneric to avoid shader bloat. Either remove the bump map or convince a graphics programmer that it's worth it.\n" ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); + } + + if( bHasSelfIllum ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER11, true ); // self illum mask + } + + bool bSRGBWrite = true; + if( (info.m_nLinearWrite != -1) && (params[info.m_nLinearWrite]->GetIntValue() == 1) ) + { + bSRGBWrite = false; + } + + pShaderShadow->EnableSRGBWrite( bSRGBWrite ); + + // texcoord0 : base texcoord + int pTexCoordDim[3] = { 2, 2, 3 }; + int nTexCoordCount = 1; + + if ( IsBoolSet( info.m_nSeparateDetailUVs, params ) ) + { + ++nTexCoordCount; + } + else + { + pTexCoordDim[1] = 0; + } + +#ifndef _X360 + // Special morphed decal information + if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() ) + { + nTexCoordCount = 3; + } +#endif + + // This shader supports compressed vertices, so OR in that flag: + flags |= VERTEX_FORMAT_COMPRESSED; +/*^*/ // printf("\t\t[%1d] VERTEX_FORMAT_COMPRESSED\n",(flags&VERTEX_FORMAT_COMPRESSED)!=0); + +/*^*/ // printf("\t\t -> CShaderShadowDX8::VertexShaderVertexFormat( flags=%08x, texcount=%d )\n",flags,nTexCoordCount); + + + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize ); + + if ( bHasBump || bHasDiffuseWarp ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER_COMBO( USE_WITH_2B, g_pHardwareConfig->SupportsPixelShaders_2_b() ); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); +#endif + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL this way + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + } + else // ps_2_0 + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_VERTEX_SHADER_COMBO( USE_WITH_2B, true ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && !bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, bHasSelfIllumFresnel ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK, hasNormalMapAlphaEnvmapMask && bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT, bHalfLambert); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + } +#endif + } + else // !(bHasBump || bHasDiffuseWarp) + { + bool bDistanceAlphaFromDetail = false; + bool bSoftMask = false; + bool bGlow = false; + bool bOutline = false; + + static ConVarRef mat_reduceparticles( "mat_reduceparticles" ); + bool bDoDepthBlend = IsBoolSet( info.m_nDepthBlend, params ) && !mat_reduceparticles.GetBool(); + + if ( bDistanceAlpha ) + { + bDistanceAlphaFromDetail = IsBoolSet( info.m_nDistanceAlphaFromDetail, params ); + bSoftMask = IsBoolSet( info.m_nSoftEdges, params ); + bGlow = IsBoolSet( info.m_nGlow, params ); + bOutline = IsBoolSet( info.m_nOutline, params ); + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_VERTEX_SHADER_COMBO( SEPARATE_DETAIL_UVS, IsBoolSet( info.m_nSeparateDetailUVs, params ) ); + SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow ); + SET_STATIC_VERTEX_SHADER_COMBO( DONT_GAMMA_CONVERT_VERTEX_COLOR, (! bSRGBWrite ) && bHasVertexColor ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send Gl this way + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, ( hasSelfIllumInEnvMapMask && ( bHasEnvmapMask ) ) ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP_SPHERE_LEGACY, bHasLegacyEnvSphereMap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDoDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( SRGB_INPUT_ADAPTER, bSRGBInputAdapter ? 1 : 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + } + else // ps_2_0 + { + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, ( hasSelfIllumInEnvMapMask && ( bHasEnvmapMask ) ) ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP_SPHERE_LEGACY, bHasLegacyEnvSphereMap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + } + } +#ifndef _X360 + else + { + // The vertex shader uses the vertex id stream + SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID ); + + DECLARE_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor || bHasVertexAlpha ); + SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, bHalfLambert ); + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_VERTEX_SHADER_COMBO( SEPARATE_DETAIL_UVS, IsBoolSet( info.m_nSeparateDetailUVs, params ) ); + SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal ); + SET_STATIC_VERTEX_SHADER_COMBO( DONT_GAMMA_CONVERT_VERTEX_COLOR, bSRGBWrite ? 0 : 1 ); + SET_STATIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, ( hasSelfIllumInEnvMapMask && ( bHasEnvmapMask ) ) ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); + SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP_SPHERE_LEGACY, bHasLegacyEnvSphereMap ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING, hasDiffuseLighting ); + SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bHasEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK, hasBaseAlphaEnvmapMask ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bHasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, bHasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bHasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_BASE, bSeamlessBase ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS_DETAIL, bSeamlessDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHA, bDistanceAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( DISTANCEALPHAFROMDETAIL, bDistanceAlphaFromDetail ); + SET_STATIC_PIXEL_SHADER_COMBO( SOFT_MASK, bSoftMask ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bOutline ); + SET_STATIC_PIXEL_SHADER_COMBO( OUTER_GLOW, bGlow ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER_COMBO( DEPTHBLEND, bDoDepthBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha ); + SET_STATIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); + } +#endif + } + + if ( bHasFlashlight && !IsX360() ) + { + pShader->FogToBlack(); + } + else + { + pShader->DefaultFog(); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff and the loadout and character select screens. + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + } + + if ( pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) ) + { +/*^*/ // printf("\t\t[3] pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) TRUE \n"); + if ( ! pContextData ) // make sure allocated + { + ++g_nSnapShots; + pContextData = new CVertexLitGeneric_DX9_Context; + *pContextDataPtr = pContextData; + } + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderFogParams( 21 ); + if ( bHasBaseTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame ); + } + else + { + if( bHasEnvmap ) + { + // if we only have an envmap (no basetexture), then we want the albedo to be black. + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + } + if ( bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nDetail, info.m_nDetailFrame ); + } + if ( bHasSelfIllum ) + { + if ( bHasSelfIllumMask ) // Separate texture for self illum? + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nSelfIllumMask, -1 ); // Bind it + } + else // else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER11, TEXTURE_BLACK ); // Bind dummy + } + } + + if ( (info.m_nDepthBlend != -1) && (params[info.m_nDepthBlend]->GetIntValue()) ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_FRAME_BUFFER_FULL_DEPTH ); + } + if ( bSeamlessDetail || bSeamlessBase ) + { + float flSeamlessData[4]={ params[info.m_nSeamlessScale]->GetFloatValue(), + 0,0,0}; + pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, flSeamlessData ); + } + + if ( info.m_nBaseTextureTransform != -1 ) + { + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); + } + + + if ( bHasDetailTexture ) + { + if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) ) + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nDetailTextureTransform, info.m_nDetailScale ); + else + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBaseTextureTransform, info.m_nDetailScale ); + //Assert( !bHasBump ); + if ( info.m_nDetailTint != -1 ) + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstantGammaToLinear( 10, info.m_nDetailTint ); + else + { + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 10, 1, 1, 1, 1 ); + } + } + if ( bDistanceAlpha ) + { + float flSoftStart = GetFloatParam( info.m_nEdgeSoftnessStart, params ); + float flSoftEnd = GetFloatParam( info.m_nEdgeSoftnessEnd, params ); + // set all line art shader parms + bool bScaleEdges = IsBoolSet( info.m_nScaleEdgeSoftnessBasedOnScreenRes, params ); + bool bScaleOutline = IsBoolSet( info.m_nScaleOutlineSoftnessBasedOnScreenRes, params ); + + float flResScale = 1.0; + + float flOutlineStart0 = GetFloatParam( info.m_nOutlineStart0, params ); + float flOutlineStart1 = GetFloatParam( info.m_nOutlineStart1, params ); + float flOutlineEnd0 = GetFloatParam( info.m_nOutlineEnd0, params ); + float flOutlineEnd1 = GetFloatParam( info.m_nOutlineEnd1, params ); + + if ( bScaleEdges || bScaleOutline ) + { + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + flResScale=max( 0.5, max( 1024.0/nWidth, 768/nHeight ) ); + + if ( bScaleEdges ) + { + float flMid = 0.5 * ( flSoftStart + flSoftEnd ); + flSoftStart = clamp( flMid + flResScale * ( flSoftStart - flMid ), 0.05, 0.99 ); + flSoftEnd = clamp( flMid + flResScale * ( flSoftEnd - flMid ), 0.05, 0.99 ); + } + + + if ( bScaleOutline ) + { + // shrink the soft part of the outline, enlarging hard part + float flMidS = 0.5 * ( flOutlineStart1 + flOutlineStart0 ); + flOutlineStart1 = clamp( flMidS + flResScale * ( flOutlineStart1 - flMidS ), 0.05, 0.99 ); + float flMidE = 0.5 * ( flOutlineEnd1 + flOutlineEnd0 ); + flOutlineEnd1 = clamp( flMidE + flResScale * ( flOutlineEnd1 - flMidE ), 0.05, 0.99 ); + } + + } + + float flConsts[]={ + // c5 - glow values + GetFloatParam( info.m_nGlowX, params ), + GetFloatParam( info.m_nGlowY, params ), + GetFloatParam( info.m_nGlowStart, params ), + GetFloatParam( info.m_nGlowEnd, params ), + // c6 - glow color + 0,0,0, // will be filled in + GetFloatParam( info.m_nGlowAlpha, params ), + // c7 - mask range parms + flSoftStart, + flSoftEnd, + 0,0, + // c8 - outline color + 0,0,0, + GetFloatParam( info.m_nOutlineAlpha, params ), + // c9 - outline parms. ordered for optimal ps20 .wzyx swizzling + flOutlineStart0, + flOutlineEnd1, + flOutlineEnd0, + flOutlineStart1, + }; + + if ( info.m_nGlowColor != -1 ) + { + params[info.m_nGlowColor]->GetVecValue( flConsts+4, 3 ); + } + if ( info.m_nOutlineColor != -1 ) + { + params[info.m_nOutlineColor]->GetVecValue( flConsts+12, 3 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 5, flConsts, 5 ); + + } + if ( !g_pConfig->m_bFastNoBump ) + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame ); + } + else if ( bHasDiffuseWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + else + { + if ( bHasBump ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT ); + } + } + // Setting w to 1 means use separate selfillummask + float vEnvMapSaturation_SelfIllumMask[4] = {1.0f, 1.0f, 1.0f, 0.0f}; + if ( info.m_nEnvmapSaturation != -1 ) + params[info.m_nEnvmapSaturation]->GetVecValue( vEnvMapSaturation_SelfIllumMask, 3 ); + + vEnvMapSaturation_SelfIllumMask[3] = bHasSelfIllumMask ? 1.0f : 0.0f; + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 3, vEnvMapSaturation_SelfIllumMask, 1 ); + if ( bHasEnvmap ) + { + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicStateGammaToLinear( 0, info.m_nEnvmapTint, fTintReplaceFactor ); + } + else + { + pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicStateGammaToLinear( 0, -1, fTintReplaceFactor); + } + + if ( bHasEnvmapMask ) + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame ); + } + + if ( bHasSelfIllumFresnel && (!bHasFlashlight || IsX360() ) ) + { + float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f; + float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f; + float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f; + + vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias + vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale + vConstScaleBiasExp[2] = flExp; // Exp + vConstScaleBiasExp[3] = flMax; // Brightness + + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 11, vConstScaleBiasExp ); + } + + if( bHasDiffuseWarp && (!bHasFlashlight || IsX360() ) && !bHasSelfIllumFresnel ) + { + if ( r_lightwarpidentity.GetBool() ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_IDENTITY_LIGHTWARP ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, info.m_nDiffuseWarpTexture, -1 ); + } + } + + if ( bHasFlashlight ) + { + // Tweaks associated with a given flashlight + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + float tweaks[4]; + tweaks[0] = flashlightState.m_flShadowFilterSize / flashlightState.m_flShadowMapResolution; + tweaks[1] = ShadowAttenFromState( flashlightState ); + pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] ); + pShaderAPI->SetPixelShaderConstant( 2, tweaks, 1 ); + + // Dimensions of screen, used for screen-space noise map sampling + float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0}; + int nWidth, nHeight; + pShaderAPI->GetBackBufferDimensions( nWidth, nHeight ); + vScreenScale[0] = (float) nWidth / 32.0f; + vScreenScale[1] = (float) nHeight / 32.0f; + pShaderAPI->SetPixelShaderConstant( 31, vScreenScale, 1 ); + } + + if ( ( !bHasFlashlight || IsX360() ) && ( info.m_nEnvmapContrast != -1 ) ) + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); + + // mat_fullbright 2 handling + bool bLightingOnly = bVertexLitGeneric && mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + if( bLightingOnly ) + { + if ( bHasBaseTexture ) + { + if( ( bHasSelfIllum && !hasSelfIllumInEnvMapMask ) ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO ); + } + else + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + } + } + if ( bHasDetailTexture ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + } + + if ( bHasBump || bHasDiffuseWarp ) + { + pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + pContextData->m_SemiStaticCmdsOut.SetPixelShaderStateAmbientLightCube( 5 ); + pContextData->m_SemiStaticCmdsOut.CommitPixelShaderLighting( 13 ); + } + pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( 4, info.m_nSelfIllumTint, fBlendFactor ); + pContextData->m_SemiStaticCmdsOut.SetAmbientCubeDynamicStateVertexShader(); + pContextData->m_SemiStaticCmdsOut.End(); + } + } + if ( pShaderAPI ) + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + if ( bHasEnvmap ) + { + DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nEnvmap, info.m_nEnvmapFrame ); + } + + bool bFlashlightShadows = false; + if ( bHasFlashlight ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows ) + { + pShader->BindTexture( SHADER_SAMPLER8, pFlashlightDepthTexture, 0 ); + DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER6, TEXTURE_SHADOW_NOISE_2D ); + } + + SetFlashLightColorFromState( state, pShaderAPI, 28, bFlashlightNoLambert ); + + Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 ); + pShader->BindTexture( SHADER_SAMPLER7, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + } + + + // Set up light combo state + LightState_t lightState = {0, false, false}; + if ( bVertexLitGeneric && (!bHasFlashlight || IsX360() ) ) + { + pShaderAPI->GetDX9LightState( &lightState ); + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; + int numBones = pShaderAPI->GetCurrentNumBones(); + + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + if ( bHasBump || bHasDiffuseWarp ) + { +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_vs20 ); + + // Bind ps_2_b shader so we can get shadow mapping... + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL this way + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_bump_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_bump_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_bump_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + else // !( bHasBump || bHasDiffuseWarp ) + { + if ( bAmbientOnly ) // Override selected light combo to be ambient only + { + lightState.m_bAmbientLight = true; + lightState.m_bStaticLight = false; + lightState.m_nNumLights = 0; + } + +#ifndef _X360 + if ( !g_pHardwareConfig->HasFastVertexTextures() ) +#endif + { + bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow(); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( + LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_vs20 ); + + // Bind ps_2_b shader so we can get shadow mapping + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL this way + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20b ); + +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( + LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( + LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps20 ); + } + } +#ifndef _X360 + else + { + pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( vertexlit_and_unlit_generic_vs30 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vertexlit_and_unlit_generic_ps30 ); +// SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, + pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) ); + SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, vertexlit_and_unlit_generic_ps30 ); + + bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; + pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); + } +#endif + } + + if ( ( info.m_nHDRColorScale != -1 ) && pShader->IsHDREnabled() ) + { + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() ); + } + else + { + pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 ); + } + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + DynamicCmdsOut.SetPixelShaderConstant( 20, eyePos ); + + // Non-bump case does its own depth feathering work + if ( !bHasBump && !bHasDiffuseWarp ) + { + DynamicCmdsOut.SetDepthFeatheringPixelShaderConstant( 13, GetFloatParam( info.m_nDepthBlendScale, params, 50.0f ) ); + } + + float fPixelFogType = pShaderAPI->GetPixelFogCombo() == 1 ? 1 : 0; + float fWriteDepthToAlpha = bWriteDepthToAlpha && IsPC() ? 1 : 0; + float fWriteWaterFogToDestAlpha = (pShaderAPI->GetPixelFogCombo() == 1 && bWriteWaterFogToAlpha) ? 1 : 0; + float fVertexAlpha = bHasVertexAlpha ? 1 : 0; + + // Controls for lerp-style paths through shader code (bump and non-bump have use different register) + float vShaderControls[4] = { fPixelFogType, fWriteDepthToAlpha, fWriteWaterFogToDestAlpha, fVertexAlpha }; + DynamicCmdsOut.SetPixelShaderConstant( 12, vShaderControls, 1 ); + + // flashlightfixme: put this in common code. + if ( bHasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + SetFlashLightColorFromState( flashlightState, pShaderAPI, 28, bFlashlightNoLambert ); + + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 ); + + pShader->BindTexture( SHADER_SAMPLER7, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame ); + + float atten_pos[8]; + atten_pos[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors + atten_pos[1] = flashlightState.m_fLinearAtten; + atten_pos[2] = flashlightState.m_fQuadraticAtten; + atten_pos[3] = flashlightState.m_FarZ; + atten_pos[4] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin + atten_pos[5] = flashlightState.m_vecLightOrigin[1]; + atten_pos[6] = flashlightState.m_vecLightOrigin[2]; + atten_pos[7] = 1.0f; + DynamicCmdsOut.SetPixelShaderConstant( 22, atten_pos, 2 ); + + DynamicCmdsOut.SetPixelShaderConstant( 24, worldToTexture.Base(), 4 ); + } + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + pShader->Draw(); + +/*^*/ // printf("\t\tSupportsPixelShaders_2_b() && g_pConfig->UseBumpmapping() && g_pConfig->UsePhong() ) + { + DrawSkin_DX9( pShader, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr ); + return; + } + + bool bReceiveFlashlight = bVertexLitGeneric; + bool bNewFlashlight = IsX360(); + if ( bNewFlashlight ) + { + bReceiveFlashlight = bReceiveFlashlight || ( GetIntParam( info.m_nReceiveFlashlight, params ) != 0 ); + } + bool bHasFlashlight = bReceiveFlashlight && pShader->UsingFlashlight( params ); + + DrawVertexLitGeneric_DX9_Internal( pShader, params, pShaderAPI, + pShaderShadow, bVertexLitGeneric, bHasFlashlight, info, vertexCompression, pContextDataPtr ); +} diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h new file mode 100644 index 00000000..0b5b02e4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h @@ -0,0 +1,144 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VERTEXLITGENERIC_DX9_HELPER_H +#define VERTEXLITGENERIC_DX9_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VertexLitGeneric_DX9_Vars_t +{ + VertexLitGeneric_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); } + + int m_nBaseTexture; + int m_nWrinkle; + int m_nStretch; + int m_nBaseTextureFrame; + int m_nBaseTextureTransform; + int m_nAlbedo; + int m_nDetail; + int m_nDetailFrame; + int m_nDetailScale; + int m_nEnvmap; + int m_nEnvmapFrame; + int m_nEnvmapMask; + int m_nEnvmapMaskFrame; + int m_nEnvmapMaskTransform; + int m_nEnvmapTint; + int m_nBumpmap; + int m_nNormalWrinkle; + int m_nNormalStretch; + int m_nBumpFrame; + int m_nBumpTransform; + int m_nEnvmapContrast; + int m_nEnvmapSaturation; + int m_nAlphaTestReference; + int m_nVertexAlphaTest; + int m_nFlashlightNoLambert; + int m_nFlashlightTexture; + int m_nFlashlightTextureFrame; + + int m_nSelfIllumTint; + int m_nSelfIllumFresnel; + int m_nSelfIllumFresnelMinMaxExp; + + int m_nPhongExponent; + int m_nPhongTint; + int m_nPhongAlbedoTint; + int m_nPhongExponentTexture; + int m_nDiffuseWarpTexture; + int m_nPhongWarpTexture; + int m_nPhongBoost; + int m_nPhongFresnelRanges; + int m_nSelfIllumEnvMapMask_Alpha; + int m_nAmbientOnly; + int m_nHDRColorScale; + int m_nPhong; + int m_nBaseMapAlphaPhongMask; + int m_nEnvmapFresnel; + + int m_nDetailTextureCombineMode; + int m_nDetailTextureBlendFactor; + + // Rim lighting parameters + int m_nRimLight; + int m_nRimLightPower; + int m_nRimLightBoost; + int m_nRimMask; + + int m_nSeamlessScale; + int m_nSeamlessBase; + int m_nSeamlessDetail; + + // distance coded line art parameters + int m_nDistanceAlpha; + int m_nDistanceAlphaFromDetail; + + int m_nSoftEdges; + int m_nEdgeSoftnessStart; + int m_nEdgeSoftnessEnd; + int m_nScaleEdgeSoftnessBasedOnScreenRes; + + int m_nGlow; + int m_nGlowColor; + int m_nGlowAlpha; + int m_nGlowStart; + int m_nGlowEnd; + int m_nGlowX; + int m_nGlowY; + int m_nOutline; + int m_nOutlineColor; + int m_nOutlineAlpha; + int m_nOutlineStart0; + int m_nOutlineStart1; + int m_nOutlineEnd0; + int m_nOutlineEnd1; + int m_nScaleOutlineSoftnessBasedOnScreenRes; + + int m_nSeparateDetailUVs; + int m_nDetailTextureTransform; + + int m_nLinearWrite; + int m_nGammaColorRead; + + int m_nDetailTint; + int m_nInvertPhongMask; + + int m_nDepthBlend; + int m_nDepthBlendScale; + + int m_nSelfIllumMask; + int m_nReceiveFlashlight; + + int m_nBlendTintByBaseAlpha; + + int m_nTintReplacesBaseColor; + +}; + +void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); +void InitVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); +void DrawVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, + CBasePerMaterialContextData **pContextDataPtr + ); + + +#endif // VERTEXLITGENERIC_DX9_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_envmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_envmap.psh new file mode 100644 index 00000000..e539da67 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_envmap.psh @@ -0,0 +1,17 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map + +mul r0, t0, c3 ; base times modulation +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh new file mode 100644 index 00000000..a5810b5e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_flashlight_vs11.vsh @@ -0,0 +1,137 @@ +vs.1.1 + +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "SKINNING" "0..1" +# STATIC: "TEETH" "0..1" + +#include "macros.vsh" + +local( $worldPos, $worldNormal, $projPos ); + +alloc $worldPos +alloc $worldNormal +alloc $projPos + +if( 0 ) +{ + ; NOTE: Don't do this optimization anymore since it would mean a gazillion combos + ; Special case for static prop lighting. We can go directly from + ; world to proj space for position, with the exception of z, which + ; is needed for fogging *if* height fog is enabled. + + ; NOTE: We don't use this path if $envmap is defined since we need + ; worldpos for envmapping. + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + ; Need this for height fog if it's enabled and for height clipping + dp4 $worldPos.z, $vPos, $cModel2 +} +else +{ + &SkinPositionAndNormal( $worldPos, $worldNormal ); + + if( $SKINNING == 1 ) + { + &Normalize( $worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to view space + ;------------------------------------------------------------------------------ + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 +} + +mov oPos, $projPos + +;------------------------------------------------------------------------------ +; Fog +;------------------------------------------------------------------------------ +&CalcFog( $worldPos, $projPos ); + +; base tex coords +dp4 oT1.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_6 +dp4 oT1.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_7 + +; normal map coords +;dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_8 +;dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_9 + +; spotlight texcoords +dp4 oT0.x, $worldPos, $SHADER_SPECIFIC_CONST_1 +dp4 oT0.y, $worldPos, $SHADER_SPECIFIC_CONST_2 +dp4 oT0.z, $worldPos, $SHADER_SPECIFIC_CONST_3 +dp4 oT0.w, $worldPos, $SHADER_SPECIFIC_CONST_4 + +local( $worldPosToLightVector, $distFactors ); + +alloc $worldPosToLightVector + +sub $worldPosToLightVector, $SHADER_SPECIFIC_CONST_0, $worldPos +mov oT2, $worldPosToLightVector + +local( $distatten ); +alloc $distatten +; $distatten = [ 1, 1/dist, 1/distsquared ] + +; dist squared +dp3 $distatten.z, $worldPosToLightVector, $worldPosToLightVector + +; oodist +rsq $distatten.y, $distatten.z + +mov $distatten.x, $cOne + +local( $dist ); +alloc $dist +mul $dist.x, $distatten.z, $distatten.y + +rcp $distatten.z, $distatten.z ; 1/distsquared + +local( $endFalloffFactor ); +alloc $endFalloffFactor + +; ( dist - farZ ) +sub $endFalloffFactor.x, $dist.x, $SHADER_SPECIFIC_CONST_5.w +; 1 / ( (0.6f * farZ) - farZ) +mul $endFalloffFactor, $endFalloffFactor.x, $SHADER_SPECIFIC_CONST_0.w +max $endFalloffFactor, $endFalloffFactor, $cZero +min $endFalloffFactor, $endFalloffFactor, $cOne + +local( $vertAtten ); +alloc $vertAtten +dp3 $vertAtten, $distatten, $SHADER_SPECIFIC_CONST_5 +mul $vertAtten, $vertAtten, $endFalloffFactor + +if( $TEETH ) +{ + alloc $mouthAtten + dp3 $mouthAtten, $worldNormal.xyz, $SHADER_SPECIFIC_CONST_10.xyz + max $mouthAtten, $cZero, $mouthAtten + mul $mouthAtten, $mouthAtten, $SHADER_SPECIFIC_CONST_10.w + mul $vertAtten, $vertAtten, $mouthAtten + free $mouthAtten +} + +mov oD0, $vertAtten + +mov oT3.xyz, $worldNormal.xyz + + +free $dist +free $endFalloffFactor +free $worldPos +free $worldNormal +free $projPos +free $worldPosToLightVector +free $distatten +free $vertAtten diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_inc.vsh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_inc.vsh new file mode 100644 index 00000000..da6b6bf9 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_inc.vsh @@ -0,0 +1,145 @@ +#include "macros.vsh" + +sub VertexLitGeneric +{ + local( $detail ) = shift; + local( $envmap ) = shift; + local( $envmapcameraspace ) = shift; + local( $envmapsphere ) = shift; + local( $decal ) = shift; + + local( $worldPos, $worldNormal, $projPos ); + local( $reflectionVector ); + + ;------------------------------------------------------------------------------ + ; Vertex blending + ;------------------------------------------------------------------------------ + &AllocateRegister( \$worldPos ); + &AllocateRegister( \$worldNormal ); + &AllocateRegister( \$projPos ); +; if( $g_staticLightType eq "static" && $g_ambientLightType eq "none" && +; $g_localLightType1 eq "none" && $g_localLightType2 eq "none" && !$envmap ) + if( 0 ) + { + ; NOTE: Don't do this optimization anymore since it would mean a gazillion combos + ; of the flashlight shaders + ; Special case for static prop lighting. We can go directly from + ; world to proj space for position, with the exception of z, which + ; is needed for fogging *if* height fog is enabled. + + ; NOTE: We don't use this path if $envmap is defined since we need + ; worldpos for envmapping. + dp4 $projPos.x, $vPos, $cModelViewProj0 + dp4 $projPos.y, $vPos, $cModelViewProj1 + dp4 $projPos.z, $vPos, $cModelViewProj2 + dp4 $projPos.w, $vPos, $cModelViewProj3 + ; normal + dp3 $worldNormal.x, $vNormal, $cModel0 + dp3 $worldNormal.y, $vNormal, $cModel1 + dp3 $worldNormal.z, $vNormal, $cModel2 + + ; Need this for height fog if it's enabled and for height clipping + dp4 $worldPos.z, $vPos, $cModel2 + } + else + { + &SkinPositionAndNormal( $worldPos, $worldNormal ); + + if( $SKINNING == 1 ) + { + &Normalize( $worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Transform the position from world to view space + ;------------------------------------------------------------------------------ + dp4 $projPos.x, $worldPos, $cViewProj0 + dp4 $projPos.y, $worldPos, $cViewProj1 + dp4 $projPos.z, $worldPos, $cViewProj2 + dp4 $projPos.w, $worldPos, $cViewProj3 + } + + mov oPos, $projPos + + ;------------------------------------------------------------------------------ + ; Fog + ;------------------------------------------------------------------------------ + &CalcFog( $worldPos, $projPos ); + &FreeRegister( \$projPos ); + + ;------------------------------------------------------------------------------ + ; Lighting + ;------------------------------------------------------------------------------ + &DoLighting( $worldPos, $worldNormal ); + + if( !$envmap ) + { + &FreeRegister( \$worldNormal ); + } + + ;------------------------------------------------------------------------------ + ; Texture coordinates + ;------------------------------------------------------------------------------ + + dp4 oT0.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_0 + dp4 oT0.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_1 + + if( $envmap ) + { + if( $envmapcameraspace ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + + ; transform reflection vector into view space + dp3 oT1.x, $reflectionVector, $cViewModel0 + dp3 oT1.y, $reflectionVector, $cViewModel1 + dp3 oT1.z, $reflectionVector, $cViewModel2 + + &FreeRegister( \$reflectionVector ); + } + elsif( $envmapsphere ) + { + &AllocateRegister( \$reflectionVector ); + &ComputeReflectionVector( $worldPos, $worldNormal, $reflectionVector ); + &ComputeSphereMapTexCoords( $reflectionVector, "oT1" ); + + &FreeRegister( \$reflectionVector ); + } + else + { + &ComputeReflectionVector( $worldPos, $worldNormal, "oT1" ); + } + + ; envmap mask + dp4 oT2.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_2 + dp4 oT2.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_3 + + &FreeRegister( \$worldNormal ); + } + else + { + if ( $decal ) + { + &AllocateRegister( \$temp ); + mov $temp, $vTexCoord0 + sub oT1.xyz, $temp.xyz, $vTexCoord1.xyz + sub oT2.xyz, $vTexCoord2.xyz, $temp.xyz + &FreeRegister( \$temp ); + } + else + { + ; YUCK! This is to make texcoords continuous for mat_softwaretl + mov oT1, $cZero + mov oT2, $cZero + } + } + + if( $detail ) + { + dp4 oT3.x, $vTexCoord0, $SHADER_SPECIFIC_CONST_4 + dp4 oT3.y, $vTexCoord0, $SHADER_SPECIFIC_CONST_5 + } + &FreeRegister( \$worldPos ); +} + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2.psh new file mode 100644 index 00000000..dd19efce --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2.psh @@ -0,0 +1,5 @@ +ps.1.1 + +mov r0, v0 + + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2_ps11.fxc b/sp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2_ps11.fxc new file mode 100644 index 00000000..70ad7094 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_lightingonly_overbright2_ps11.fxc @@ -0,0 +1,9 @@ +struct PS_INPUT +{ + float3 vColor0 : COLOR0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + return float4( i.vColor0, 1.0 ); +} diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_maskedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_maskedenvmap.psh new file mode 100644 index 00000000..c10600e3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_maskedenvmap.psh @@ -0,0 +1,19 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +tex t0 ; base color +tex t1 ; cube map +tex t2 ; envmap mask + +mul r0, t0, c3 ; Base times modulation +mul r1, t1, t2 ; Envmap * mask +mad r0.rgb, r1, c2, r0 ; Base * mod + envmap * mask * tint +mul r0.rgb, v0, r0 ; apply vertex lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedenvmap.psh new file mode 100644 index 00000000..321e797b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedenvmap.psh @@ -0,0 +1,25 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 +tex t1 + +mul r0.rgb, t0, c3 + ; base times modulation +mov r0.a, c3.a ; use modulation alpha (don't use texture alpha) + +mad r0.rgb, t1, c2, r0 ; + envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting + diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedmaskedenvmap.psh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedmaskedenvmap.psh new file mode 100644 index 00000000..e7c52910 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_selfilluminatedmaskedenvmap.psh @@ -0,0 +1,26 @@ +ps.1.1 + +;------------------------------------------------------------------------------ +; Draw a texture . . woo hoo! +; t0 - texture +; +; The texture coordinates need to be defined as follows: +; tc0 - texcoords +;------------------------------------------------------------------------------ + +; Get the color from the texture +tex t0 ; base +tex t1 ; env map +tex t2 ; mask + +mul r0.rgb, t0, c3 + ; base times modulation +mul r0.a, c3.a, t2.a ; alpha = mod alpha * mask alpha + +mul r1, t2, t1 ; envmapmask * envmap +mad r0.rgb, r1, c2, r0 ; + envmapmask * envmap * envmaptint (color only) + +mul r0.rgb, v0, r0 ; Apply lighting +mul_x2 r0.rgb, c0, r0 ; * 2 * (overbrightFactor/2) + +mul r1, t0, c1 ; Self illum * tint +lrp r0.rgb, t0.a, r1, r0 ; Blend between self-illum + base * lighting diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_vs11.vsh b/sp/src/materialsystem/stdshaders/vertexlitgeneric_vs11.vsh new file mode 100644 index 00000000..c0ab2765 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_vs11.vsh @@ -0,0 +1,22 @@ +vs.1.1 + +# STATIC: "HALF_LAMBERT" "0..1" +# STATIC: "ENVMAP" "0..1" +# STATIC: "ENVMAPCAMERASPACE" "0..0" +# STATIC: "ENVMAPSPHERE" "0..1" +# DYNAMIC: "DOWATERFOG" "0..1" +# DYNAMIC: "LIGHT_COMBO" "0..21" +# DYNAMIC: "SKINNING" "0..1" + +# can't have envmapshere or envmapcameraspace without envmap +# SKIP: !$ENVMAP && ( $ENVMAPSPHERE || $ENVMAPCAMERASPACE ) + +# can't have both envmapsphere and envmapcameraspace +# SKIP: $ENVMAPSPHERE && $ENVMAPCAMERASPACE + +# decal is by itself +# SKIP: $DECAL && ( $DETAIL || $ENVMAP || $ENVMAPCAMERASPACE || $ENVMAPSPHERE ) + +#include "VertexLitGeneric_inc.vsh" + +&VertexLitGeneric( 1, $ENVMAP, $ENVMAPCAMERASPACE, $ENVMAPSPHERE, 0 ); diff --git a/sp/src/materialsystem/stdshaders/volume_clouds.cpp b/sp/src/materialsystem/stdshaders/volume_clouds.cpp new file mode 100644 index 00000000..1421dbb4 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/volume_clouds.cpp @@ -0,0 +1,59 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "volume_clouds_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( VolumeClouds, VolumeClouds_dx9 ) +BEGIN_VS_SHADER( VolumeClouds_dx9, "VolumeClouds" ) + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "2", "" ) + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 1" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 2" ) + SHADER_PARAM( BASETEXTURE3, SHADER_PARAM_TYPE_TEXTURE, "", "Texture 3" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "0.0", "Needs CurrentTime Proxy" ) + END_SHADER_PARAMS + + void SetupVarsVolumeClouds( VolumeCloudsVars_t &info ) + { + info.m_nRefractAmount = REFRACTAMOUNT; + info.m_nTexture1 = BASETEXTURE; + info.m_nTexture2 = BASETEXTURE2; + info.m_nTexture3 = BASETEXTURE3; + info.m_nTime = TIME; + } + + SHADER_INIT_PARAMS() + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + InitParamsVolumeClouds( this, params, pMaterialName, info ); + } + + SHADER_FALLBACK + { + if ( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + // Fallback to unlit generic + return "UnlitGeneric_DX8"; + } + + return 0; + } + + SHADER_INIT + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + InitVolumeClouds( this, params, info ); + } + + SHADER_DRAW + { + VolumeCloudsVars_t info; + SetupVarsVolumeClouds( info ); + DrawVolumeClouds( this, params, pShaderAPI, pShaderShadow, info, vertexCompression ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/volume_clouds_helper.cpp b/sp/src/materialsystem/stdshaders/volume_clouds_helper.cpp new file mode 100644 index 00000000..cd2e889e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/volume_clouds_helper.cpp @@ -0,0 +1,138 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "volume_clouds_helper.h" +#include "convar.h" + +// Auto generated inc files +#include "volume_clouds_vs20.inc" +#include "volume_clouds_ps20.inc" +#include "volume_clouds_ps20b.inc" + + +void InitParamsVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VolumeCloudsVars_t &info ) +{ + // Set material flags + SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING ); + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + SET_FLAGS( MATERIAL_VAR_TRANSLUCENT ); + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nTime, 0.0f ); + + // Set material parameter default values + SET_PARAM_FLOAT_IF_NOT_DEFINED( info.m_nRefractAmount, kDefaultRefractAmount ); +} + +void InitVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, VolumeCloudsVars_t &info ) +{ + // Load textures + if ( (info.m_nTexture1 != -1) && params[info.m_nTexture1]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture1, TEXTUREFLAGS_SRGB ); + } + + if ( (info.m_nTexture2 != -1) && params[info.m_nTexture2]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture2, TEXTUREFLAGS_SRGB ); + } + + if ( (info.m_nTexture3 != -1) && params[info.m_nTexture3]->IsDefined() ) + { + pShader->LoadTexture( info.m_nTexture3, TEXTUREFLAGS_SRGB ); + } +} + +void DrawVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, VolumeCloudsVars_t &info, VertexCompressionType_t vertexCompression ) +{ + SHADOW_STATE + { + // Set stream format (note that this shader supports compression) + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + int nTexCoordCount = 1; + int userDataSize = 0; + pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); + + // Vertex Shader + DECLARE_STATIC_VERTEX_SHADER( volume_clouds_vs20 ); + SET_STATIC_VERTEX_SHADER( volume_clouds_vs20 ); + + // Pixel Shader + if( g_pHardwareConfig->SupportsPixelShaders_2_b() && !IsOpenGL() ) // Always send POSIX down the 20 path (rg - why?) + { + DECLARE_STATIC_PIXEL_SHADER( volume_clouds_ps20b ); + SET_STATIC_PIXEL_SHADER( volume_clouds_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( volume_clouds_ps20 ); + SET_STATIC_PIXEL_SHADER( volume_clouds_ps20 ); + } + + // Textures + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + pShaderShadow->EnableSRGBWrite( true ); + + // Blending + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->EnableAlphaWrites( false ); + + // !!! We need to turn this back on because EnableAlphaBlending() above disables it! + //pShaderShadow->EnableDepthWrites( true ); + } + DYNAMIC_STATE + { + // Set Vertex Shader Combos + DECLARE_DYNAMIC_VERTEX_SHADER( volume_clouds_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); + SET_DYNAMIC_VERTEX_SHADER( volume_clouds_vs20 ); + + // Set Vertex Shader Constants + + // Time + float vPackedVsConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float flTime = IS_PARAM_DEFINED( info.m_nTime ) && params[info.m_nTime]->GetFloatValue() > 0.0f ? params[info.m_nTime]->GetFloatValue() : pShaderAPI->CurrentTime(); + float flRotateSpeed = 0.065f; + vPackedVsConst1[0] = flTime * flRotateSpeed * 1.0f; + vPackedVsConst1[1] = flTime * flRotateSpeed * 2.0f; + vPackedVsConst1[2] = flTime * flRotateSpeed * 4.0f; + vPackedVsConst1[0] -= (float)( (int)( vPackedVsConst1[0] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + vPackedVsConst1[1] -= (float)( (int)( vPackedVsConst1[1] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + vPackedVsConst1[2] -= (float)( (int)( vPackedVsConst1[2] / ( 2.0f * 3.14159f ) ) ) * 2.0f * 3.14159f; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vPackedVsConst1, 1 ); + + // Set Pixel Shader Combos + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() && !IsOpenGL() ) // Always send POSIX down the 20 path (rg - why?) + { + DECLARE_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( volume_clouds_ps20 ); + } + + // Bind textures + pShader->BindTexture( SHADER_SAMPLER0, info.m_nTexture1 ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nTexture2 ); + pShader->BindTexture( SHADER_SAMPLER2, info.m_nTexture3 ); + + // Set Pixel Shader Constants + float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->GetWorldSpaceCameraPosition( vEyePos ); + pShaderAPI->SetPixelShaderConstant( 5, vEyePos, 1 ); + + float vPackedConst6[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vPackedConst6[0] = IS_PARAM_DEFINED( info.m_nRefractAmount ) ? params[info.m_nRefractAmount]->GetFloatValue() : kDefaultRefractAmount; + vPackedConst6[1] = vPackedVsConst1[0]; // Time % 1000 + pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 ); + } + pShader->Draw(); +} diff --git a/sp/src/materialsystem/stdshaders/volume_clouds_helper.h b/sp/src/materialsystem/stdshaders/volume_clouds_helper.h new file mode 100644 index 00000000..abbb63b7 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/volume_clouds_helper.h @@ -0,0 +1,41 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef VOLUME_CLOUDS_HELPER_H +#define VOLUME_CLOUDS_HELPER_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct VolumeCloudsVars_t +{ + VolumeCloudsVars_t() { memset( this, 0xFF, sizeof( VolumeCloudsVars_t ) ); } + + int m_nRefractAmount; + int m_nTexture1; + int m_nTexture2; + int m_nTexture3; + int m_nTime; +}; + +// Default values (Arrays should only be vec[4]) +static const float kDefaultRefractAmount = 0.1f; + +void InitParamsVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VolumeCloudsVars_t &info ); +void InitVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, VolumeCloudsVars_t &info ); +void DrawVolumeClouds( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, VolumeCloudsVars_t &info, VertexCompressionType_t vertexCompression ); + +#endif // VolumeClouds_HELPER_H diff --git a/sp/src/materialsystem/stdshaders/volume_clouds_ps2x.fxc b/sp/src/materialsystem/stdshaders/volume_clouds_ps2x.fxc new file mode 100644 index 00000000..7435f305 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/volume_clouds_ps2x.fxc @@ -0,0 +1,66 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] + +// Includes ======================================================================================= +#include "common_vertexlitgeneric_dx9.h" + +// Texture Samplers =============================================================================== +sampler g_tInnerSampler : register( s0 ); +sampler g_tMiddleSampler : register( s1 ); +sampler g_tOuterSampler : register( s2 ); + +// Shaders Constants and Globals ================================================================== +//const float4 g_vPackedConst6 : register( c6 ); +//#define g_flTime g_vPackedConst6.w + +// Interpolated values ============================================================================ +struct PS_INPUT +{ + float4 v2DTangentViewVector01 : TEXCOORD0; + float4 vUv01 : TEXCOORD1; + float4 v2DTangentViewVector2_vUv2 : TEXCOORD2; +}; + +// Main =========================================================================================== +float4 main( PS_INPUT i ) : COLOR +{ + float4 vFinalColor = float4( 0.0f, 0.0f, 0.0f, 1.0f ); + +#if defined(SHADER_MODEL_PS_2_0) + float flNumLayers = 2.0f; +#else + float flNumLayers = 10.0f; +#endif + + //float flColorDim = 1.0f; + for ( float j=flNumLayers-1.0f; j>=0.0f; j-=1.0f ) // From hightest to lowest layer + { + float4 vInnerTexel = tex2D( g_tInnerSampler, saturate( i.vUv01.xy + i.v2DTangentViewVector01.xy * 0.005 * j ) ); + float4 vMiddleTexel = tex2D( g_tMiddleSampler, saturate( i.vUv01.wz + i.v2DTangentViewVector01.wz * 0.005 * j ) ); + float4 vOuterTexel = tex2D( g_tOuterSampler, saturate( i.v2DTangentViewVector2_vUv2.wz + i.v2DTangentViewVector2_vUv2.xy * 0.005 * j ) ); + + float4 vThisTexel; + vThisTexel.rgb = ( vInnerTexel.rgb * vInnerTexel.a ) + ( vMiddleTexel.rgb * vMiddleTexel.a ) + ( vOuterTexel.rgb * vOuterTexel.a ); + vThisTexel.a = 1.0f - ( ( 1.0f - vOuterTexel.a ) * ( 1.0f - vMiddleTexel.a ) * ( 1.0f - vInnerTexel.a ) ); + + //vThisTexel.rgb *= flColorDim; + //flColorDim *= 0.95f; + + // 5.0 and 0.8625 are magic numbers that look good with the current textures + float flBlendValue = saturate( pow( vThisTexel.a, lerp( 5.0f, 0.8625f, saturate( j/(flNumLayers-1.0f) ) ) ) ); + + vFinalColor.rgb = vThisTexel.rgb + ( vFinalColor.rgb * ( 1.0f - flBlendValue ) ); + vFinalColor.a *= 1.0f - flBlendValue; // Dest alpha scalar + } + + //===============// + // Combine terms // + //===============// + float4 result; + result.rgb = vFinalColor.rgb; + result.a = 1.0f - vFinalColor.a; + + return FinalOutput( result, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_LINEAR ); //go back to final output when it'll fit. +} diff --git a/sp/src/materialsystem/stdshaders/volume_clouds_vs20.fxc b/sp/src/materialsystem/stdshaders/volume_clouds_vs20.fxc new file mode 100644 index 00000000..ccab2574 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/volume_clouds_vs20.fxc @@ -0,0 +1,103 @@ +//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "SKINNING" "0..1" + +// Includes +#include "common_vs_fxc.h" + +// Globals +static const bool g_bSkinning = SKINNING ? true : false; + +const float3 g_vTime : register( SHADER_SPECIFIC_CONST_0 ); +#define g_flTime1x g_vTime.x +#define g_flTime2x g_vTime.y +#define g_flTime4x g_vTime.z + +const float4 cBaseTexCoordTransform[2] : register( SHADER_SPECIFIC_CONST_1 ); + +// Structs +struct VS_INPUT +{ + float4 vPos : POSITION; // Position + float4 vNormal : NORMAL; // Normal + float4 vBoneWeights : BLENDWEIGHT; // Skin weights + float4 vBoneIndices : BLENDINDICES; // Skin indices + float4 vTexCoord0 : TEXCOORD0; // Base texture coordinates + float4 vUserData : TANGENT; +}; + +struct VS_OUTPUT +{ + float4 vProjPosition : POSITION; // Projection-space position + float4 v2DTangentViewVector01 : TEXCOORD0; + float4 vUv01 : TEXCOORD1; + float4 v2DTangentViewVector2_vUv2 : TEXCOORD2; +}; + +// Main +VS_OUTPUT main( const VS_INPUT i ) +{ + VS_OUTPUT o; + + // Decompress compressed normal and tangent + float4 vObjPosition = i.vPos.xyzw; + float3 vObjNormal; + float4 vObjTangent; + DecompressVertex_NormalTangent( i.vNormal, i.vUserData, vObjNormal, vObjTangent ); + + // Transform the position + float3 vWorldPosition = { 0.0f, 0.0f, 0.0f }; + float3 vWorldNormal = { 0.0f, 0.0f, 0.0f }; + float3 vWorldTangent = { 0.0f, 0.0f, 0.0f }; + float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f }; + SkinPositionNormalAndTangentSpace( g_bSkinning, vObjPosition, vObjNormal.xyz, vObjTangent.xyzw, i.vBoneWeights, i.vBoneIndices, vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal ); + vWorldNormal.xyz = normalize( vWorldNormal.xyz ); + vWorldTangent.xyz = normalize( vWorldTangent.xyz ); + vWorldBinormal.xyz = normalize( vWorldBinormal.xyz ); + + // Transform into projection space + float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj ); + o.vProjPosition = vProjPosition; + + // View vector + float3 vWorldViewVector = normalize( vWorldPosition.xyz - cEyePos.xyz ); + float3 vTangentViewVector = Vec3WorldToTangentNormalized( vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz ); + + // Texture coordinates + float4 mRotate; + float2 vBaseUv = i.vTexCoord0.xy; + + // Inner layer + mRotate.x = cos( g_flTime4x ); + mRotate.y = -sin( g_flTime4x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + o.vUv01.xy = ( vBaseUv.xy - 0.5f ) * 1.0f; + o.vUv01.xy = float2( dot( o.vUv01.xy, mRotate.xy ), dot( o.vUv01.xy, mRotate.zw ) ); + o.vUv01.xy += 0.5f; + o.v2DTangentViewVector01.xy = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + // Middle layer + mRotate.x = cos( g_flTime2x ); + mRotate.y = -sin( g_flTime2x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + o.vUv01.wz = ( vBaseUv.xy - 0.5f ) * 1.0f; + o.vUv01.wz = float2( dot( o.vUv01.wz, mRotate.xy ), dot( o.vUv01.wz, mRotate.zw ) ); + o.vUv01.wz += 0.5f; + o.v2DTangentViewVector01.wz = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + // Outer layer + mRotate.x = cos( g_flTime1x ); + mRotate.y = -sin( g_flTime1x ); + mRotate.z = -mRotate.y; + mRotate.w = mRotate.x; + float2 vUv2 = ( vBaseUv.xy - 0.5f ) * 1.0f; + vUv2.xy = float2( dot( vUv2.xy, mRotate.xy ), dot( vUv2.xy, mRotate.zw ) ); + vUv2.xy += 0.5f; + o.v2DTangentViewVector2_vUv2.wz = vUv2.xy; + o.v2DTangentViewVector2_vUv2.xy = float2( dot( vTangentViewVector.xy, mRotate.xy ), dot( vTangentViewVector.xy, mRotate.zw ) ); + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/vr_distort_hud.cpp b/sp/src/materialsystem/stdshaders/vr_distort_hud.cpp new file mode 100644 index 00000000..b78a3e51 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vr_distort_hud.cpp @@ -0,0 +1,224 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "commandbuilder.h" + +#include "vr_distort_hud_ps20.inc" +#include "vr_distort_hud_ps20b.inc" +#include "vr_distort_hud_vs20.inc" +#include "vr_distort_hud_ps30.inc" +#include "vr_distort_hud_vs30.inc" + +#include "../materialsystem_global.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +class CVRDistortTexture_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > m_SemiStaticCmdsOut; + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CVRDistortTexture_DX9_Context( void ) + { + m_pStaticCmds = NULL; + } + + ~CVRDistortTexture_DX9_Context( void ) + { + ResetStaticCmds(); + } + +}; + + +BEGIN_VS_SHADER( vr_distort_hud, "Help for hud warp" ) + BEGIN_SHADER_PARAMS + + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_gui", "" ) + SHADER_PARAM( DISTORTMAP, SHADER_PARAM_TYPE_TEXTURE, "vr_distort_map_left", "" ) + SHADER_PARAM( DISTORTBOUNDS, SHADER_PARAM_TYPE_VEC4, "[ 0 0 1 1 ]", "" ) + SHADER_PARAM( HUDTRANSLUCENT, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( HUDUNDISTORT, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( DISTORTMAP, TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NODEBUGOVERRIDE | TEXTUREFLAGS_SINGLECOPY | + TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ); + } + + SHADER_DRAW + { + CVRDistortTexture_DX9_Context *pContextData = reinterpret_cast< CVRDistortTexture_DX9_Context *> ( *pContextDataPtr ); + bool bNeedRegenStaticCmds = ( !pContextData ) || pShaderShadow; + + if ( !pContextData ) // make sure allocated + { + pContextData = new CVRDistortTexture_DX9_Context; + *pContextDataPtr = pContextData; + } + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER0, BASETEXTURE, -1 ); + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER1, DISTORTMAP, -1 ); + + staticCmdsBuf.End(); + + // now, copy buf + pContextData->m_pStaticCmds = new uint8[ staticCmdsBuf.Size() ]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + + if ( pShaderAPI && pContextData->m_bMaterialVarsChanged ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + pContextData->m_SemiStaticCmdsOut.SetAmbientCubeDynamicStateVertexShader(); + pContextData->m_SemiStaticCmdsOut.End(); + } + + SHADOW_STATE + { + SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->EnableSRGBWrite( true ); + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.0f ); + + if ( IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) ) + { + pShaderShadow->EnableAlphaTest( true ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + pShaderShadow->EnableAlphaTest( false ); + pShaderShadow->EnableBlending( false ); + pShaderShadow->BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ZERO ); + } + + DefaultFog(); + + int nFormat = 0; + nFormat |= VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( nFormat, 2, 0, 0 ); + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + SET_STATIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + SET_STATIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + SET_STATIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + } + } + else + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + SET_STATIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + SET_STATIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + } + } + + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + pShaderAPI->SetDefaultState(); + + SetPixelShaderConstant( 0, DISTORTBOUNDS ); + SetPixelShaderConstant( 1, HUDTRANSLUCENT ); + + int hudUndistortEnabled = ( params[ HUDUNDISTORT ]->GetIntValue() == 0 ) ? 0 : 1; + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_HUDUNDISTORT, hudUndistortEnabled ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_HUDUNDISTORT, hudUndistortEnabled ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps20 ); + } + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_hud_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_HUDUNDISTORT, hudUndistortEnabled ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_hud_ps30 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + + Draw(); + + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/vr_distort_hud_ps2x.fxc b/sp/src/materialsystem/stdshaders/vr_distort_hud_ps2x.fxc new file mode 100644 index 00000000..331c1897 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vr_distort_hud_ps2x.fxc @@ -0,0 +1,78 @@ +// DYNAMIC: "CMBO_HUDUNDISTORT" "0..1" + +#include "shader_constant_register_map.h" +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler DistortMapTextureSampler : register( s1 ); + +const float4 DistortBounds : register( c0 ); +const int bHudTranslucent : register( c1 ); + +struct PS_INPUT +{ + float2 vBaseTexCoord : TEXCOORD0; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + float2 vOriginal = i.vBaseTexCoord.xy; + + + // The full uv 0->1 range of the base texture here is shifted/scaled so that it maps + // to the region that would be minUV->maxUV of the base texture in the regular undistort + // code. This lets us overlay a higher-resolution inset rectangle directly onto the + // render target with undistort, which results in a much higher-quality HUD. + + float2 minUV = DistortBounds.xy; + float2 maxUV = DistortBounds.zw; + float2 scaleUV = 1.0 / ( maxUV - minUV ); + + + float2 vGreen; + float4 vFinal; + + #if ( CMBO_HUDUNDISTORT ) + { + float4 vRead = tex2D( DistortMapTextureSampler, vOriginal ); + + float2 vRed = vRead.xy; + float2 vBlue = vRead.zw; + + vGreen = ( vRed + vBlue ) / 2.0; + + vRed = ( vRed - minUV ) * scaleUV; + vGreen = ( vGreen - minUV ) * scaleUV; + vBlue = ( vBlue - minUV ) * scaleUV; + + vFinal.r = tex2D( BaseTextureSampler, vRed ).r; + vFinal.ga = tex2D( BaseTextureSampler, vGreen ).ga; + vFinal.b = tex2D( BaseTextureSampler, vBlue ).b; + } + #else + { + vGreen = ( vOriginal - minUV ) * scaleUV; + vFinal = tex2D( BaseTextureSampler, vGreen ); + } + #endif + + + // When the HUD isn't supposed to be rendered as translucent, some of its elements do occasionally have non-unit alpha. + // We always have blending and alphatest enabled here, so if the hud itself is not supposed to be translucent we need + // to fix up the alphas. + vFinal.a = lerp( 1, vFinal.a, bHudTranslucent ); + + + // Smooth off the edges of the quad. This also gives (0,0,0,0) in the outer areas, for alpha test and for blackout. + + const float edgeRampFrac = 0.005; + float2 uvEdgeRamp = smoothstep( float2(-edgeRampFrac,-edgeRampFrac), float2(edgeRampFrac,edgeRampFrac), vGreen ) * + ( 1 - smoothstep( float2(1-edgeRampFrac,1-edgeRampFrac), float2(1+edgeRampFrac,1+edgeRampFrac), vGreen ) ); + + float edgeRamp = uvEdgeRamp.x * uvEdgeRamp.y; + + vFinal *= edgeRamp; + + + return vFinal; +} diff --git a/sp/src/materialsystem/stdshaders/vr_distort_hud_vs20.fxc b/sp/src/materialsystem/stdshaders/vr_distort_hud_vs20.fxc new file mode 100644 index 00000000..b82bfa13 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vr_distort_hud_vs20.fxc @@ -0,0 +1,26 @@ +#include "common_vs_fxc.h" + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + o.vProjPos = v.vPos; + o.vBaseTexCoord = v.vBaseTexCoord; + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/vr_distort_texture.cpp b/sp/src/materialsystem/stdshaders/vr_distort_texture.cpp new file mode 100644 index 00000000..1e87d72a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vr_distort_texture.cpp @@ -0,0 +1,213 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "BaseVSShader.h" +#include "commandbuilder.h" + +#include "vr_distort_texture_ps20.inc" +#include "vr_distort_texture_ps20b.inc" +#include "vr_distort_texture_vs20.inc" +#include "vr_distort_texture_ps30.inc" +#include "vr_distort_texture_vs30.inc" + +#include "../materialsystem_global.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + + + + + + +class CVRDistortTexture_DX9_Context : public CBasePerMaterialContextData +{ +public: + uint8 *m_pStaticCmds; + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > m_SemiStaticCmdsOut; + + void ResetStaticCmds( void ) + { + if ( m_pStaticCmds ) + { + delete[] m_pStaticCmds; + m_pStaticCmds = NULL; + } + } + + CVRDistortTexture_DX9_Context( void ) + { + m_pStaticCmds = NULL; + } + + ~CVRDistortTexture_DX9_Context( void ) + { + ResetStaticCmds(); + } + +}; + + +static const float kAllZeros[ 4 ] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + +BEGIN_VS_SHADER( vr_distort_texture, "Help for warp" ) + BEGIN_SHADER_PARAMS + + SHADER_PARAM( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( DISTORTMAP, SHADER_PARAM_TYPE_TEXTURE, "vr_distort_map", "" ) + SHADER_PARAM( USERENDERTARGET, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + LoadTexture( DISTORTMAP, TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NODEBUGOVERRIDE | + TEXTUREFLAGS_SINGLECOPY | TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ); + } + + SHADER_DRAW + { + CVRDistortTexture_DX9_Context *pContextData = reinterpret_cast< CVRDistortTexture_DX9_Context *> ( *pContextDataPtr ); + bool bNeedRegenStaticCmds = ( !pContextData ) || pShaderShadow; + + if ( !pContextData ) // make sure allocated + { + pContextData = new CVRDistortTexture_DX9_Context; + *pContextDataPtr = pContextData; + } + + if ( pShaderShadow || bNeedRegenStaticCmds ) + { + pContextData->ResetStaticCmds(); + CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf; + + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER0, BASETEXTURE, -1 ); + staticCmdsBuf.BindTexture( this, SHADER_SAMPLER1, DISTORTMAP, -1 ); + + staticCmdsBuf.End(); + + // now, copy buf + pContextData->m_pStaticCmds = new uint8[ staticCmdsBuf.Size() ]; + memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() ); + } + + if ( pShaderAPI && pContextData->m_bMaterialVarsChanged ) + { + // need to regenerate the semistatic cmds + pContextData->m_SemiStaticCmdsOut.Reset(); + pContextData->m_bMaterialVarsChanged = false; + + pContextData->m_SemiStaticCmdsOut.SetAmbientCubeDynamicStateVertexShader(); + pContextData->m_SemiStaticCmdsOut.End(); + } + + SHADOW_STATE + { + SetInitialShadowState( ); + + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableDepthTest( false ); + + pShaderShadow->EnableBlending( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + pShaderShadow->EnableSRGBWrite( true ); + pShaderShadow->EnableAlphaWrites( false ); + pShaderShadow->EnableAlphaTest( false ); + + DefaultFog(); + + int nFormat = 0; + nFormat |= VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( nFormat, 2, 0, 0 ); + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + SET_STATIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + SET_STATIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + SET_STATIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + } + } + else + { + DECLARE_STATIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + SET_STATIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + + DECLARE_STATIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + SET_STATIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + } + } + + DYNAMIC_STATE + { + CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut; + DynamicCmdsOut.Call( pContextData->m_pStaticCmds ); + DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() ); + + pShaderAPI->SetDefaultState(); + + int useRenderTarget = ( params[ USERENDERTARGET ]->GetIntValue() == 0 ) ? 0 : 1; + + if ( !g_pHardwareConfig->SupportsShaderModel_3_0() ) + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_USERENDERTARGET, useRenderTarget ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_USERENDERTARGET, useRenderTarget ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps20 ); + } + } + else + { + DECLARE_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + SET_DYNAMIC_VERTEX_SHADER( vr_distort_texture_vs30 ); + + DECLARE_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( CMBO_USERENDERTARGET, useRenderTarget ); + SET_DYNAMIC_PIXEL_SHADER( vr_distort_texture_ps30 ); + } + + DynamicCmdsOut.End(); + pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() ); + } + Draw(); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/vr_distort_texture_ps2x.fxc b/sp/src/materialsystem/stdshaders/vr_distort_texture_ps2x.fxc new file mode 100644 index 00000000..23ff3f5f --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vr_distort_texture_ps2x.fxc @@ -0,0 +1,49 @@ +// DYNAMIC: "CMBO_USERENDERTARGET" "0..1" + +#include "shader_constant_register_map.h" +#include "common_ps_fxc.h" + +sampler BaseTextureSampler : register( s0 ); +sampler DistortMapTextureSampler : register( s1 ); + + +struct PS_INPUT +{ + float2 vBaseTexCoord : TEXCOORD0; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + float2 vOriginal = i.vBaseTexCoord.xy; + + float4 vRead = tex2D( DistortMapTextureSampler, vOriginal ); + + float2 vGreen; + vGreen.r = ( vRead.x + vRead.z ) / 2.0; + vGreen.g = ( vRead.y + vRead.w ) / 2.0; + + float4 vFinal; + vFinal.r = tex2D( BaseTextureSampler, vRead.xy ).r; + vFinal.ga = tex2D( BaseTextureSampler, vGreen ).ga; + vFinal.b = tex2D( BaseTextureSampler, vRead.zw ).b; + + float fBoundsCheck; + #if ( CMBO_USERENDERTARGET ) + { + fBoundsCheck = saturate( dot( (vGreen.xy < float2(0.01,0.01)), float2(1,1)) + dot( (vGreen.xy > float2(0.99,0.99)), float2(1,1)) ); + } + #else + { + fBoundsCheck = saturate( dot( (vGreen.xy < float2(0.005,0.005)), float2(1,1)) + dot( (vGreen.xy > float2(0.995,0.995)), float2(1,1)) + + (vGreen.x > 0.495 && vGreen.x < 0.505 ) ); + } + #endif + + vFinal.xyz = lerp( vFinal.xyz, float3(0,0,0), fBoundsCheck ); + + return vFinal; +} + + + diff --git a/sp/src/materialsystem/stdshaders/vr_distort_texture_vs20.fxc b/sp/src/materialsystem/stdshaders/vr_distort_texture_vs20.fxc new file mode 100644 index 00000000..b82bfa13 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/vr_distort_texture_vs20.fxc @@ -0,0 +1,26 @@ +#include "common_vs_fxc.h" + + +struct VS_INPUT +{ + float4 vPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +struct VS_OUTPUT +{ + float4 vProjPos : POSITION; + float2 vBaseTexCoord : TEXCOORD0; +}; + + +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o; + + o.vProjPos = v.vPos; + o.vBaseTexCoord = v.vBaseTexCoord; + + return o; +} diff --git a/sp/src/materialsystem/stdshaders/water.cpp b/sp/src/materialsystem/stdshaders/water.cpp new file mode 100644 index 00000000..92a26375 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water.cpp @@ -0,0 +1,614 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" +#include "common_hlsl_cpp_consts.h" // hack hack hack! +#include "convar.h" + +#include "WaterCheap_vs20.inc" +#include "WaterCheap_ps20.inc" +#include "WaterCheap_ps20b.inc" +#include "Water_vs20.inc" +#include "Water_ps20.inc" +#include "water_ps20b.inc" + +#ifndef _X360 +static ConVar r_waterforceexpensive( "r_waterforceexpensive", "0", FCVAR_ARCHIVE ); +#endif + +DEFINE_FALLBACK_SHADER( Water, Water_DX9_HDR ) + +BEGIN_VS_SHADER( Water_DX90, + "Help for Water" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterRefraction", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0.8", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "dev/water_normal", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( FOGSTART, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( FOGEND, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( ABOVEWATER, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( NOLOWENDLIGHTMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( SCROLL1, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( SCROLL2, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( BLURREFRACT, SHADER_PARAM_TYPE_BOOL, "0", "Cause the refraction to be blurry on ps2b hardware" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + if( !params[ABOVEWATER]->IsDefined() ) + { + Warning( "***need to set $abovewater for material %s\n", pMaterialName ); + params[ABOVEWATER]->SetIntValue( 1 ); + } + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCALE]->IsDefined() ) + { + params[SCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[SCROLL1]->IsDefined() ) + { + params[SCROLL1]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + if( !params[SCROLL2]->IsDefined() ) + { + params[SCROLL2]->SetVecValue( 0.0f, 0.0f, 0.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + + // By default, we're force expensive on dx9. NO WE DON'T!!!! + if( !params[FORCEEXPENSIVE]->IsDefined() ) + { +#ifdef _X360 + params[FORCEEXPENSIVE]->SetIntValue( 0 ); +#else + params[FORCEEXPENSIVE]->SetIntValue( 1 ); +#endif + } + if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + + // Fallbacks for water need lightmaps usually + if ( !params[NOLOWENDLIGHTMAP]->GetIntValue() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[NORMALMAP]->IsDefined() ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + return "Water_DX81"; + } + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE, TEXTUREFLAGS_SRGB ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE, TEXTUREFLAGS_SRGB ); + } + if ( params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP, TEXTUREFLAGS_SRGB ); + } + if ( params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + if( params[BASETEXTURE]->IsDefined() ) + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + } + } + + inline void GetVecParam( int constantVar, float *val ) + { + if( constantVar == -1 ) + return; + + IMaterialVar* pVar = s_ppParams[constantVar]; + Assert( pVar ); + + if (pVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pVar->GetVecValue( val, 4 ); + else + val[0] = val[1] = val[2] = val[3] = pVar->GetFloatValue(); + } + + inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bReflection, bool bRefraction ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + if( bRefraction ) + { + // refract sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + if( bReflection ) + { + // reflect sampler + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); + if( params[BASETEXTURE]->IsTexture() ) + { + // BASETEXTURE + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true ); + // LIGHTMAP + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); + } + } + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 1; + if( params[BASETEXTURE]->IsTexture() ) + { + numTexCoords = 3; + } + pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 ); + + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( params[NORMALMAP]->IsTexture() && g_pHardwareConfig->SupportsNormalMapCompression() ) + { + ITexture *pNormalMap = params[NORMALMAP]->GetTextureValue(); + if ( pNormalMap ) + { + // Clamp this to 0 or 1 since that's how we've authored the water shader (i.e. no separate alpha map/channel) + nNormalDecodeMode = pNormalMap->GetNormalDecodeMode() == NORMAL_DECODE_NONE ? NORMAL_DECODE_NONE : NORMAL_DECODE_ATI2N; + } + } + + DECLARE_STATIC_VERTEX_SHADER( water_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_VERTEX_SHADER( water_vs20 ); + + // "REFLECT" "0..1" + // "REFRACT" "0..1" + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( water_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( ABOVEWATER, params[ABOVEWATER]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER_COMBO( BLURRY_REFRACT, params[BLURREFRACT]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( water_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( water_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( REFLECT, bReflection ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( ABOVEWATER, params[ABOVEWATER]->GetIntValue() ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() ); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( water_ps20 ); + } + + FogToFogColor(); + + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + + pShaderShadow->EnableAlphaWrites( true ); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + if( bRefraction ) + { + // HDRFIXME: add comment about binding.. Specify the number of MRTs in the enable + BindTexture( SHADER_SAMPLER0, REFRACTTEXTURE, -1 ); + } + if( bReflection ) + { + BindTexture( SHADER_SAMPLER2, REFLECTTEXTURE, -1 ); + } + BindTexture( SHADER_SAMPLER4, NORMALMAP, BUMPFRAME ); + if( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // Refraction tint + if( bRefraction ) + { + SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT ); + } + // Reflection tint + if( bReflection ) + { + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER ) + { + // Need to multiply by 4 in linear space since we premultiplied into + // the render target by .25 to get overbright data in the reflection render target. + float gammaReflectTint[3]; + params[REFLECTTINT]->GetVecValue( gammaReflectTint, 3 ); + float linearReflectTint[4]; + linearReflectTint[0] = GammaToLinear( gammaReflectTint[0] ) * 4.0f; + linearReflectTint[1] = GammaToLinear( gammaReflectTint[1] ) * 4.0f; + linearReflectTint[2] = GammaToLinear( gammaReflectTint[2] ) * 4.0f; + linearReflectTint[3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 4, linearReflectTint, 1 ); + } + else + { + SetPixelShaderConstantGammaToLinear( 4, REFLECTTINT ); + } + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + float curtime=pShaderAPI->CurrentTime(); + float vc0[4]; + float v0[4]; + params[SCROLL1]->GetVecValue(v0,4); + vc0[0]=curtime*v0[0]; + vc0[1]=curtime*v0[1]; + params[SCROLL2]->GetVecValue(v0,4); + vc0[2]=curtime*v0[0]; + vc0[3]=curtime*v0[1]; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vc0, 1 ); + + float c0[4] = { 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + + float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + // fresnel constants + float c3[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, c3, 1 ); + + float c5[4] = { params[REFLECTAMOUNT]->GetFloatValue(), params[REFLECTAMOUNT]->GetFloatValue(), + params[REFRACTAMOUNT]->GetFloatValue(), params[REFRACTAMOUNT]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); + + SetPixelShaderConstantGammaToLinear( 6, FOGCOLOR ); + + float c7[4] = + { + params[FOGSTART]->GetFloatValue(), + params[FOGEND]->GetFloatValue() - params[FOGSTART]->GetFloatValue(), + 1.0f, + 0.0f + }; + if (g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER ) + { + // water overbright factor + c7[2] = 4.0; + } + pShaderAPI->SetPixelShaderConstant( 7, c7, 1 ); + + pShaderAPI->SetPixelShaderFogParams( 8 ); + + DECLARE_DYNAMIC_VERTEX_SHADER( water_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( water_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() ); + SET_DYNAMIC_PIXEL_SHADER( water_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( water_ps20 ); + } + } + Draw(); + } + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bRefraction ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + if( bBlend ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + // envmap + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + // normal map + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( bRefraction && bBlend ) + { + // refraction map (used for alpha) + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; + if ( params[NORMALMAP]->IsTexture() && g_pHardwareConfig->SupportsNormalMapCompression() ) + { + ITexture *pNormalMap = params[NORMALMAP]->GetTextureValue(); + if ( pNormalMap ) + { + // Clamp this to 0 or 1 since that's how we've authored the water shader (i.e. no separate alpha map/channel) + nNormalDecodeMode = pNormalMap->GetNormalDecodeMode() == NORMAL_DECODE_NONE ? NORMAL_DECODE_NONE : NORMAL_DECODE_ATI2N; + } + } + + DECLARE_STATIC_VERTEX_SHADER( watercheap_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( BLEND, bBlend && bRefraction ); + SET_STATIC_VERTEX_SHADER( watercheap_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( watercheap_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL, params[NOFRESNEL]->GetIntValue() == 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLEND, bBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTALPHA, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( watercheap_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( watercheap_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL, params[NOFRESNEL]->GetIntValue() == 0 ); + SET_STATIC_PIXEL_SHADER_COMBO( BLEND, bBlend ); + SET_STATIC_PIXEL_SHADER_COMBO( REFRACTALPHA, bRefraction ); + SET_STATIC_PIXEL_SHADER_COMBO( HDRTYPE, g_pHardwareConfig->GetHDRType() ); + Vector4D Scroll1; + params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 ); + SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE,fabs(Scroll1.x) > 0.0); + SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); + SET_STATIC_PIXEL_SHADER( watercheap_ps20 ); + } + + // HDRFIXME: test cheap water! + if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) + { + // we are writing linear values from this shader. + pShaderShadow->EnableSRGBWrite( true ); + } + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + BindTexture( SHADER_SAMPLER0, ENVMAP, ENVMAPFRAME ); + BindTexture( SHADER_SAMPLER1, NORMALMAP, BUMPFRAME ); + if( bRefraction && bBlend ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTEXTURE, -1 ); + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + + float cheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float cheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + float cheapWaterParams[4] = + { + cheapWaterStartDistance * VSHADER_VECT_SCALE, + cheapWaterEndDistance * VSHADER_VECT_SCALE, + PSHADER_VECT_SCALE / ( cheapWaterEndDistance - cheapWaterStartDistance ), + cheapWaterStartDistance / ( cheapWaterEndDistance - cheapWaterStartDistance ), + }; + pShaderAPI->SetPixelShaderConstant( 1, cheapWaterParams ); + + if( g_pConfig->bShowSpecular ) + { + SetPixelShaderConstant( 2, REFLECTTINT, REFLECTBLENDFACTOR ); + } + else + { + float zero[4] = { 0.0f, 0.0f, 0.0f, params[REFLECTBLENDFACTOR]->GetFloatValue() }; + pShaderAPI->SetPixelShaderConstant( 2, zero ); + } + + pShaderAPI->SetPixelShaderFogParams( 3 ); + + if( params[SCROLL1]->IsDefined()) + { + float curtime=pShaderAPI->CurrentTime(); + float vc0[4]; + float v0[4]; + params[SCROLL1]->GetVecValue(v0,4); + vc0[0]=curtime*v0[0]; + vc0[1]=curtime*v0[1]; + params[SCROLL2]->GetVecValue(v0,4); + vc0[2]=curtime*v0[0]; + vc0[3]=curtime*v0[1]; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vc0, 1 ); + } + + DECLARE_DYNAMIC_VERTEX_SHADER( watercheap_vs20 ); + SET_DYNAMIC_VERTEX_SHADER( watercheap_vs20 ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20b ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20 ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20 ); + } + } + Draw(); + } + + SHADER_DRAW + { + // TODO: fit the cheap water stuff into the water shader so that we don't have to do + // 2 passes. +#ifdef _X360 + bool bForceExpensive = false; +#else + bool bForceExpensive = r_waterforceexpensive.GetBool(); +#endif + bool bForceCheap = (params[FORCECHEAP]->GetIntValue() != 0) || UsingEditor( params ); + if ( bForceCheap ) + { + bForceExpensive = false; + } + else + { + bForceExpensive = bForceExpensive || (params[FORCEEXPENSIVE]->GetIntValue() != 0); + } + Assert( !( bForceCheap && bForceExpensive ) ); + + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); +#ifdef _X360 + bool bReflection = params[REFLECTTEXTURE]->IsTexture(); +#else + bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture(); +#endif + bool bDrewSomething = false; + if ( !bForceCheap && ( bReflection || bRefraction ) ) + { + bDrewSomething = true; + DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction ); + } + + // Use $decal to see if we are a decal or not. . if we are, then don't bother + // drawing the cheap version for now since we don't have access to env_cubemap +#ifdef _X360 + if( params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) && !bForceExpensive ) +#else + if( !bReflection && params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) +#endif + { + bDrewSomething = true; + DrawCheapWater( params, pShaderShadow, pShaderAPI, !bForceCheap, bRefraction ); + } + + if( !bDrewSomething ) + { + // We are likely here because of the tools. . . draw something so that + // we won't go into wireframe-land. + Draw(); + } + } +END_SHADER + +//----------------------------------------------------------------------------- +// This allows us to use a block labelled 'Water_DX9_HDR' in the water materials +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( Water_DX9_HDR, Water_DX90, + "Help for Water_DX9_HDR" ) + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "WATER_DX90"; + } + return 0; + } +END_INHERITED_SHADER + diff --git a/sp/src/materialsystem/stdshaders/water_dudv.cpp b/sp/src/materialsystem/stdshaders/water_dudv.cpp new file mode 100644 index 00000000..cf29c183 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water_dudv.cpp @@ -0,0 +1,95 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + + +#include "BaseVSShader.h" + +#include "waterdudv_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Water_DuDv, "Help for Water_DuDv" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "dudv bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + } + + SHADER_FALLBACK + { + return 0; + } + + SHADER_INIT + { + if ( params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + if( !params[REFRACTTINT]->IsDefined() ) + { + params[REFRACTTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + } + + SHADER_DRAW + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( true ); + pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0, 0 ); + + pShaderShadow->SetVertexShader( "WaterDuDv_vs11", 0 ); + pShaderShadow->SetPixelShader( "WaterDuDv_ps11", 0 ); + DisableFog(); + } + DYNAMIC_STATE + { + waterdudv_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + vshIndex.SetDOFOG( pShaderAPI->GetSceneFogMode() != MATERIAL_FOG_NONE ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + Vector4D vec; + const float *pTint = params[REFRACTTINT]->GetVecValue(); + float flAverage = ( pTint[0] + pTint[1] + pTint[2] ) / 3.0f; + vec.Init( flAverage, flAverage, flAverage, 1.0f ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, vec.Base() ); + + // Amount to refract + SetPixelShaderConstant( 0, REFRACTAMOUNT ); + + // Used to renormalize + vec.Init( 1.0f, 1.0f, 1.0f, 1.0f ); + pShaderAPI->SetPixelShaderConstant( 1, vec.Base() ); + + // Used to deal with the red channel + vec.Init( 0.0f, 1.0f, 1.0f, 1.0f ); + pShaderAPI->SetPixelShaderConstant( 2, vec.Base() ); + + vec.Init( 1.0f, 0.0f, 0.0f, 0.0f ); + pShaderAPI->SetPixelShaderConstant( 3, vec.Base() ); + + BindTexture( SHADER_TEXTURE_STAGE0, BUMPMAP, BUMPFRAME ); + } + Draw(); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/water_dx60.cpp b/sp/src/materialsystem/stdshaders/water_dx60.cpp new file mode 100644 index 00000000..b6c952b3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water_dx60.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// NOTE: Water DX60 is located in LightmappedGeneric_DX6 so it can inherit +DEFINE_FALLBACK_SHADER( Water, Water_DX60 ) + diff --git a/sp/src/materialsystem/stdshaders/water_dx80.cpp b/sp/src/materialsystem/stdshaders/water_dx80.cpp new file mode 100644 index 00000000..2f31bb5b --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water_dx80.cpp @@ -0,0 +1,419 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" + +#include "water_vs11.inc" +#include "watercheappervertexfresnel_vs11.inc" +#include "watercheap_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +BEGIN_VS_SHADER( Water_DX80, + "Help for Water_DX80" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "dudv bump map" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCALE]->IsDefined() ) + { + params[SCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[FORCEEXPENSIVE]->IsDefined() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + } + + SHADER_FALLBACK + { + if ( IsPC() && ( g_pHardwareConfig->GetDXSupportLevel() < 80 || !g_pHardwareConfig->HasProjectedBumpEnv() ) ) + { + return "Water_DX60"; + } + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE ); + } + if (params[BUMPMAP]->IsDefined() ) + { + LoadTexture( BUMPMAP ); + } + if (params[ENVMAP]->IsDefined() ) + { + LoadCubeMap( ENVMAP ); + } + if (params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + } + + inline void SetCheapWaterFactors( IMaterialVar **params, IShaderDynamicAPI* pShaderAPI, int nConstantReg ) + { + float flCheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float flCheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + float flCheapWaterConstants[4] = + { + flCheapWaterStartDistance, + 1.0f / ( flCheapWaterEndDistance - flCheapWaterStartDistance ), + 0.0f, + 0.0f + }; + pShaderAPI->SetVertexShaderConstant( nConstantReg, flCheapWaterConstants ); + } + + inline void DrawReflection( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlendReflection ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + if( bBlendReflection ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + + water_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WaterReflect_ps11", 0 ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + + float fReflectionAmount = params[REFLECTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fReflectionAmount, 0.0f, 0.0f, fReflectionAmount ); + + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER1, REFLECTTEXTURE, -1 ); + BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + pShaderAPI->SetVertexShaderIndex( 0 ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + // used to invert y + float c[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFLECTTINT ); + + water_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline void DrawRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + water_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WaterRefract_ps11", 0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount ); + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER1, REFRACTTEXTURE ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + + // used to invert y + float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFRACTTINT ); + + water_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline void DrawRefractionForFresnel( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI ) + { + SHADOW_STATE + { + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + water_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WaterRefractFresnel_ps11", 0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true ); + float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue(); + pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount ); + BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER1, REFRACTTEXTURE ); + BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + SetCheapWaterFactors( params, pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 ); + + // used to invert y + float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 ); + + SetPixelShaderConstant( 0, REFRACTTINT ); + + water_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bBlendFresnel, bool bNoPerVertexFresnel ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( bBlend ) + { + if ( bBlendFresnel ) + { + EnableAlphaBlending( SHADER_BLEND_DST_ALPHA, SHADER_BLEND_ONE_MINUS_DST_ALPHA ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + } + + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | + VERTEX_TANGENT_T, 1, 0, 0 ); + + if( bNoPerVertexFresnel ) + { + watercheap_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WaterCheap_vs11", vshIndex.GetIndex() ); + } + else + { + watercheappervertexfresnel_vs11_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WaterCheapPerVertexFresnel_vs11", vshIndex.GetIndex() ); + } + + static const char *s_pPixelShaderName[] = + { + "WaterCheapOpaque_ps11", + "WaterCheap_ps11", + "WaterCheapNoFresnelOpaque_ps11", + "WaterCheapNoFresnel_ps11", + }; + + int nPshIndex = 0; + if ( bBlend ) nPshIndex |= 0x1; + if ( bNoPerVertexFresnel ) nPshIndex |= 0x2; + pShaderShadow->SetPixelShader( s_pPixelShaderName[nPshIndex] ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, NORMALMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER3, ENVMAP, ENVMAPFRAME ); + + if( bBlend && !bBlendFresnel ) + { + SetCheapWaterFactors( params, pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_2 ); + } + else + { + float flCheapWaterConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, flCheapWaterConstants ); + } + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + SetPixelShaderConstant( 1, REFLECTTINT, REFLECTBLENDFACTOR ); + + if( bNoPerVertexFresnel ) + { + watercheap_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + else + { + watercheappervertexfresnel_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + } + Draw(); + } + + SHADER_DRAW + { + // NOTE: Here's what all this means. + // 1) ForceCheap means use env_cubemap only + // 2) ForceExpensive means do real reflection instead of env_cubemap. + // By default, it will do refraction and use env_cubemap for the reflection. + // If dest alpha is available, it will also use dest alpha for a fresnel term. + // otherwise there will be no fresnel term as it looks bizzare. + + bool bBlendReflection = false; + bool bForceCheap = params[FORCECHEAP]->GetIntValue() != 0 || UsingEditor( params ); + bool bForceExpensive = !bForceCheap && (params[FORCEEXPENSIVE]->GetIntValue() != 0); + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); + bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture(); + bool bReflectionUseFresnel = false; + + // Can't do fresnel when forcing cheap or if there's no refraction + if( !bForceCheap ) + { + if( bRefraction ) + { + // NOTE: Expensive reflection does the fresnel correctly per-pixel + if ( g_pHardwareConfig->HasDestAlphaBuffer() && !bReflection && !params[NOFRESNEL]->GetIntValue() ) + { + DrawRefractionForFresnel( params, pShaderShadow, pShaderAPI ); + bReflectionUseFresnel = true; + } + else + { + DrawRefraction( params, pShaderShadow, pShaderAPI ); + } + bBlendReflection = true; + } + if( bReflection ) + { + DrawReflection( params, pShaderShadow, pShaderAPI, bBlendReflection ); + } + } + + // Use $decal to see if we are a decal or not. . if we are, then don't bother + // drawing the cheap version for now since we don't have access to env_cubemap + if( !bReflection && params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) ) + { + bool bNoPerVertexFresnel = ( params[NOFRESNEL]->GetIntValue() || bReflectionUseFresnel || bForceCheap || !bRefraction ); + DrawCheapWater( params, pShaderShadow, pShaderAPI, bBlendReflection, bReflectionUseFresnel, bNoPerVertexFresnel ); + } + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/water_dx81.cpp b/sp/src/materialsystem/stdshaders/water_dx81.cpp new file mode 100644 index 00000000..764ffe9e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water_dx81.cpp @@ -0,0 +1,311 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "mathlib/vmatrix.h" + +#include "water_ps14.inc" +#include "watercheap_vs14.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( Water, Water_DX81 ) + +BEGIN_VS_SHADER( Water_DX81, + "Help for Water_DX81" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" ) + SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" ) + SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" ) + SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" ) + SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" ) + SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "", "normal map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" ) + SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" ) + SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." ) + SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" ) + SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" ) + SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" ) + SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" ) + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() ) + { + params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f ); + } + if( !params[CHEAPWATERENDDISTANCE]->IsDefined() ) + { + params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f ); + } + if( !params[SCALE]->IsDefined() ) + { + params[SCALE]->SetVecValue( 1.0f, 1.0f ); + } + if( !params[FOGCOLOR]->IsDefined() ) + { + params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f ); + Warning( "material %s needs to have a $fogcolor.\n", pMaterialName ); + } + if( !params[REFLECTENTITIES]->IsDefined() ) + { + params[REFLECTENTITIES]->SetIntValue( 0 ); + } + if( !params[FORCEEXPENSIVE]->IsDefined() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() ) + { + params[FORCEEXPENSIVE]->SetIntValue( 0 ); + } + if( !params[REFLECTBLENDFACTOR]->IsDefined() ) + { + params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f ); + } + if( !params[FORCEEXPENSIVE]->GetIntValue() && !params[ENVMAP]->IsDefined() ) + { + params[ENVMAP]->SetStringValue( "engine/defaultcubemap" ); + } + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 81 ) + { + return "Water_DX80"; + } + return 0; + } + + SHADER_INIT + { + Assert( params[WATERDEPTH]->IsDefined() ); + if( params[REFRACTTEXTURE]->IsDefined() ) + { + LoadTexture( REFRACTTEXTURE ); + } + if( params[REFLECTTEXTURE]->IsDefined() ) + { + LoadTexture( REFLECTTEXTURE ); + } + if (params[ENVMAP]->IsDefined() ) + { + LoadTexture( ENVMAP ); + } + if (params[NORMALMAP]->IsDefined() ) + { + LoadBumpMap( NORMALMAP ); + } + } + + inline int GetReflectionRefractionPixelShaderIndex( bool bReflection, bool bRefraction ) + { + // "REFLECT" "0..1" + // "REFRACT" "0..1" + int pshIndex = ( bReflection ? 1 : 0 ) | ( bRefraction ? 2 : 0 ); + return pshIndex; + } + + inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, bool bReflection, bool bRefraction ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if( bRefraction ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + if( bReflection ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T; + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + water_ps14_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "Water_ps14", vshIndex.GetIndex() ); + + int pshIndex = GetReflectionRefractionPixelShaderIndex( bReflection, bRefraction ); + pShaderShadow->SetPixelShader ( "Water_ps14", pshIndex ); + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_NORMALIZATION_CUBEMAP ); + if( bRefraction ) + { + BindTexture( SHADER_SAMPLER2, REFRACTTEXTURE, -1 ); + } + BindTexture( SHADER_SAMPLER3, NORMALMAP, BUMPFRAME ); + if( bReflection ) + { + BindTexture( SHADER_SAMPLER4, REFLECTTEXTURE, -1 ); + } + + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, REFLECTAMOUNT ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM ); + SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, REFRACTAMOUNT ); + + float c0[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 0, c0, 1 ); + + SetPixelShaderConstant( 1, REFRACTTINT ); + SetPixelShaderConstant( 4, REFLECTTINT ); + + float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f }; + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + // ERASE ME! + float c3[4] = { 5.0f, 0.0f, 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 3, c3, 1 ); + + // reflection/refraction scale + float reflectionRefractionScale[4] = { params[REFLECTAMOUNT]->GetFloatValue(), + params[REFRACTAMOUNT]->GetFloatValue(), 0.0f, 0.0f }; + pShaderAPI->SetPixelShaderConstant( 5, reflectionRefractionScale, 1 ); + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, reflectionRefractionScale, 1 ); + + water_ps14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + enum DrawCheapType_t + { + DRAW_CHEAP_OPAQUE = 0, + DRAW_CHEAP_FRESNEL_OPAQUE, + DRAW_CHEAP_LOD_ONLY, + DRAW_CHEAP_FRESNEL_AND_LOD, + }; + + inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow, + IShaderDynamicAPI* pShaderAPI, DrawCheapType_t type ) + { + SHADOW_STATE + { + SetInitialShadowState( ); + + // In edit mode, use nocull + if ( UsingEditor( params ) ) + { + s_pShaderShadow->EnableCulling( false ); + } + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + if ( (type != DRAW_CHEAP_OPAQUE) && (type != DRAW_CHEAP_FRESNEL_OPAQUE) ) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + pShaderShadow->VertexShaderVertexFormat( + VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | + VERTEX_TANGENT_T, 1, 0, 0 ); + + watercheap_vs14_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WaterCheap_vs14", vshIndex.GetIndex() ); + + static const char *s_pPixelShader[] = + { + "WaterCheapOpaque_ps14", + "WaterCheapFresnelOpaque_ps14", + "WaterCheap_ps14", + "WaterCheapFresnel_ps14", + }; + + pShaderShadow->SetPixelShader( s_pPixelShader[type] ); + FogToFogColor(); + } + DYNAMIC_STATE + { + pShaderAPI->SetDefaultState(); + BindTexture( SHADER_SAMPLER0, NORMALMAP, BUMPFRAME ); + BindTexture( SHADER_SAMPLER3, ENVMAP, ENVMAPFRAME ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALIZATION_CUBEMAP ); + + float pCheapWaterConstants[4] = { 0, 0, 0, 0 }; + if ( (type != DRAW_CHEAP_OPAQUE) && (type != DRAW_CHEAP_FRESNEL_OPAQUE) ) + { + float flCheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue(); + float flCheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue(); + pCheapWaterConstants[0] = flCheapWaterStartDistance; + pCheapWaterConstants[1] = 1.0f / ( flCheapWaterEndDistance - flCheapWaterStartDistance ); + } + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, pCheapWaterConstants ); + + SetPixelShaderConstant( 0, FOGCOLOR ); + SetPixelShaderConstant( 1, REFLECTTINT, REFLECTBLENDFACTOR ); + + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM ); + + watercheap_vs14_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + // NOTE: Here's what all this means. + // 1) ForceCheap means use env_cubemap only + // 2) ForceExpensive means do real reflection instead of env_cubemap. + // By default, it will do refraction and use env_cubemap for the reflection. + + // Also, it will fade to cheap water at a particular distance, + // based on CheapWaterStartDistance and CheapWaterEndDistance + // * In the ForceCheap case, no fading is required + // * In the default case, it will fade based on these parameters in a single pass + // * In the expensive case, it will have to perform the fade in a separate pass. + + bool bForceCheap = params[FORCECHEAP]->GetIntValue() != 0 || UsingEditor( params ); + bool bForceExpensive = params[FORCEEXPENSIVE]->GetIntValue() != 0; + bool bRefraction = params[REFRACTTEXTURE]->IsTexture(); + bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture(); + DrawCheapType_t type = params[NOFRESNEL]->GetIntValue() ? DRAW_CHEAP_OPAQUE : DRAW_CHEAP_FRESNEL_OPAQUE; + if( !bForceCheap && (bRefraction || bReflection) ) + { + DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction ); + if ( !bReflection ) + { + type = params[NOFRESNEL]->GetIntValue() ? DRAW_CHEAP_LOD_ONLY : DRAW_CHEAP_FRESNEL_AND_LOD; + } + else + { + type = DRAW_CHEAP_LOD_ONLY; + } + } + + // Use $decal to see if we are a decal or not. . if we are, then don't bother + // drawing the cheap version for now since we don't have access to env_cubemap + if( params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) && !bReflection ) + { + DrawCheapWater( params, pShaderShadow, pShaderAPI, type ); + } + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/water_ps2x.fxc b/sp/src/materialsystem/stdshaders/water_ps2x.fxc new file mode 100644 index 00000000..a80a8a15 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water_ps2x.fxc @@ -0,0 +1,110 @@ +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b] [= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "BASETEXTURE" "0..1" +// STATIC: "MULTITEXTURE" "0..1" +// STATIC: "REFLECT" "0..1" +// STATIC: "REFRACT" "0..1" +// STATIC: "ABOVEWATER" "0..1" +// STATIC: "BLURRY_REFRACT" "0..1" [ps20b] + +// When we turn NORMAL_DECODE_MODE on, this shader only needs 0..1, not 0..2 +// STATIC: "NORMAL_DECODE_MODE" "0..0" [XBOX] +// STATIC: "NORMAL_DECODE_MODE" "0..0" [PC] + +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] + +// SKIP: $MULTITEXTURE && $BASETEXTURE + +#if defined(SHADER_MODEL_PS_2_0) +# define BLURRY_REFRACT 0 +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + +#include "water_ps2x_helper.h" + + +sampler RefractSampler : register( s0 ); +#if BASETEXTURE +sampler BaseTextureSampler : register( s1 ); +#endif +sampler ReflectSampler : register( s2 ); +#if BASETEXTURE +sampler LightmapSampler : register( s3 ); +#endif +sampler NormalSampler : register( s4 ); + +const HALF4 vRefractTint : register( c1 ); +const HALF4 vReflectTint : register( c4 ); +const float4 g_ReflectRefractScale : register( c5 ); // xy - reflect scale, zw - refract scale +const HALF4 g_WaterFogColor : register( c6 ); +const HALF4 g_WaterFogParams : register( c7 ); + +const float4 g_PixelFogParams : register( c8 ); + + +#define g_WaterFogStart g_WaterFogParams.x +#define g_WaterFogEndMinusStart g_WaterFogParams.y +#define g_Reflect_OverBright g_WaterFogParams.z + +struct PS_INPUT +{ + float2 vBumpTexCoord : TEXCOORD0; + half3 vTangentEyeVect : TEXCOORD1; + float4 vReflectXY_vRefractYX : TEXCOORD2; + float W : TEXCOORD3; + float4 vProjPos : TEXCOORD4; + float screenCoord : TEXCOORD5; +#if MULTITEXTURE + float4 vExtraBumpTexCoord : TEXCOORD6; +#endif +#if BASETEXTURE +// CENTROID: TEXCOORD6 + HALF4 lightmapTexCoord1And2 : TEXCOORD6; +// CENTROID: TEXCOORD7 + HALF4 lightmapTexCoord3 : TEXCOORD7; +#endif + + float4 fogFactorW : COLOR1; +}; + +float4 main( PS_INPUT i ) : COLOR +{ + DrawWater_params_t params; + + params.vBumpTexCoord = i.vBumpTexCoord; +#if MULTITEXTURE + params.vExtraBumpTexCoord = i.vExtraBumpTexCoord; +#endif + params.vReflectXY_vRefractYX = i.vReflectXY_vRefractYX; + params.w = i.W; + params.vReflectRefractScale = g_ReflectRefractScale; + params.fReflectOverbright = g_Reflect_OverBright; + params.vReflectTint = vReflectTint; + params.vRefractTint = vRefractTint; + params.vTangentEyeVect = i.vTangentEyeVect; + params.waterFogColor = g_WaterFogColor; +#if BASETEXTURE + params.lightmapTexCoord1And2 = i.lightmapTexCoord1And2; + params.lightmapTexCoord3 = i.lightmapTexCoord3; +#endif + params.vProjPos = i.vProjPos; + params.pixelFogParams = g_PixelFogParams; + params.fWaterFogStart = g_WaterFogStart; + params.fWaterFogEndMinusStart = g_WaterFogEndMinusStart; + + float4 result; + float fogFactor; + DrawWater( params, + // yay. . can't put sampler in a struct. +#if BASETEXTURE + BaseTextureSampler, + LightmapSampler, +#endif + NormalSampler, RefractSampler, ReflectSampler, + result, fogFactor ); + + return FinalOutput( float4( result.rgb, 1.0f ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_NONE, (WRITE_DEPTH_TO_DESTALPHA != 0), i.vProjPos.z ); +} + diff --git a/sp/src/materialsystem/stdshaders/water_ps2x_helper.h b/sp/src/materialsystem/stdshaders/water_ps2x_helper.h new file mode 100644 index 00000000..b15b9986 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/water_ps2x_helper.h @@ -0,0 +1,239 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include "common_ps_fxc.h" + +struct DrawWater_params_t +{ + float2 vBumpTexCoord; +#if MULTITEXTURE + float4 vExtraBumpTexCoord; +#endif + float4 vReflectXY_vRefractYX; + float w; + float4 vReflectRefractScale; + float fReflectOverbright; + float4 vReflectTint; + float4 vRefractTint; + half3 vTangentEyeVect; + float4 waterFogColor; +#if BASETEXTURE + HALF4 lightmapTexCoord1And2; + HALF4 lightmapTexCoord3; +#endif + float4 vProjPos; + float4 pixelFogParams; + float fWaterFogStart; + float fWaterFogEndMinusStart; +}; + +void DrawWater( in DrawWater_params_t i, +#if BASETEXTURE + in sampler BaseTextureSampler, + in sampler LightmapSampler, +#endif + in sampler NormalSampler, + in sampler RefractSampler, + in sampler ReflectSampler, + out float4 result, out float fogFactor ) +{ + bool bReflect = REFLECT ? true : false; + bool bRefract = REFRACT ? true : false; + +#if MULTITEXTURE + float4 vNormal = tex2D( NormalSampler, i.vBumpTexCoord ); + float4 vNormal1 = tex2D( NormalSampler, i.vExtraBumpTexCoord.xy ); + float4 vNormal2 = tex2D( NormalSampler, i.vExtraBumpTexCoord.zw ); + vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 ); + +#if ( NORMAL_DECODE_MODE == NORM_DECODE_ATI2N ) + vNormal.xy = vNormal.xy * 2.0f - 1.0f; + vNormal.z = sqrt( 1.0f - dot(vNormal.xy, vNormal.xy) ); + vNormal.a = 1.0f; +#else + vNormal.xyz = 2.0 * vNormal.xyz - 1.0; +#endif + +#else + float4 vNormal = DecompressNormal( NormalSampler, i.vBumpTexCoord, NORMAL_DECODE_MODE ); +#endif + + // Perform division by W only once + float ooW = 1.0f / i.w; + + float2 unwarpedRefractTexCoord = i.vReflectXY_vRefractYX.wz * ooW; + +#if ABOVEWATER + float waterFogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a; +#else + // We don't actually have valid depth values in alpha when we are underwater looking out, so + // just set to farthest value. + float waterFogDepthValue = 1.0f; +#endif + float4 reflectRefractScale = i.vReflectRefractScale; +#if !BASETEXTURE +#if ( BLURRY_REFRACT == 0 ) + reflectRefractScale *= waterFogDepthValue; +#endif +#endif + + // Compute coordinates for sampling Reflection + float2 vReflectTexCoord; + float2 vRefractTexCoord; + + // vectorize the dependent UV calculations (reflect = .xy, refract = .wz) + float4 vN; + vN.xy = vNormal.xy; + vN.w = vNormal.x; + vN.z = vNormal.y; + float4 vDependentTexCoords = vN * vNormal.a * reflectRefractScale; + + vDependentTexCoords += ( i.vReflectXY_vRefractYX * ooW ); + vReflectTexCoord = vDependentTexCoords.xy; + vRefractTexCoord = vDependentTexCoords.wz; + + HALF4 vReflectColor = tex2D( ReflectSampler, vReflectTexCoord ); +#if BLURRY_REFRACT + // Sample reflection and refraction + float2 ddx1=float2(0.005,0); + float2 ddy1=float2(0,0.005); + float4 vRefractColor=float4(0,0,0,0); + +#if 0 + float sumweights=0; + for(int ix=-2;ix<=2;ix++) + { + for(int iy=-2;iy<=2;iy++) + { + float weight=1; ///(1+abs(ix)+abs(iy)); + vRefractColor += weight*tex2D( RefractSampler, vRefractTexCoord+ix*ddx1+iy*ddy1); + sumweights+=weight; + } + } +#else + // NOTE: Generated by genwaterloop.pl in the stdshaders directory. + // Need to unroll for 360 to avoid shader compilation problems. + // Modified genwaterloop.pl and regenerate if you need different params + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -2 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + -1 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 0 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 1 * ddx1 + 2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + -2 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + -1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 0 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 1 * ddy1 ); + vRefractColor += tex2D( RefractSampler, vRefractTexCoord + 2 * ddx1 + 2 * ddy1 ); + float sumweights = 25; + // NOTE: end of generated code. +#endif + + vRefractColor *= (1.0/sumweights); + vReflectColor *= i.fReflectOverbright; + vReflectColor *= i.vReflectTint; + vRefractColor *= i.vRefractTint; +# if ABOVEWATER + // Don't mess with this in the underwater case since we don't really have + // depth values there. + // get the blurred depth value to be used for fog. + waterFogDepthValue = vRefractColor.a; +# endif +#else + vReflectColor *= i.vReflectTint; + HALF4 vRefractColor = tex2D( RefractSampler, vRefractTexCoord ); + // get the depth value from the refracted sample to be used for fog. +# if ABOVEWATER + // Don't mess with this in the underwater case since we don't really have + // depth values there. + waterFogDepthValue = tex2D( RefractSampler, vRefractTexCoord ).a; +# endif +#endif + + half3 vEyeVect; + vEyeVect = normalize( i.vTangentEyeVect ); + + // Fresnel term + HALF fNdotV = saturate( dot( vEyeVect, vNormal ) ); + HALF fFresnel = pow( 1.0 - fNdotV, 5 ); + +#if !BASETEXTURE + // fFresnel == 1.0f means full reflection + fFresnel *= saturate( ( waterFogDepthValue - 0.05f ) * 20.0f ); +#endif + + + // blend between refraction and fog color. +#if ABOVEWATER + vRefractColor = lerp( vRefractColor, i.waterFogColor * LINEAR_LIGHT_SCALE, saturate( waterFogDepthValue - 0.05f ) ); +#else + float waterFogFactor = saturate( ( i.vProjPos.z - i.fWaterFogStart ) / i.fWaterFogEndMinusStart ); + vRefractColor = lerp( vRefractColor, i.waterFogColor * LINEAR_LIGHT_SCALE, waterFogFactor ); +#endif + +#if BASETEXTURE + float4 baseSample = tex2D( BaseTextureSampler, i.vBumpTexCoord.xy ); + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + HALF3 lightmapColor1 = lightmapSample1.rgb; + HALF3 lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + HALF3 lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + + float3 dp; + dp.x = saturate( dot( vNormal, bumpBasis[0] ) ); + dp.y = saturate( dot( vNormal, bumpBasis[1] ) ); + dp.z = saturate( dot( vNormal, bumpBasis[2] ) ); + dp *= dp; + + float3 diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) ); + diffuseLighting *= LIGHT_MAP_SCALE / sum; + HALF3 diffuseComponent = baseSample.rgb * diffuseLighting; +#endif + + if( bReflect && bRefract ) + { + result = lerp( vRefractColor, vReflectColor, fFresnel ); + } + else if( bReflect ) + { +#if BASETEXTURE + result = float4( diffuseComponent, 1.0f ) + vReflectColor * fFresnel * baseSample.a; +#else + result = vReflectColor; +#endif + } + else if( bRefract ) + { + result = vRefractColor; + } + else + { + result = float4( 0.0f, 0.0f, 0.0f, 0.0f ); + } + +#if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE) + fogFactor = CalcRangeFog( i.vProjPos.z, i.pixelFogParams.x, i.pixelFogParams.z, i.pixelFogParams.w ); +#else + fogFactor = 0; +#endif +} diff --git a/sp/src/materialsystem/stdshaders/waterreflect_ps14.psh b/sp/src/materialsystem/stdshaders/waterreflect_ps14.psh new file mode 100644 index 00000000..7104e45c --- /dev/null +++ b/sp/src/materialsystem/stdshaders/waterreflect_ps14.psh @@ -0,0 +1,8 @@ +ps.1.4 + +texld r0, t0_dw.xyw ; sample dudv map + +phase + +texld r0, t0 + diff --git a/sp/src/materialsystem/stdshaders/waterrefract_ps14.psh b/sp/src/materialsystem/stdshaders/waterrefract_ps14.psh new file mode 100644 index 00000000..5b5d1755 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/waterrefract_ps14.psh @@ -0,0 +1,23 @@ +ps.1.4 + +; non-fresnel version +; t0: +; texture: dudv map +; texcoords: coords for normal map +; t1: +; texcoords: uvw for first dp3 +; t2: +; texture: renderable texture that we are going to perturb +; texcoords: uvw for second dp3 +;tex t0 ; sample dudv map +;texm3x2pad t1, t0 ; +;texm3x2tex t2, t0 ; sample renderabletexture + +;mul r0, t2, c1 + + +texld r0, t0 ; sample dudv map + +phase + +texld r0, t2_dw.xyw diff --git a/sp/src/materialsystem/stdshaders/worldtwotextureblend.cpp b/sp/src/materialsystem/stdshaders/worldtwotextureblend.cpp new file mode 100644 index 00000000..542013e0 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldtwotextureblend.cpp @@ -0,0 +1,500 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//===========================================================================// + +#include "BaseVSShader.h" + +#include "convar.h" + +#include "lightmappedgeneric_vs20.inc" +#include "WorldTwoTextureBlend_ps20.inc" +#include "WorldTwoTextureBlend_ps20b.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern ConVar r_flashlight_version2; + +// FIXME: Need to make a dx9 version so that "CENTROID" works. +BEGIN_VS_SHADER( WorldTwoTextureBlend, + "Help for WorldTwoTextureBlend" ) + +BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) +END_SHADER_PARAMS + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "WorldTwoTextureBlend_DX6"; + + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "WorldTwoTextureBlend_DX8"; + + return 0; + } + + SHADER_INIT_PARAMS() + { + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + { + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + } + + if ( g_pHardwareConfig->SupportsBorderColor() ) + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" ); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + } + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() && params[ALBEDO]->IsDefined() && + params[BASETEXTURE]->IsDefined() && + !( params[NODIFFUSEBUMPLIGHTING]->IsDefined() && params[NODIFFUSEBUMPLIGHTING]->GetIntValue() ) ) + { + params[BASETEXTURE]->SetStringValue( params[ALBEDO]->GetStringValue() ); + } + + if( !params[NODIFFUSEBUMPLIGHTING]->IsDefined() ) + { + params[NODIFFUSEBUMPLIGHTING]->SetIntValue( 0 ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[DETAILFRAME]->IsDefined() ) + { + params[DETAILFRAME]->SetIntValue( 0 ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + } + + SHADER_INIT + { + if( g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined() ) + { + LoadBumpMap( BUMPMAP ); + } + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE, TEXTUREFLAGS_SRGB ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + LoadTexture( FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB ); + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + } + + // We always need this because of the flashlight. + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + + void DrawPass( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, + IShaderShadow* pShaderShadow, bool hasFlashlight, VertexCompressionType_t vertexCompression ) + { + bool hasBump = params[BUMPMAP]->IsTexture(); + bool hasDiffuseBumpmap = hasBump && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0); + bool hasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool hasDetailTexture = /*!hasBump && */params[DETAIL]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) != 0; + bool bHasDetailAlpha = params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() != 0; + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + + BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true ); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use + + bool bSeamlessMapping = params[SEAMLESS_SCALE]->GetFloatValue() != 0.0; + + SHADOW_STATE + { + int nShadowFilterMode = 0; + + // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState + pShaderShadow->EnableAlphaTest( bIsAlphaTested ); + if( hasFlashlight ) + { + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats + } + + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + pShaderShadow->EnableDepthWrites( false ); + + // Be sure not to write to dest alpha + pShaderShadow->EnableAlphaWrites( false ); + } + else + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + + unsigned int flags = VERTEX_POSITION; + if( hasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true ); + } + // if( hasLightmap ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ); + } + if( hasFlashlight ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); + pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 ); + flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL; + } + if( hasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + if( hasBump ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); + } + if( hasVertexColor ) + { + flags |= VERTEX_COLOR; + } + + // Normalizing cube map + pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); + + // texcoord0 : base texcoord + // texcoord1 : lightmap texcoord + // texcoord2 : lightmap texcoord offset + int numTexCoords = 2; + if( hasBump ) + { + numTexCoords = 3; + } + + pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 ); + + // Pre-cache pixel shaders + bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); + + pShaderShadow->EnableSRGBWrite( true ); + + DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, false ); + SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE, hasFlashlight ); + SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, false ); + SET_STATIC_VERTEX_SHADER_COMBO( RELIEF_MAPPING, 0 ); //( bumpmap_variant == 2 )?1:0); + SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); //( bumpmap_variant == 2 )?1:0); +#ifdef _X360 + SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); +#endif + SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture ); + SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP, hasBump ); + SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap ); + SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR, hasVertexColor ); + SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, hasSelfIllum ); + SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE, bHasDetailAlpha ); + SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight ); + SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); + SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + } + + // HACK HACK HACK - enable alpha writes all the time so that we have them for + // underwater stuff. + // But only do it if we're not using the alpha already for translucency + pShaderShadow->EnableAlphaWrites( bFullyOpaque ); + + + if( hasFlashlight ) + { + FogToBlack(); + } + else + { + DefaultFog(); + } + } + DYNAMIC_STATE + { + if( hasBaseTexture ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE ); + } + + // if( hasLightmap ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + } + + bool bFlashlightShadows = false; + if( hasFlashlight ) + { + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture ); + bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL ); + + SetFlashLightColorFromState( state, pShaderAPI ); + + BindTexture( SHADER_SAMPLER2, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame ); + + if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() ) + { + BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture ); + } + } + if( hasDetailTexture ) + { + BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME ); + } + if( hasBump ) + { + if( !g_pConfig->m_bFastNoBump ) + { + BindTexture( SHADER_SAMPLER4, BUMPMAP, BUMPFRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT ); + } + } + pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED ); + + // If we don't have a texture transform, we don't have + // to set vertex shader constants or run vertex shader instructions + // for the texture transform. + bool bHasTextureTransform = + !( params[BASETEXTURETRANSFORM]->MatrixIsIdentity() && + params[BUMPTRANSFORM]->MatrixIsIdentity() ); + + bool bVertexShaderFastPath = !bHasTextureTransform; + if( params[DETAIL]->IsTexture() ) + { + bVertexShaderFastPath = false; + } + if( pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0 ) + { + bVertexShaderFastPath = false; + } + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor( color ); + if( !( bVertexShaderFastPath && color[0] == 1.0f && color[1] == 1.0f && color[2] == 1.0f && color[3] == 1.0f ) ) + { + bVertexShaderFastPath = false; + s_pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color ); + if (! bSeamlessMapping) + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + if( hasBump && !bHasDetailAlpha ) + { + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BUMPTRANSFORM ); + Assert( !hasDetailTexture ); + } + } + + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH, bVertexShaderFastPath ); + SET_DYNAMIC_VERTEX_SHADER_COMBO( + LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0); + SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 ); + + bool bWriteDepthToAlpha; + bool bWriteWaterFogToAlpha; + if( bFullyOpaque ) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." ); + } + else + { + //can't write a special value to dest alpha if we're actually using as-intended alpha + bWriteDepthToAlpha = false; + bWriteWaterFogToAlpha = false; + } + + + if ( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + + // Don't write fog to alpha if we're using translucency + SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z) && + (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); + SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 ); + } + + + // always set the transform for detail textures since I'm assuming that you'll + // always have a detailscale. + if( hasDetailTexture ) + { + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, DETAILSCALE ); + Assert( !( hasBump && !bHasDetailAlpha ) ); + } + + SetPixelShaderConstantGammaToLinear( 7, SELFILLUMTINT ); + + float eyePos[4]; + pShaderAPI->GetWorldSpaceCameraPosition( eyePos ); + pShaderAPI->SetPixelShaderConstant( 10, eyePos, 1 ); + pShaderAPI->SetPixelShaderFogParams( 11 ); + + if ( bSeamlessMapping ) + { + float map_scale[4]={ params[SEAMLESS_SCALE]->GetFloatValue(),0,0,0}; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + } + + + if( hasFlashlight ) + { + VMatrix worldToTexture; + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture ); + + // Set the flashlight attenuation factors + float atten[4]; + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant( 20, atten, 1 ); + + // Set the flashlight origin + float pos[4]; + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pos[3] = 1.0f; + pShaderAPI->SetPixelShaderConstant( 15, pos, 1 ); + + pShaderAPI->SetPixelShaderConstant( 16, worldToTexture.Base(), 4 ); + } + } + Draw(); + } + + SHADER_DRAW + { + bool bHasFlashlight = UsingFlashlight( params ); + if ( bHasFlashlight && ( IsX360() || r_flashlight_version2.GetInt() ) ) + { + DrawPass( params, pShaderAPI, pShaderShadow, false, vertexCompression ); + SHADOW_STATE + { + SetInitialShadowState( ); + } + } + DrawPass( params, pShaderAPI, pShaderShadow, bHasFlashlight, vertexCompression ); + } + +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/worldtwotextureblend_dx6.cpp b/sp/src/materialsystem/stdshaders/worldtwotextureblend_dx6.cpp new file mode 100644 index 00000000..3ae6383a --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldtwotextureblend_dx6.cpp @@ -0,0 +1,258 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( WorldTwoTextureBlend, WorldTwoTextureBlend_DX6 ) + + +BEGIN_SHADER( WorldTwoTextureBlend_DX6, + "Help for WorldTwoTextureBlend" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + END_SHADER_PARAMS + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + LoadTexture( BASETEXTURE ); + LoadTexture( DETAIL ); + } + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + SHADER_DRAW + { + float detailScale = params[DETAILSCALE]->GetFloatValue(); + + bool hasFlashlight = UsingFlashlight( params ); + + if( hasFlashlight ) + { + DrawFlashlight_dx70( params, pShaderAPI, pShaderShadow, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + return; + } + + // DX6 fallback mode. + if ( params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() ) + { + DetailAlphaMaskPass1( pShaderShadow, pShaderAPI, params, detailScale ); + DetailAlphaMaskPass2( pShaderShadow, pShaderAPI, detailScale ); + } + else + { + // FIXME: add multitexture support! + NormalModePass1( pShaderShadow, pShaderAPI ); + NormalModePass2( pShaderShadow, pShaderAPI, params, detailScale ); + NormalModePass3( pShaderShadow, pShaderAPI, params, detailScale ); + } + } + + + // ------------------------------------------------------------------------------ // + // "Normal" mode - doesn't use the detail texture's alpha mask. + // ------------------------------------------------------------------------------ // + + void NormalModePass1( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + } + Draw(); + } + + void NormalModePass2( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, + IMaterialVar **params, + float detailScale ) + { + SHADOW_STATE + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableBlending( true ); + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + if ( detailScale != 1.0f ) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE0 ); + pShaderAPI->LoadIdentity(); + pShaderAPI->ScaleXY( detailScale, detailScale ); + } + BindTexture( SHADER_SAMPLER0, DETAIL ); + } + Draw(); + } + + void NormalModePass3( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, + IMaterialVar **params, + float detailScale ) + { + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + SingleTextureLightmapBlendMode(); + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + FogToOOOverbright(); + } + DYNAMIC_STATE + { + if ( detailScale != 1.0f ) + pShaderAPI->LoadIdentity( ); + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + Draw(); + } + + + // ------------------------------------------------------------------------------ // + // "Detail alpha mask mode". + // ------------------------------------------------------------------------------ // + + void DetailAlphaMaskPass1( + IShaderShadow *pShaderShadow, + IShaderDynamicAPI *pShaderAPI, + IMaterialVar **params, + float detailScale ) + { + // The equation is [B*Da + (1-Da)] * [D * L] + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Stage 0 + // Color = B*2 + // Note the 2x here.. we do 4x total in this shader and + // the first 2x is here. The second is in SingleTextureLightmapBlendMode in the 2nd pass. + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + // Stage 1 [where P = prev stage] + // Color = B*Da + (1-Da) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATEINVCOLOR_ADDALPHA, + SHADER_TEXARG_INVTEXTUREALPHA, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_TEXCOORD1 ); + FogToFogColor(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, DETAIL ); + + pShaderAPI->Color4f( 1, 1, 1, 1 ); + + if ( detailScale != 1.0f ) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE1 ); + pShaderAPI->LoadIdentity(); + pShaderAPI->ScaleXY( detailScale, detailScale ); + } + + } + Draw(); + } + + void DetailAlphaMaskPass2( IShaderShadow *pShaderShadow, IShaderDynamicAPI *pShaderAPI, float detailScale ) + { + SHADOW_STATE + { + s_pShaderShadow->EnableCustomPixelPipe( true ); + s_pShaderShadow->CustomTextureStages( 2 ); + + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true); + + // Make sure the texgen transform is applied to the texture coordinates and not to an auto-generated reflection vector or whatever. + s_pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_OBJECT_LINEAR ); + + // This turns on blending and does overbrighting if it's enabled. + SingleTextureLightmapBlendMode(); + + // Stage 0, color = D + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + // Stage 1, color = D*L + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_TEXTURE ); + + // Use the lightmap coordinates in both stages. + pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_LIGHTMAP_TEXCOORD1 ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER0, DETAIL); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( detailScale != 1.0f ) + { + pShaderAPI->MatrixMode( MATERIAL_TEXTURE1 ); + pShaderAPI->LoadIdentity(); + + pShaderAPI->MatrixMode( MATERIAL_TEXTURE0 ); + pShaderAPI->LoadIdentity(); + pShaderAPI->ScaleXY( detailScale, detailScale ); + } + } + + Draw(); + } + +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/worldtwotextureblend_dx8.cpp b/sp/src/materialsystem/stdshaders/worldtwotextureblend_dx8.cpp new file mode 100644 index 00000000..a58d9dfb --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldtwotextureblend_dx8.cpp @@ -0,0 +1,175 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "lightmappedgeneric_vs11.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +DEFINE_FALLBACK_SHADER( WorldTwoTextureBlend, WorldTwoTextureBlend_DX8 ) + +BEGIN_VS_SHADER( WorldTwoTextureBlend_DX8, + "Help for WorldTwoTextureBlend_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM_OVERRIDE( BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend", "iris texture", 0 ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/WorldTwoTextureBlend_detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "1.0", "scale of the detail texture" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + END_SHADER_PARAMS + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80 ) + return "WorldTwoTextureBlend_DX6"; + + return 0; + } + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + } + + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->IsDefined() ) + { + params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->SetIntValue( 0 ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + + const char *GetPixelShaderName( IMaterialVar** params, bool bHasBaseTexture, bool bHasDetailTexture ) + { + bool bSelfIllum = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM); + if ( !bHasBaseTexture ) + { + if ( !bHasDetailTexture ) + return "LightmappedGeneric_NoTexture"; + + return "LightmappedGeneric_DetailNoTexture"; + } + + if ( !bHasDetailTexture ) + { + if ( bSelfIllum ) + return "LightmappedGeneric_SelfIlluminated"; + + return "LightmappedGeneric"; + } + + if ( !params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() ) + { + if ( bSelfIllum ) + return "WorldTwoTextureBlend_SelfIlluminated"; + + return "WorldTwoTextureBlend"; + } + + return "WorldTwoTextureBlend_DetailAlpha"; + } + + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, false, -1, -1, -1, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + return; + } + + bool bHasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool bHasDetailTexture = params[DETAIL]->IsTexture(); + bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + + SHADOW_STATE + { + if ( bHasBaseTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + if ( bHasDetailTexture ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + } + pShaderShadow->EnableBlending( false ); + + pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 2, 0, 0 ); + + // Let the shaders do the fun stuff. + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( bHasDetailTexture ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( bHasVertexColor ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pPixelShaderName = GetPixelShaderName( params, bHasBaseTexture, bHasDetailTexture ); + pShaderShadow->SetPixelShader( pPixelShaderName ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + if ( bHasBaseTexture ) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( bHasDetailTexture ) + { + BindTexture( SHADER_SAMPLER2, DETAIL ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + } + + SetModulationVertexShaderDynamicState(); + + // Dynamic vertex shader index. + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + } + Draw(); + } + +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc b/sp/src/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc new file mode 100644 index 00000000..b81fa7bd --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldtwotextureblend_ps2x.fxc @@ -0,0 +1,217 @@ +//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// STATIC: "CONVERT_TO_SRGB" "0..1" [ps20b][= g_pHardwareConfig->NeedsShaderSRGBConversion()] [PC] +// STATIC: "CONVERT_TO_SRGB" "0..0" [= 0] [XBOX] +// STATIC: "DETAILTEXTURE" "0..1" +// STATIC: "BUMPMAP" "0..1" +// STATIC: "VERTEXCOLOR" "0..1" +// STATIC: "SELFILLUM" "0..1" +// STATIC: "DIFFUSEBUMPMAP" "0..1" +// STATIC: "DETAIL_ALPHA_MASK_BASE_TEXTURE" "0..1" +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "SEAMLESS" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b] [PC] +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [XBOX] + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [PC] +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [XBOX] +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] + +// SKIP: $DETAILTEXTURE && ( $BUMPMAP && !$DETAIL_ALPHA_MASK_BASE_TEXTURE ) +// SKIP: !$BUMPMAP && $DIFFUSEBUMPMAP +// SKIP: $VERTEXCOLOR && $BUMPMAP +// SKIP: FLASHLIGHT && $SELFILLUM +// SKIP: FLASHLIGHT && $DETAIL_ALPHA_MASK_BASE_TEXTURE +// SKIP: FLASHLIGHT && ($BUMPMAP || $DIFFUSEBUMPMAP) + +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) [ps20b] + +#if defined( SHADER_MODEL_PS_2_0 ) +# define WRITE_DEPTH_TO_DESTALPHA 0 +#endif + + +#define HDRTYPE HDR_TYPE_NONE +#include "common_flashlight_fxc.h" +#include "common_ps_fxc.h" + +const HALF4 g_SelfIllumTint : register( c7 ); +static const HALF g_OverbrightFactor = 2.0f; + +const HALF3 g_EyePos : register( c10 ); +const HALF4 g_FogParams : register( c11 ); + +const HALF3 g_FlashlightPos : register( c15 ); +// flashlightfixme: Move this math into the vertex shader. +const float4x4 g_FlashlightWorldToTexture : register( c16 ); + +const float4 g_FlashlightAttenuationFactors : register( c20 ); + +sampler BaseTextureSampler : register( s0 ); +sampler LightmapSampler : register( s1 ); +sampler FlashlightSampler : register( s2 ); +sampler DetailSampler : register( s3 ); +sampler BumpmapSampler : register( s4 ); +sampler NormalizeSampler : register( s6 ); + +struct PS_INPUT +{ + HALF2 baseTexCoord : TEXCOORD0; + HALF4 detailOrBumpTexCoord : TEXCOORD1; + HALF4 lightmapTexCoord1And2 : TEXCOORD2; // CENTROID: TEXCOORD2 + HALF2 lightmapTexCoord3 : TEXCOORD3; // CENTROID: TEXCOORD3 + HALF4 worldPos_projPosZ : TEXCOORD4; + HALF3x3 tangentSpaceTranspose : TEXCOORD5; + // tangentSpaceTranspose : TEXCOORD6; + // tangentSpaceTranspose : TEXCOORD7; + HALF4 vertexColor : COLOR; +}; + + +float4 main( PS_INPUT i ) : COLOR +{ + bool bDetailTexture = DETAILTEXTURE ? true : false; + bool bBumpmap = BUMPMAP ? true : false; + bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false; + bool bVertexColor = VERTEXCOLOR ? true : false; + bool bSelfIllum = SELFILLUM ? true : false; + bool bDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE ? true : false; + bool bFlashlight = FLASHLIGHT ? true : false; + + HALF3 lightmapColor1 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor2 = HALF3( 1.0f, 1.0f, 1.0f ); + HALF3 lightmapColor3 = HALF3( 1.0f, 1.0f, 1.0f ); + if( bBumpmap && bDiffuseBumpmap ) + { + HALF2 bumpCoord1; + HALF2 bumpCoord2; + HALF2 bumpCoord3; + ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3 ); + + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + lightmapColor1 = lightmapSample1.rgb; + lightmapColor2 = tex2D( LightmapSampler, bumpCoord2 ); + lightmapColor3 = tex2D( LightmapSampler, bumpCoord3 ); + } + else + { + if( !bFlashlight ) + { + HALF2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy ); + HALF4 lightmapSample1 = tex2D( LightmapSampler, bumpCoord1 ); + lightmapColor1 = lightmapSample1.rgb; + } + } + + HALF4 detailColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + if( bDetailTexture ) + { + detailColor = tex2D( DetailSampler, i.detailOrBumpTexCoord.xy ); + } + + HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f ); + baseColor = tex2D( BaseTextureSampler, i.baseTexCoord ); + if ( bDetailAlphaMaskBaseTexture ) + { + // This is what WorldTwoTextureBlend_DX6 does. + baseColor.rgb = saturate( saturate( baseColor * 2 ) * detailColor.a + (1 - detailColor.a) ); + baseColor.rgb *= detailColor; + } + else + { + baseColor.rgb = lerp( baseColor, detailColor, detailColor.a ); + } + + HALF3 normal = HALF3( 0.0f, 0.0f, 1.0f ); + if( bBumpmap ) + { + HALF3 normalTexel; + normalTexel = tex2D( BumpmapSampler, i.detailOrBumpTexCoord.xy ); + normal = 2.0 * normalTexel - 1.0; + } + + HALF3 albedo = HALF3( 1.0f, 1.0f, 1.0f ); + HALF alpha = 1.0f; + albedo *= baseColor; + if( !bSelfIllum ) + { + alpha *= baseColor.a; + } + + // The vertex color contains the modulation color + vertex color combined + albedo *= i.vertexColor; + alpha *= i.vertexColor.a; // not sure about this one + + HALF3 diffuseLighting; + if( bFlashlight ) + { + float3 worldSpaceNormal; + // Make the unbumped version not so fucking stupid and not need tangentSpaceTranspose you knob. + worldSpaceNormal = mul( normal, i.tangentSpaceTranspose ); + + int nShadowSampleLevel = 0; + bool bDoShadows = false; +// On ps_2_b, we can do shadow mapping +#if ( FLASHLIGHTSHADOWS && (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0) ) ) + nShadowSampleLevel = FLASHLIGHTDEPTHFILTERMODE; + bDoShadows = true; +#endif + float4 flashlightSpacePosition = mul( float4( i.worldPos_projPosZ.xyz, 1.0f ), g_FlashlightWorldToTexture ); + + diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, flashlightSpacePosition, + worldSpaceNormal, g_FlashlightAttenuationFactors.xyz, + g_FlashlightAttenuationFactors.w, FlashlightSampler, FlashlightSampler, NormalizeSampler, + nShadowSampleLevel, bDoShadows, false, float2(0, 0), false ); + } + else + { + if( bBumpmap && bDiffuseBumpmap ) + { + float dot1 = saturate( dot( normal, bumpBasis[0] ) ); + float dot2 = saturate( dot( normal, bumpBasis[1] ) ); + float dot3 = saturate( dot( normal, bumpBasis[2] ) ); + + float sum = dot1 + dot2 + dot3; + diffuseLighting = dot1 * lightmapColor1 + + dot2 * lightmapColor2 + + dot3 * lightmapColor3; + diffuseLighting *= 1.0f / sum; + } + else + { + diffuseLighting = lightmapColor1; + } + + // Only scale here since the flashlight will already be scaled properly + diffuseLighting *= g_OverbrightFactor; + } + + HALF3 diffuseComponent = albedo * diffuseLighting; + + if( bSelfIllum ) + { + HALF3 selfIllumComponent = g_SelfIllumTint * albedo; + diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a ); + } + + HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f ); + HALF3 result = diffuseComponent + specularLighting; + + float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w ); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#endif + + return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, (WRITE_DEPTH_TO_DESTALPHA != 0), i.worldPos_projPosZ.w ); +} + diff --git a/sp/src/materialsystem/stdshaders/worldvertexalpha.cpp b/sp/src/materialsystem/stdshaders/worldvertexalpha.cpp new file mode 100644 index 00000000..85bad1c1 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertexalpha.cpp @@ -0,0 +1,259 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "WorldVertexAlpha.inc" +#include "worldvertexalpha_ps20.inc" +#include "worldvertexalpha_ps20b.inc" + +BEGIN_VS_SHADER( WorldVertexAlpha, + "Help for WorldVertexAlpha" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + SET_FLAGS2( MATERIAL_VAR2_BLEND_WITH_LIGHTMAP_ALPHA ); + } + SHADER_INIT + { + // Load the base texture here! + LoadTexture( BASETEXTURE ); + } + + SHADER_FALLBACK + { +// if( g_pHardwareConfig->GetDXSupportLevel() < 90 || g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) + { + return "WorldVertexAlpha_DX8"; + } + return 0; + } + + SHADER_DRAW + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() && !UsingEditor( params ) ) + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + { + // NOTE: This is the DX8, Non-Hammer version. + + SHADOW_STATE + { + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WorldVertexAlpha" ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + Draw(); + } + else + { + // DX 9 version with HDR support + + // Pass 1 + SHADOW_STATE + { + SetInitialShadowState(); + + pShaderShadow->EnableAlphaWrites( true ); + + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ZERO, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 0 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 0 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + } + Draw(); + + // Pass 2 + SHADOW_STATE + { + SetInitialShadowState(); + + pShaderShadow->EnableAlphaWrites( true ); + pShaderShadow->EnableColorWrites( false ); + + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + pShaderShadow->EnableBlendingSeparateAlpha( true ); + pShaderShadow->BlendFuncSeparateAlpha( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 1 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_STATIC_PIXEL_SHADER_COMBO( PASS, 1 ); + SET_STATIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + + if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20b ); + } + else + { + DECLARE_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + SET_DYNAMIC_PIXEL_SHADER( worldvertexalpha_ps20 ); + } + } + Draw(); + } + } + else + { + // NOTE: This is the DX7, Hammer version. + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); +// pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + // Use vertex color for Hammer because it puts the blending alpha in the vertices. + unsigned int colorFlag = 0; + if( UsingEditor( params ) ) + { + colorFlag |= SHADER_DRAW_COLOR; + } + + pShaderShadow->DrawFlags( colorFlag | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | + SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + + Draw(); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/worldvertexalpha_dx8.cpp b/sp/src/materialsystem/stdshaders/worldvertexalpha_dx8.cpp new file mode 100644 index 00000000..0ea139ee --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertexalpha_dx8.cpp @@ -0,0 +1,113 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + +#include "worldvertexalpha.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WorldVertexAlpha, WorldVertexAlpha_DX8 ) + +BEGIN_VS_SHADER( WorldVertexAlpha_DX8, + "Help for WorldVertexAlpha_DX8" ) + + BEGIN_SHADER_PARAMS + END_SHADER_PARAMS + + SHADER_INIT_PARAMS() + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + } + SHADER_INIT + { + // Load the base texture here! + LoadTexture( BASETEXTURE ); + } + + SHADER_DRAW + { + if( g_pHardwareConfig->SupportsVertexAndPixelShaders() && !UsingEditor( params ) ) + { + // NOTE: This is the DX8, Non-Hammer version. + + SHADOW_STATE + { + // Base time lightmap (Need two texture stages) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + worldvertexalpha_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexAlpha", vshIndex.GetIndex() ); + + pShaderShadow->SetPixelShader( "WorldVertexAlpha" ); + FogToFogColor(); + } + + DYNAMIC_STATE + { + // Bind the base texture (Stage0) and lightmap (Stage1) + BindTexture( SHADER_SAMPLER0, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + EnablePixelShaderOverbright( 0, true, true ); + + worldvertexalpha_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + + Draw(); + } + else + { + // NOTE: This is the DX7, Hammer version. + // FIXME: Gary - you need to write a proper non-fixed function shader for this. + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->EnableBlending( true ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); +// pShaderShadow->BlendFunc( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); + + // Use vertex color for Hammer because it puts the blending alpha in the vertices. + unsigned int colorFlag = 0; + if( UsingEditor( params ) ) + { + colorFlag |= SHADER_DRAW_COLOR; + } + + pShaderShadow->DrawFlags( colorFlag | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | + SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + + Draw(); + } + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition.cpp b/sp/src/materialsystem/stdshaders/worldvertextransition.cpp new file mode 100644 index 00000000..e7d6a9ab --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertextransition.cpp @@ -0,0 +1,157 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" +#include "convar.h" + +#include "worldvertextransition_dx8_helper.h" +#include "lightmappedgeneric_dx9_helper.h" + +static LightmappedGeneric_DX9_Vars_t s_info; + + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX9 ) + +BEGIN_VS_SHADER( WorldVertexTransition_DX9, "Help for WorldVertexTransition" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $detail" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + + // detail (multi-) texturing + SHADER_PARAM( DETAILBLENDMODE, SHADER_PARAM_TYPE_INTEGER, "0", "mode for combining detail texture with base. 0=normal, 1= additive, 2=alpha blend detail over base, 3=crossfade" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "blend amount for detail texture." ) + SHADER_PARAM( DETAILTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "detail texture tint" ) + + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$envmapmask texcoord transform" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_INTEGER, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( BUMPMAP2, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader3_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM2, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( BUMPMASK, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( FRAME2, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $basetexture2" ) + SHADER_PARAM( BASETEXTURENOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( BASETEXTURE2NOENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" ) + SHADER_PARAM( DETAIL_ALPHA_MASK_BASE_TEXTURE, SHADER_PARAM_TYPE_BOOL, "0", + "If this is 1, then when detail alpha=0, no base texture is blended and when " + "detail alpha=1, you get detail*base*lightmap" ) + SHADER_PARAM( LIGHTWARPTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "light munging lookup texture" ) + SHADER_PARAM( BLENDMODULATETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "texture to use r/g channels for blend range for" ) + SHADER_PARAM( BLENDMASKTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$blendmodulatetexture texcoord transform" ) + SHADER_PARAM( MASKEDBLENDING, SHADER_PARAM_TYPE_INTEGER, "0", "blend using texture with no vertex alpha. For using texture blending on non-displacements" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + END_SHADER_PARAMS + + void SetupVars( WorldVertexTransitionEditor_DX8_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTextureTransformVar = BASETEXTURETRANSFORM; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nBaseTexture2FrameVar = FRAME2; + info.m_nBaseTexture2TransformVar = BASETEXTURETRANSFORM; // FIXME!!!! + } + + void SetupVars( LightmappedGeneric_DX9_Vars_t& info ) + { + info.m_nBaseTexture = BASETEXTURE; + info.m_nBaseTextureFrame = FRAME; + info.m_nBaseTextureTransform = BASETEXTURETRANSFORM; + info.m_nAlbedo = ALBEDO; + info.m_nSelfIllumTint = SELFILLUMTINT; + + info.m_nDetail = DETAIL; + info.m_nDetailFrame = DETAILFRAME; + info.m_nDetailScale = DETAILSCALE; + info.m_nDetailTextureCombineMode = DETAILBLENDMODE; + info.m_nDetailTextureBlendFactor = DETAILBLENDFACTOR; + info.m_nDetailTint = DETAILTINT; + + info.m_nEnvmap = ENVMAP; + info.m_nEnvmapFrame = ENVMAPFRAME; + info.m_nEnvmapMask = ENVMAPMASK; + info.m_nEnvmapMaskFrame = ENVMAPMASKFRAME; + info.m_nEnvmapMaskTransform = ENVMAPMASKTRANSFORM; + info.m_nEnvmapTint = ENVMAPTINT; + info.m_nBumpmap = BUMPMAP; + info.m_nBumpFrame = BUMPFRAME; + info.m_nBumpTransform = BUMPTRANSFORM; + info.m_nEnvmapContrast = ENVMAPCONTRAST; + info.m_nEnvmapSaturation = ENVMAPSATURATION; + info.m_nFresnelReflection = FRESNELREFLECTION; + info.m_nNoDiffuseBumpLighting = NODIFFUSEBUMPLIGHTING; + info.m_nBumpmap2 = BUMPMAP2; + info.m_nBumpFrame2 = BUMPFRAME2; + info.m_nBaseTexture2 = BASETEXTURE2; + info.m_nBaseTexture2Frame = FRAME2; + info.m_nBumpTransform2 = BUMPTRANSFORM2; + info.m_nBumpMask = BUMPMASK; + info.m_nBaseTextureNoEnvmap = BASETEXTURENOENVMAP; + info.m_nBaseTexture2NoEnvmap = BASETEXTURE2NOENVMAP; + info.m_nDetailAlphaMaskBaseTexture = DETAIL_ALPHA_MASK_BASE_TEXTURE; + info.m_nFlashlightTexture = FLASHLIGHTTEXTURE; + info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.m_nLightWarpTexture = LIGHTWARPTEXTURE; + info.m_nBlendModulateTexture = BLENDMODULATETEXTURE; + info.m_nBlendMaskTransform = BLENDMASKTRANSFORM; + info.m_nMaskedBlending = MASKEDBLENDING; + info.m_nSelfShadowedBumpFlag = SSBUMP; + info.m_nSeamlessMappingScale = SEAMLESS_SCALE; + info.m_nAlphaTestReference = -1; + } + + SHADER_FALLBACK + { + if( g_pHardwareConfig->GetDXSupportLevel() < 90 ) + return "WorldVertexTransition_DX8"; + + return 0; + } + + SHADER_INIT_PARAMS() + { + SetupVars( s_info ); + InitParamsLightmappedGeneric_DX9( this, params, pMaterialName, s_info ); + } + + SHADER_INIT + { + SetupVars( s_info ); + InitLightmappedGeneric_DX9( this, params, s_info ); + } + + SHADER_DRAW + { + if ( UsingEditor( params ) ) + { + WorldVertexTransitionEditor_DX8_Vars_t info; + SetupVars( info ); + DrawWorldVertexTransitionEditor_DX8( this, params, pShaderAPI, pShaderShadow, info ); + return; + } + + DrawLightmappedGeneric_DX9( this, params, pShaderAPI, pShaderShadow, s_info, pContextDataPtr ); + } +END_SHADER + diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition_dx6.cpp b/sp/src/materialsystem/stdshaders/worldvertextransition_dx6.cpp new file mode 100644 index 00000000..163291e3 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertextransition_dx6.cpp @@ -0,0 +1,52 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "shaderlib/cshader.h" + +#include "worldvertextransition_dx6_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DEFINE_FALLBACK_SHADER( WorldVertexTransition, WorldVertexTransition_DX6 ) + +BEGIN_SHADER( WorldVertexTransition_DX6, + "Help for WorldVertexTransition_dx6" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( BASETEXTURE2, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture2", "base texture2 help" ) + END_SHADER_PARAMS + + void SetupVars( WorldVertexTransition_DX6_Vars_t& info ) + { + info.m_nBaseTextureVar = BASETEXTURE; + info.m_nBaseTextureFrameVar = FRAME; + info.m_nBaseTexture2Var = BASETEXTURE2; + info.m_nFlashlightTextureVar = FLASHLIGHTTEXTURE; + } + + SHADER_INIT_PARAMS() + { + WorldVertexTransition_DX6_Vars_t info; + SetupVars( info ); + InitParamsWorldVertexTransition_DX6( params, info ); + } + + SHADER_INIT + { + WorldVertexTransition_DX6_Vars_t info; + SetupVars( info ); + InitWorldVertexTransition_DX6( this, params, info ); + } + + SHADER_DRAW + { + WorldVertexTransition_DX6_Vars_t info; + SetupVars( info ); + DrawWorldVertexTransition_DX6( this, params, pShaderAPI, pShaderShadow, info ); + } +END_SHADER diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.cpp b/sp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.cpp new file mode 100644 index 00000000..7539ff29 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.cpp @@ -0,0 +1,206 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "shaderlib/cshader.h" +#include "worldvertextransition_dx6_helper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +void InitParamsWorldVertexTransition_DX6( IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + // FLASHLIGHTFIXME + params[info.m_nFlashlightTextureVar]->SetStringValue( "effects/flashlight001" ); +} + +void InitWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ) +{ + // FLASHLIGHTFIXME + if ( params[info.m_nFlashlightTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nFlashlightTextureVar ); + } + + if ( params[info.m_nBaseTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTextureVar ); + } + + if ( params[info.m_nBaseTexture2Var]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2Var ); + } +} + +static void DrawFlashlightPass( CBaseShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, int nPass, WorldVertexTransition_DX6_Vars_t &info ) +{ + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + pShaderShadow->SetDiffuseMaterialSource( SHADER_MATERIALSOURCE_COLOR1 ); + if( nPass == 0 ) + { + pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_ONE ); + } + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_COLOR | SHADER_DRAW_NORMAL; + pShaderShadow->DrawFlags( flags ); + pShader->FogToBlack(); + + pShaderShadow->EnableLighting( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // color stage 0 + // projected texture * vertex color (lighting) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + // color stage 1 + // * base texture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + // alpha stage 0 + // get alpha from constant alpha * vertex color + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_VERTEXCOLOR ); + + // alpha stage 1 + // get alpha from $basetexture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Shove the view position into texcoord 0 before the texture matrix. + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + } + DYNAMIC_STATE + { + pShader->SetFlashlightFixedFunctionTextureTransform( MATERIAL_TEXTURE0 ); + + // NOTE: This has to come after the loadmatrix since the loadmatrix screws with the + // transform flags!!!!!! + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 3, true ); + + pShader->BindTexture( SHADER_SAMPLER0, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME ); + if( nPass == 0 ) + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var, -1 ); + } + else + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTextureVar, info.m_nBaseTextureFrameVar ); + } + } + pShader->Draw(); +} + + +void DrawWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransition_DX6_Vars_t &info ) +{ + bool bHasFlashlight = pShader->UsingFlashlight( params ); + if( bHasFlashlight ) + { + DrawFlashlightPass( pShader, params, pShaderAPI, pShaderShadow, 0, info ); + DrawFlashlightPass( pShader, params, pShaderAPI, pShaderShadow, 1, info ); + return; + } + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, OVERBRIGHT ); + + pShaderShadow->DrawFlags( SHADER_DRAW_COLOR | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + //pShaderAPI->TexMinFilter( SHADER_TEXFILTERMODE_NEAREST ); + //pShaderAPI->TexMagFilter( SHADER_TEXFILTERMODE_NEAREST ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTextureVar ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + pShader->Draw(); + + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableBlending( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // alpha and color stage 0 + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_TEXTURE ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_TEXTURE ); + + // alpha and color stage 1 + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE2X, + SHADER_TEXARG_PREVIOUSSTAGE, + SHADER_TEXARG_TEXTURE ); + + // Looks backwards, but this is done so that lightmap alpha = 1 when only + // using 1 texture (needed for translucent displacements). + pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + pShaderShadow->DrawFlags( SHADER_DRAW_COLOR | SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_LIGHTMAP_TEXCOORD0 ); + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_LIGHTMAP ); + } + pShader->Draw(); +} diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.h b/sp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.h new file mode 100644 index 00000000..16e0bfd5 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertextransition_dx6_helper.h @@ -0,0 +1,39 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef WORLDVERTEXTRANSITION_DX6_HELPER_H +#define WORLDVERTEXTRANSITION_DX6_HELPER_H + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct WorldVertexTransition_DX6_Vars_t +{ + WorldVertexTransition_DX6_Vars_t() { memset( this, 0xFF, sizeof(WorldVertexTransition_DX6_Vars_t) ); } + + int m_nBaseTextureVar; + int m_nBaseTextureFrameVar; + int m_nBaseTexture2Var; + int m_nFlashlightTextureVar; +}; + +void InitParamsWorldVertexTransition_DX6( IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ); +void InitWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, WorldVertexTransition_DX6_Vars_t &info ); +void DrawWorldVertexTransition_DX6( CBaseShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransition_DX6_Vars_t &info ); + + +#endif // WORLDVERTEXTRANSITION_DX6_HELPER_H \ No newline at end of file diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp b/sp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp new file mode 100644 index 00000000..6a49fd71 --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.cpp @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "worldvertextransition_dx8_helper.h" +#include "BaseVSShader.h" + +#include "WorldVertexTransition.inc" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +void InitParamsWorldVertexTransitionEditor_DX8( IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); +} + +void InitWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + if ( params[info.m_nBaseTextureVar]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTextureVar ); + } + + if ( params[info.m_nBaseTexture2Var]->IsDefined() ) + { + pShader->LoadTexture( info.m_nBaseTexture2Var ); + } +} + +void DrawWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransitionEditor_DX8_Vars_t &info ) +{ + SHADOW_STATE + { + // This is the dx8 worldcraft version (non-bumped always.. too bad) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION | VERTEX_COLOR; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition", vshIndex.GetIndex() ); + pShaderShadow->SetPixelShader( "WorldVertexTransition_Editor" ); + + pShader->FogToFogColor(); + } + DYNAMIC_STATE + { + pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTextureVar, info.m_nBaseTextureFrameVar ); + pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture2Var, info.m_nBaseTexture2FrameVar ); + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_LIGHTMAP ); + + pShader->EnablePixelShaderOverbright( 0, true, true ); + + // JasonM - Gnarly hack since we're calling this legacy shader from DX9 + int nTextureTransformConst = VERTEX_SHADER_SHADER_SPECIFIC_CONST_0; + int nTextureTransformConst2 = VERTEX_SHADER_SHADER_SPECIFIC_CONST_2; + if ( g_pHardwareConfig->GetDXSupportLevel() >= 90) + { + nTextureTransformConst -= 10; + nTextureTransformConst2 -= 10; + } + + pShader->SetVertexShaderTextureTransform( nTextureTransformConst, info.m_nBaseTextureTransformVar ); + pShader->SetVertexShaderTextureTransform( nTextureTransformConst2, info.m_nBaseTexture2TransformVar ); + + worldvertextransition_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + pShader->Draw(); +} diff --git a/sp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.h b/sp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.h new file mode 100644 index 00000000..d17d532e --- /dev/null +++ b/sp/src/materialsystem/stdshaders/worldvertextransition_dx8_helper.h @@ -0,0 +1,44 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef WORLDVERTEXTRANSITION_DX8_HELPER_H +#define WORLDVERTEXTRANSITION_DX8_HELPER_H + +#include + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CBaseVSShader; +class IMaterialVar; +class IShaderDynamicAPI; +class IShaderShadow; + + +//----------------------------------------------------------------------------- +// Init params/ init/ draw methods +//----------------------------------------------------------------------------- +struct WorldVertexTransitionEditor_DX8_Vars_t +{ + WorldVertexTransitionEditor_DX8_Vars_t() { memset( this, 0xFF, sizeof(WorldVertexTransitionEditor_DX8_Vars_t) ); } + + int m_nBaseTextureVar; + int m_nBaseTextureFrameVar; + int m_nBaseTextureTransformVar; + int m_nBaseTexture2Var; + int m_nBaseTexture2FrameVar; + int m_nBaseTexture2TransformVar; +}; + +void InitParamsWorldVertexTransitionEditor_DX8( IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ); +void InitWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, WorldVertexTransitionEditor_DX8_Vars_t &info ); +void DrawWorldVertexTransitionEditor_DX8( CBaseVSShader *pShader, IMaterialVar** params, + IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, WorldVertexTransitionEditor_DX8_Vars_t &info ); + + +#endif // WORLDVERTEXTRANSITION_DX8_HELPER_H \ No newline at end of file