mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-03-12 05:30:21 +03:00
This should include the latest version of every shader that was in the 2007 SDK. It also includes a smattering of debug shaders, both VR distortion shaders, and other assorted shaders that will hopefully be useful. None of these new files are included in the game shader DLL project. If you need to modify one of these shaders for use in your mod you will need to rename it so that you don't collide with the version of that shader that lives in stdshader_dx9.dll.
978 lines
38 KiB
C++
978 lines
38 KiB
C++
//========= 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 );
|
|
}
|