aboutsummaryrefslogtreecommitdiff
path: root/mp/src/materialsystem/stdshaders/water.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mp/src/materialsystem/stdshaders/water.cpp')
-rw-r--r--mp/src/materialsystem/stdshaders/water.cpp614
1 files changed, 614 insertions, 0 deletions
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
+