You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
962 lines
34 KiB
962 lines
34 KiB
//========= Copyright (c) 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"
|
|
|
|
ConVar r_buildingmapforworld( "r_buildingmapforworld", "0" );
|
|
|
|
#include "WaterCheap_vs20.inc"
|
|
#include "WaterCheap_ps20.inc"
|
|
#include "WaterCheap_ps20b.inc"
|
|
#include "Water_vs20.inc"
|
|
#include "water_ps20.inc"
|
|
#include "water_ps20b.inc"
|
|
#include "shaderlib/commandbuilder.h"
|
|
|
|
// NOTE: This has to be the last file included!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
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( SCENEDEPTH, 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.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( 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( 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( WATERBLENDFACTOR, 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( FLASHLIGHTTINT, SHADER_PARAM_TYPE_FLOAT, "0", "" )
|
|
SHADER_PARAM( LIGHTMAPWATERFOG, SHADER_PARAM_TYPE_BOOL, "0", "" )
|
|
SHADER_PARAM( FORCEFRESNEL, SHADER_PARAM_TYPE_FLOAT, "0", "" )
|
|
|
|
SHADER_PARAM( FORCEENVMAP, SHADER_PARAM_TYPE_BOOL, "0", "" )
|
|
|
|
SHADER_PARAM( DEPTH_FEATHER, SHADER_PARAM_TYPE_INTEGER, "0", "" )
|
|
|
|
// New flow params
|
|
SHADER_PARAM( FLOWMAP, SHADER_PARAM_TYPE_TEXTURE, "", "flowmap" )
|
|
SHADER_PARAM( FLOWMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $flowmap" )
|
|
SHADER_PARAM( FLOWMAPSCROLLRATE, SHADER_PARAM_TYPE_VEC2, "[0 0", "2D rate to scroll $flowmap" )
|
|
SHADER_PARAM( FLOW_NOISE_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "flow noise texture" )
|
|
|
|
SHADER_PARAM( FLOW_WORLDUVSCALE, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( FLOW_NORMALUVSCALE, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( FLOW_TIMEINTERVALINSECONDS, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( FLOW_UVSCROLLDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( FLOW_BUMPSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( FLOW_NOISE_SCALE, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( FLOW_DEBUG, SHADER_PARAM_TYPE_BOOL, "0", "" )
|
|
|
|
SHADER_PARAM( COLOR_FLOW_UVSCALE, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( COLOR_FLOW_TIMEINTERVALINSECONDS, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( COLOR_FLOW_UVSCROLLDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( COLOR_FLOW_LERPEXP, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
SHADER_PARAM( COLOR_FLOW_DISPLACEBYNORMALSTRENGTH, SHADER_PARAM_TYPE_FLOAT, "", "" )
|
|
|
|
SHADER_PARAM( SIMPLEOVERLAY, SHADER_PARAM_TYPE_TEXTURE, "", "simpleoverlay" )
|
|
|
|
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[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[WATERBLENDFACTOR]->IsDefined() )
|
|
{
|
|
params[WATERBLENDFACTOR]->SetFloatValue( 1.0f );
|
|
}
|
|
|
|
if ( IsPS3() && !params[SCENEDEPTH]->IsDefined() )
|
|
{
|
|
params[SCENEDEPTH]->SetStringValue( "^PS3^DEPTHBUFFER" );
|
|
}
|
|
|
|
// If there's no envmap or reflection texture, make sure to set the reflection tint to 0 so we don't reflect garbage
|
|
// (The better change would be to add static combos to support no environment map but this is a lower impact change at this point)
|
|
if ( !params[ ENVMAP ]->IsDefined() && !params[ REFLECTTEXTURE ]->IsDefined() )
|
|
{
|
|
params[ REFLECTTINT ]->SetVecValue( 0.0f, 0.0f, 0.0f, 0.0f );
|
|
}
|
|
|
|
InitFloatParam( FLOW_WORLDUVSCALE, params, 1.0f );
|
|
InitFloatParam( FLOW_NORMALUVSCALE, params, 1.0f );
|
|
InitFloatParam( FLOW_TIMEINTERVALINSECONDS, params, 0.4f );
|
|
InitFloatParam( FLOW_UVSCROLLDISTANCE, params, 0.2f );
|
|
InitFloatParam( FLOW_BUMPSTRENGTH, params, 1.0f );
|
|
InitFloatParam( FLOW_NOISE_SCALE, params, 0.0002f );
|
|
|
|
InitFloatParam( COLOR_FLOW_UVSCALE, params, 1.0f );
|
|
InitFloatParam( COLOR_FLOW_TIMEINTERVALINSECONDS, params, 0.4f );
|
|
InitFloatParam( COLOR_FLOW_UVSCROLLDISTANCE, params, 0.2f );
|
|
InitFloatParam( COLOR_FLOW_LERPEXP, params, 1.0f );
|
|
InitFloatParam( COLOR_FLOW_DISPLACEBYNORMALSTRENGTH, params, 0.0025f );
|
|
|
|
InitIntParam( FORCEENVMAP, params, 0 );
|
|
|
|
InitIntParam( FORCECHEAP, params, 0 );
|
|
InitFloatParam( FLASHLIGHTTINT, params, 1.0f );
|
|
InitIntParam( LIGHTMAPWATERFOG, params, 0 );
|
|
InitFloatParam( FORCEFRESNEL, params, -1.0f );
|
|
|
|
// Fallbacks for water need lightmaps usually
|
|
if ( params[BASETEXTURE]->IsDefined() || ( params[LIGHTMAPWATERFOG]->GetIntValue() != 0 ) )
|
|
{
|
|
SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP );
|
|
}
|
|
|
|
SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP );
|
|
// Don't need bumped lightmaps unless we have a basetexture. We only use them otherwise for lighting the water fog, which only needs one sample.
|
|
if( params[BASETEXTURE]->IsDefined() && g_pConfig->UseBumpmapping() && params[NORMALMAP]->IsDefined() )
|
|
{
|
|
SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP );
|
|
}
|
|
|
|
if ( !params[DEPTH_FEATHER]->IsDefined() )
|
|
{
|
|
params[DEPTH_FEATHER]->SetIntValue( 0 );
|
|
}
|
|
}
|
|
|
|
SHADER_FALLBACK
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SHADER_INIT
|
|
{
|
|
Assert( params[WATERDEPTH]->IsDefined() );
|
|
|
|
if( params[REFRACTTEXTURE]->IsDefined() )
|
|
{
|
|
LoadTexture( REFRACTTEXTURE, TEXTUREFLAGS_SRGB );
|
|
}
|
|
if( params[SCENEDEPTH]->IsDefined() )
|
|
{
|
|
LoadTexture( SCENEDEPTH, 0 );
|
|
}
|
|
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 );
|
|
}
|
|
if ( params[FLOWMAP]->IsDefined() )
|
|
{
|
|
LoadTexture( FLOWMAP );
|
|
}
|
|
if ( params[FLOW_NOISE_TEXTURE]->IsDefined() )
|
|
{
|
|
LoadTexture( FLOW_NOISE_TEXTURE );
|
|
}
|
|
if ( params[SIMPLEOVERLAY]->IsDefined() )
|
|
{
|
|
LoadTexture( SIMPLEOVERLAY, 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 )
|
|
{
|
|
Vector4D Scroll1;
|
|
params[SCROLL1]->GetVecValue( Scroll1.Base(), 4 );
|
|
|
|
bool bHasFlowmap = params[FLOWMAP]->IsTexture();
|
|
bool bHasBaseTexture = params[BASETEXTURE]->IsTexture();
|
|
bool bHasMultiTexture = fabs( Scroll1.x ) > 0.0f;
|
|
bool hasFlashlight = !bHasMultiTexture && UsingFlashlight( params );
|
|
bool bLightmapWaterFog = ( params[LIGHTMAPWATERFOG]->GetIntValue() != 0 );
|
|
bool bHasSimpleOverlay = params[SIMPLEOVERLAY]->IsTexture();
|
|
bool bForceFresnel = ( params[FORCEFRESNEL]->GetFloatValue() != -1.0f );
|
|
|
|
if ( bHasFlowmap )
|
|
{
|
|
bHasMultiTexture = false;
|
|
}
|
|
|
|
if ( bHasBaseTexture || bHasMultiTexture )
|
|
{
|
|
//hasFlashlight = false;
|
|
//bLightmapWaterFog = false;
|
|
}
|
|
|
|
// LIGHTMAP - needed either with basetexture or lightmapwaterfog. Not sure where the bReflection restriction comes in.
|
|
bool bUsingLightmap = bLightmapWaterFog || ( bReflection && bHasBaseTexture );
|
|
|
|
SHADOW_STATE
|
|
{
|
|
SetInitialShadowState( );
|
|
if ( bRefraction )
|
|
{
|
|
// refract sampler
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !IsX360() );
|
|
}
|
|
|
|
if ( bReflection )
|
|
{
|
|
// reflect sampler
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, !IsX360() );
|
|
}
|
|
else
|
|
{
|
|
// envmap sampler
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false );
|
|
}
|
|
|
|
if ( bHasBaseTexture )
|
|
{
|
|
// BASETEXTURE
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true );
|
|
}
|
|
|
|
// normal map
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
|
|
|
|
if ( bUsingLightmap )
|
|
{
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false );
|
|
}
|
|
|
|
// flowmap
|
|
if ( bHasFlowmap )
|
|
{
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
|
|
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, false );
|
|
}
|
|
|
|
if( hasFlashlight )
|
|
{
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
|
|
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
|
|
//pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 );
|
|
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );
|
|
}
|
|
|
|
if ( IsGameConsole() )
|
|
{
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );
|
|
}
|
|
|
|
if ( bHasSimpleOverlay )
|
|
{
|
|
// SIMPLEOVERLAY
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER11, true );
|
|
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER11, true );
|
|
}
|
|
|
|
// pseudo-translucent water only gets used on platforms which disable refract (as a cheaper substitute for refractive water)
|
|
if( IS_FLAG_SET( MATERIAL_VAR_PSEUDO_TRANSLUCENT ) )
|
|
{
|
|
s_pShaderShadow->EnableBlendingForceOpaque( true );
|
|
s_pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
|
|
s_pShaderShadow->EnableDepthWrites( 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;
|
|
// You need lightmap data if you are using lightmapwaterfog or you have a basetexture.
|
|
if ( bLightmapWaterFog || bHasBaseTexture )
|
|
{
|
|
numTexCoords = 3;
|
|
}
|
|
pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 );
|
|
|
|
DECLARE_STATIC_VERTEX_SHADER( water_vs20 );
|
|
SET_STATIC_VERTEX_SHADER_COMBO( MULTITEXTURE, bHasMultiTexture );
|
|
SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE, bHasBaseTexture );
|
|
SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight );
|
|
SET_STATIC_VERTEX_SHADER_COMBO( LIGHTMAPWATERFOG, bLightmapWaterFog );
|
|
SET_STATIC_VERTEX_SHADER_COMBO( FLOWMAP, bHasFlowmap );
|
|
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, bHasMultiTexture );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, bHasBaseTexture );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( LIGHTMAPWATERFOG, bLightmapWaterFog );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FORCEFRESNEL, bForceFresnel );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( SIMPLEOVERLAY, bHasSimpleOverlay );
|
|
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, bHasMultiTexture );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, bHasBaseTexture );
|
|
// SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FORCEFRESNEL, bForceFresnel );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( SIMPLEOVERLAY, bHasSimpleOverlay );
|
|
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, SRGBReadMask( !IsX360() ), REFRACTTEXTURE, -1 );
|
|
}
|
|
|
|
if ( bReflection )
|
|
{
|
|
BindTexture( SHADER_SAMPLER1, SRGBReadMask( !IsX360() ), REFLECTTEXTURE, -1 );
|
|
}
|
|
else if ( params[ ENVMAP ]->IsDefined() )
|
|
{
|
|
BindTexture( SHADER_SAMPLER1, TEXTURE_BINDFLAGS_NONE, ENVMAP );
|
|
}
|
|
|
|
BindTexture( SHADER_SAMPLER2, TEXTURE_BINDFLAGS_NONE, NORMALMAP, BUMPFRAME );
|
|
|
|
if ( bUsingLightmap )
|
|
{
|
|
pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_BINDFLAGS_NONE, TEXTURE_LIGHTMAP );
|
|
}
|
|
|
|
if( bHasBaseTexture )
|
|
{
|
|
BindTexture( SHADER_SAMPLER10, IsX360() ? TEXTURE_BINDFLAGS_NONE : TEXTURE_BINDFLAGS_SRGBREAD, BASETEXTURE, FRAME );
|
|
}
|
|
|
|
if ( bHasFlowmap )
|
|
{
|
|
BindTexture( SHADER_SAMPLER4, TEXTURE_BINDFLAGS_NONE, FLOWMAP, FLOWMAPFRAME );
|
|
BindTexture( SHADER_SAMPLER5, TEXTURE_BINDFLAGS_NONE, FLOW_NOISE_TEXTURE );
|
|
|
|
float vFlowConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
vFlowConst1[0] = 1.0f / params[ FLOW_WORLDUVSCALE ]->GetFloatValue();
|
|
vFlowConst1[1] = 1.0f / params[ FLOW_NORMALUVSCALE ]->GetFloatValue();
|
|
vFlowConst1[2] = params[ FLOW_BUMPSTRENGTH ]->GetFloatValue();
|
|
vFlowConst1[3] = params[ COLOR_FLOW_DISPLACEBYNORMALSTRENGTH ]->GetFloatValue();
|
|
pShaderAPI->SetPixelShaderConstant( 13, vFlowConst1, 1 );
|
|
|
|
float vFlowConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
vFlowConst2[0] = params[ FLOW_TIMEINTERVALINSECONDS ]->GetFloatValue();
|
|
vFlowConst2[1] = params[ FLOW_UVSCROLLDISTANCE ]->GetFloatValue();
|
|
vFlowConst2[2] = params[ FLOW_NOISE_SCALE ]->GetFloatValue();
|
|
pShaderAPI->SetPixelShaderConstant( 14, vFlowConst2, 1 );
|
|
|
|
float vColorFlowConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
vColorFlowConst1[0] = 1.0f / params[ COLOR_FLOW_UVSCALE ]->GetFloatValue();
|
|
vColorFlowConst1[1] = params[ COLOR_FLOW_TIMEINTERVALINSECONDS ]->GetFloatValue();
|
|
vColorFlowConst1[2] = params[ COLOR_FLOW_UVSCROLLDISTANCE ]->GetFloatValue();
|
|
vColorFlowConst1[3] = params[ COLOR_FLOW_LERPEXP ]->GetFloatValue();
|
|
pShaderAPI->SetPixelShaderConstant( 26, vColorFlowConst1, 1 );
|
|
}
|
|
|
|
if( bHasSimpleOverlay )
|
|
{
|
|
BindTexture( SHADER_SAMPLER11, TEXTURE_BINDFLAGS_SRGBREAD, SIMPLEOVERLAY );
|
|
}
|
|
|
|
if ( IsGameConsole() )
|
|
{
|
|
if ( IsPS3() )
|
|
{
|
|
BindTexture( SHADER_SAMPLER9, TEXTURE_BINDFLAGS_NONE, SCENEDEPTH, -1 );
|
|
}
|
|
else if ( IsX360() )
|
|
{
|
|
pShaderAPI->BindStandardTexture( SHADER_SAMPLER9, TEXTURE_BINDFLAGS_NONE, TEXTURE_FRAME_BUFFER_FULL_DEPTH );
|
|
}
|
|
else
|
|
{
|
|
Error( "water.cpp: Unsupported console platform.\n" );
|
|
}
|
|
|
|
VMatrix viewMatrix, projMatrix, worldToProjMatrix, projToWorldMatrix;
|
|
pShaderAPI->GetMatrix( MATERIAL_VIEW, viewMatrix.m[0] );
|
|
pShaderAPI->GetActualProjectionMatrix( projMatrix.m[0] );
|
|
|
|
// The view and proj matrices are transposed vs. what you would normally expect, argh.
|
|
//viewMatrix = viewMatrix.Transpose();
|
|
//projMatrix = projMatrix.Transpose();
|
|
//MatrixMultiply( projMatrix, viewMatrix, worldToProjMatrix );
|
|
//MatrixInverseGeneral( worldToProjMatrix, projToWorldMatrix );
|
|
|
|
// One less transpose.
|
|
MatrixMultiply( viewMatrix, projMatrix, worldToProjMatrix );
|
|
MatrixInverseGeneral( worldToProjMatrix, projToWorldMatrix );
|
|
projToWorldMatrix = projToWorldMatrix.Transpose();
|
|
|
|
// Send down rows 2 (Z) and 3 (W), because that's all the water shader needs to recover worldspace Z.
|
|
pShaderAPI->SetPixelShaderConstant( 33, &projToWorldMatrix.m[2][0], 1 );
|
|
pShaderAPI->SetPixelShaderConstant( 34, &projToWorldMatrix.m[3][0], 1 );
|
|
|
|
int nDepthFeather = params[DEPTH_FEATHER]->GetIntValue();
|
|
const float flDepthFeatherDistanceFactor = .16f;
|
|
Vector4D vEdgeFeatheringParams( flDepthFeatherDistanceFactor, nDepthFeather ? 0.0f : 1.0f, 0.0f, 0.0f );
|
|
pShaderAPI->SetPixelShaderConstant( 35, vEdgeFeatheringParams.Base(), 1 );
|
|
}
|
|
|
|
// Time
|
|
float vTimeConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
float flTime = pShaderAPI->CurrentTime();
|
|
vTimeConst[0] = flTime;
|
|
//vTimeConst[0] -= ( float )( ( int )( vTimeConst[0] / 1000.0f ) ) * 1000.0f;
|
|
pShaderAPI->SetPixelShaderConstant( 8, vTimeConst, 1 );
|
|
|
|
// These constants are used to rotate the world space water normals around the up axis to align the
|
|
// normal with the camera and then give us a 2D offset vector to use for reflection and refraction uv's
|
|
VMatrix mView;
|
|
pShaderAPI->GetMatrix( MATERIAL_VIEW, mView.m[0] );
|
|
mView = mView.Transpose3x3();
|
|
|
|
Vector4D vCameraRight( mView.m[0][0], mView.m[0][1], mView.m[0][2], 0.0f );
|
|
vCameraRight.z = 0.0f; // Project onto the plane of water
|
|
vCameraRight.AsVector3D().NormalizeInPlace();
|
|
|
|
Vector4D vCameraForward;
|
|
CrossProduct( Vector( 0.0f, 0.0f, 1.0f ), vCameraRight.AsVector3D(), vCameraForward.AsVector3D() ); // I assume the water surface normal is pointing along z!
|
|
|
|
pShaderAPI->SetPixelShaderConstant( 22, vCameraRight.Base() );
|
|
pShaderAPI->SetPixelShaderConstant( 23, vCameraForward.Base() );
|
|
|
|
SetPixelShaderConstant( 25, FORCEFRESNEL );
|
|
|
|
// Refraction tint
|
|
if( bRefraction )
|
|
{
|
|
SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT );
|
|
}
|
|
|
|
// Reflection tint
|
|
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] = params[WATERBLENDFACTOR]->GetFloatValue();
|
|
pShaderAPI->SetPixelShaderConstant( 4, linearReflectTint, 1 );
|
|
}
|
|
else
|
|
{
|
|
SetPixelShaderConstantGammaToLinear( 4, REFLECTTINT, WATERBLENDFACTOR );
|
|
}
|
|
|
|
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 );
|
|
|
|
#if 0
|
|
SetPixelShaderConstantGammaToLinear( 6, FOGCOLOR );
|
|
#else
|
|
// Need to use the srgb curve since that we do in UpdatePixelFogColorConstant so that we match the older version of water where we render to an offscreen buffer and fog on the way in.
|
|
float fogColorConstant[4];
|
|
|
|
params[FOGCOLOR]->GetVecValue( fogColorConstant, 3 );
|
|
fogColorConstant[3] = 0.0f;
|
|
|
|
fogColorConstant[0] = SrgbGammaToLinear( fogColorConstant[0] );
|
|
fogColorConstant[1] = SrgbGammaToLinear( fogColorConstant[1] );
|
|
fogColorConstant[2] = SrgbGammaToLinear( fogColorConstant[2] );
|
|
pShaderAPI->SetPixelShaderConstant( 6, fogColorConstant, 1 );
|
|
#endif
|
|
|
|
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( 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( bHasFlowmap )
|
|
{
|
|
SetPixelShaderConstant( 9, FLOWMAPSCROLLRATE );
|
|
}
|
|
|
|
DECLARE_DYNAMIC_VERTEX_SHADER( water_vs20 );
|
|
SET_DYNAMIC_VERTEX_SHADER( water_vs20 );
|
|
|
|
#ifdef _PS3
|
|
CCommandBufferBuilder< CDynamicCommandStorageBuffer > DynamicCmdsOut;
|
|
#else
|
|
CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut;
|
|
#endif
|
|
|
|
bool bFlashlightShadows = false;
|
|
bool bUberlight = false;
|
|
if( hasFlashlight )
|
|
{
|
|
#ifdef _PS3
|
|
CCommandBufferBuilder< CFixedCommandStorageBuffer< 256 > > flashlightECB;
|
|
#endif
|
|
|
|
pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight );
|
|
#ifdef _PS3
|
|
{
|
|
flashlightECB.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4 );
|
|
}
|
|
#endif
|
|
if( IsX360())
|
|
{
|
|
DynamicCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4 );
|
|
}
|
|
|
|
CBCmdSetPixelShaderFlashlightState_t state;
|
|
state.m_LightSampler = SHADER_SAMPLER6; // FIXME . . don't want this here.
|
|
state.m_DepthSampler = SHADER_SAMPLER7;
|
|
state.m_ShadowNoiseSampler = SHADER_SAMPLER8;
|
|
state.m_nColorConstant = PSREG_FLASHLIGHT_COLOR;
|
|
state.m_nAttenConstant = 15;
|
|
state.m_nOriginConstant = 16;
|
|
state.m_nDepthTweakConstant = 21;
|
|
state.m_nScreenScaleConstant = PSREG_FLASHLIGHT_SCREEN_SCALE;
|
|
state.m_nWorldToTextureConstant = -1;
|
|
state.m_bFlashlightNoLambert = false;
|
|
state.m_bSinglePassFlashlight = true;
|
|
|
|
#ifdef _PS3
|
|
{
|
|
flashlightECB.SetPixelShaderFlashlightState( state );
|
|
flashlightECB.End();
|
|
|
|
ShaderApiFast( pShaderAPI )->ExecuteCommandBufferPPU( flashlightECB.Base() );
|
|
}
|
|
#else
|
|
{
|
|
DynamicCmdsOut.SetPixelShaderFlashlightState( state );
|
|
}
|
|
#endif
|
|
DynamicCmdsOut.SetPixelShaderConstant( 10, FLASHLIGHTTINT );
|
|
}
|
|
|
|
// Get viewport and render target dimensions and set shader constant to do a 2D mad
|
|
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
|
pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight );
|
|
|
|
int nRtWidth, nRtHeight;
|
|
pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight );
|
|
|
|
float vViewportMad[4];
|
|
|
|
// viewport->screen transform
|
|
vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth;
|
|
vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight;
|
|
vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth;
|
|
vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight;
|
|
DynamicCmdsOut.SetPixelShaderConstant( 24, vViewportMad, 1 );
|
|
|
|
if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
|
|
{
|
|
DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20b );
|
|
SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
|
|
SET_DYNAMIC_PIXEL_SHADER( water_ps20b );
|
|
}
|
|
else
|
|
{
|
|
DECLARE_DYNAMIC_PIXEL_SHADER( water_ps20 );
|
|
SET_DYNAMIC_PIXEL_SHADER( water_ps20 );
|
|
}
|
|
|
|
DynamicCmdsOut.End();
|
|
pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() );
|
|
}
|
|
Draw();
|
|
}
|
|
|
|
inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow,
|
|
IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bRefraction )
|
|
{
|
|
bool bHasFlowmap = params[FLOWMAP]->IsTexture();
|
|
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 );
|
|
}
|
|
|
|
// Noise texture
|
|
if ( bHasFlowmap )
|
|
{
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
|
|
pShaderShadow->EnableTexture( SHADER_SAMPLER4, 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 );
|
|
|
|
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( FLOWMAP, bHasFlowmap );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) );
|
|
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( FLOWMAP, bHasFlowmap );
|
|
SET_STATIC_PIXEL_SHADER_COMBO( FLOW_DEBUG, clamp( params[ FLOW_DEBUG ]->GetIntValue(), 0, 2 ) );
|
|
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, TEXTURE_BINDFLAGS_NONE, ENVMAP, ENVMAPFRAME );
|
|
BindTexture( SHADER_SAMPLER1, TEXTURE_BINDFLAGS_NONE, NORMALMAP, BUMPFRAME );
|
|
if( bRefraction && bBlend )
|
|
{
|
|
BindTexture( SHADER_SAMPLER2, TEXTURE_BINDFLAGS_NONE, REFRACTTEXTURE, -1 );
|
|
}
|
|
|
|
if ( bHasFlowmap )
|
|
{
|
|
BindTexture( SHADER_SAMPLER3, TEXTURE_BINDFLAGS_NONE, FLOWMAP );
|
|
BindTexture( SHADER_SAMPLER4, TEXTURE_BINDFLAGS_NONE, FLOW_NOISE_TEXTURE );
|
|
|
|
float vFlowConst1[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
vFlowConst1[0] = 1.0f / params[ FLOW_WORLDUVSCALE ]->GetFloatValue();
|
|
vFlowConst1[1] = 1.0f / params[ FLOW_NORMALUVSCALE ]->GetFloatValue();
|
|
vFlowConst1[2] = params[ FLOW_BUMPSTRENGTH ]->GetFloatValue();
|
|
pShaderAPI->SetPixelShaderConstant( 13, vFlowConst1, 1 );
|
|
|
|
float vFlowConst2[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
vFlowConst2[0] = params[ FLOW_TIMEINTERVALINSECONDS ]->GetFloatValue();
|
|
vFlowConst2[1] = params[ FLOW_UVSCROLLDISTANCE ]->GetFloatValue();
|
|
vFlowConst2[2] = params[ FLOW_NOISE_SCALE ]->GetFloatValue();
|
|
pShaderAPI->SetPixelShaderConstant( 14, vFlowConst2, 1 );
|
|
|
|
// Time % 1000
|
|
float vTimeConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
float flTime = pShaderAPI->CurrentTime();
|
|
vTimeConst[0] = flTime;
|
|
//vTimeConst[0] -= ( float )( ( int )( vTimeConst[0] / 1000.0f ) ) * 1000.0f;
|
|
pShaderAPI->SetPixelShaderConstant( 10, vTimeConst, 1 );
|
|
}
|
|
|
|
pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_BINDFLAGS_NONE, 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, WATERBLENDFACTOR );
|
|
}
|
|
else
|
|
{
|
|
float zero[4] = { 0.0f, 0.0f, 0.0f, params[WATERBLENDFACTOR]->GetFloatValue() };
|
|
pShaderAPI->SetPixelShaderConstant( 2, zero );
|
|
}
|
|
|
|
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( 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( watercheap_ps20b );
|
|
}
|
|
else
|
|
{
|
|
DECLARE_DYNAMIC_PIXEL_SHADER( watercheap_ps20 );
|
|
SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() );
|
|
SET_DYNAMIC_PIXEL_SHADER( watercheap_ps20 );
|
|
}
|
|
}
|
|
Draw();
|
|
}
|
|
|
|
SHADER_DRAW
|
|
{
|
|
bool bRefraction = params[REFRACTTEXTURE]->IsTexture();
|
|
bool bReflection = params[REFLECTTEXTURE]->IsTexture();
|
|
bool bEnvMap = params[ENVMAP]->IsTexture() && ( params[FORCEENVMAP]->GetIntValue() == 1 );
|
|
bool bForceCheap = ( params[FORCECHEAP]->GetIntValue() != 0 );
|
|
|
|
if ( ( bReflection || bRefraction || bEnvMap ) && !UsingEditor( params ) && !bForceCheap )
|
|
{
|
|
#ifdef _GAMECONSOLE
|
|
{
|
|
if ( IS_FLAG_SET( MATERIAL_VAR_PSEUDO_TRANSLUCENT ) )
|
|
{
|
|
// Do not render pseudo translucent water during the auto Z pass on Xbox 360
|
|
if ( pShaderAPI )
|
|
{
|
|
pShaderAPI->EnablePredication( false, true );
|
|
}
|
|
}
|
|
}
|
|
#endif // _GAMECONSOLE
|
|
|
|
DrawReflectionRefraction( params, pShaderShadow, pShaderAPI, bReflection, bRefraction );
|
|
|
|
#ifdef _GAMECONSOLE
|
|
{
|
|
if ( IS_FLAG_SET( MATERIAL_VAR_PSEUDO_TRANSLUCENT ) )
|
|
{
|
|
if ( pShaderAPI )
|
|
{
|
|
pShaderAPI->DisablePredication();
|
|
}
|
|
}
|
|
}
|
|
#endif // _GAMECONSOLE
|
|
}
|
|
else
|
|
{
|
|
bool bBlend = false;
|
|
DrawCheapWater( params, pShaderShadow, pShaderAPI, bBlend, bRefraction );
|
|
}
|
|
}
|
|
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
|
|
|