From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- materialsystem/shaderlib/BaseShader.cpp | 1791 +++++++++++++++++++++++++++++++ 1 file changed, 1791 insertions(+) create mode 100644 materialsystem/shaderlib/BaseShader.cpp (limited to 'materialsystem/shaderlib/BaseShader.cpp') diff --git a/materialsystem/shaderlib/BaseShader.cpp b/materialsystem/shaderlib/BaseShader.cpp new file mode 100644 index 0000000..dcd1cc0 --- /dev/null +++ b/materialsystem/shaderlib/BaseShader.cpp @@ -0,0 +1,1791 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=====================================================================================// + +#include "shaderlib/BaseShader.h" +#include "shaderlib/ShaderDLL.h" +#include "tier0/dbg.h" +#include "shaderDLL_Global.h" +#include "IShaderSystem.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/itexture.h" +#include "materialsystem/ishaderapi.h" +#include "materialsystem/materialsystem_config.h" +#include "shaderlib/cshader.h" +#include "mathlib/vmatrix.h" +#include "tier1/strtools.h" +#include "convar.h" +#include "tier0/vprof.h" + +// NOTE: This must be the last include file in a .cpp file! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- +const char *CBaseShader::s_pTextureGroupName = NULL; +IMaterialVar **CBaseShader::s_ppParams; +IShaderShadow *CBaseShader::s_pShaderShadow; +IShaderDynamicAPI *CBaseShader::s_pShaderAPI; +IShaderInit *CBaseShader::s_pShaderInit; +int CBaseShader::s_nModulationFlags; +CMeshBuilder *CBaseShader::s_pMeshBuilder; +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +bool g_shaderConfigDumpEnable = false; //true; //DO NOT CHECK IN ENABLED FIXME + +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +CBaseShader::CBaseShader() +{ + GetShaderDLL()->InsertShader( this ); +} + + +//----------------------------------------------------------------------------- +// Shader parameter info +//----------------------------------------------------------------------------- +// Look in BaseShader.h for the enumeration for these. +// Update there if you update here. +static ShaderParamInfo_t s_StandardParams[NUM_SHADER_MATERIAL_VARS] = +{ + { "$flags", "flags", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$flags_defined", "flags_defined", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$flags2", "flags2", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$flags_defined2", "flags2_defined", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$color", "color", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 }, + { "$alpha", "alpha", SHADER_PARAM_TYPE_FLOAT, "1.0", 0 }, + { "$basetexture", "Base Texture with lighting built in", SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", 0 }, + { "$frame", "Animation Frame", SHADER_PARAM_TYPE_INTEGER, "0", 0 }, + { "$basetexturetransform", "Base Texture Texcoord Transform",SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", 0 }, + { "$flashlighttexture", "flashlight spotlight shape texture", SHADER_PARAM_TYPE_TEXTURE, "effects/flashlight001", SHADER_PARAM_NOT_EDITABLE }, + { "$flashlighttextureframe", "Animation Frame for $flashlight", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE }, + { "$color2", "color2", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 }, + { "$srgbtint", "tint value to be applied when running on new-style srgb parts", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 }, +}; + + +//----------------------------------------------------------------------------- +// Gets the standard shader parameter names +// FIXME: Turn this into one function? +//----------------------------------------------------------------------------- +int CBaseShader::GetNumParams( ) const +{ + return NUM_SHADER_MATERIAL_VARS; +} + +char const* CBaseShader::GetParamName( int nParamIndex ) const +{ + Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS ); + return s_StandardParams[nParamIndex].m_pName; +} + +const char *CBaseShader::GetParamHelp( int nParamIndex ) const +{ + Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS ); + return s_StandardParams[nParamIndex].m_pHelp; +} + +ShaderParamType_t CBaseShader::GetParamType( int nParamIndex ) const +{ + Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS ); + return s_StandardParams[nParamIndex].m_Type; +} + +const char *CBaseShader::GetParamDefault( int nParamIndex ) const +{ + Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS ); + return s_StandardParams[nParamIndex].m_pDefaultValue; +} + +int CBaseShader::GetParamFlags( int nParamIndex ) const +{ + Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS ); + return s_StandardParams[nParamIndex].m_nFlags; +} + +//----------------------------------------------------------------------------- +// Necessary to snag ahold of some important data for the helper methods +//----------------------------------------------------------------------------- +void CBaseShader::InitShaderParams( IMaterialVar** ppParams, const char *pMaterialName ) +{ + // Re-entrancy check + Assert( !s_ppParams ); + + s_ppParams = ppParams; + + OnInitShaderParams( ppParams, pMaterialName ); + + s_ppParams = NULL; +} + +void CBaseShader::InitShaderInstance( IMaterialVar** ppParams, IShaderInit *pShaderInit, const char *pMaterialName, const char *pTextureGroupName ) +{ + // Re-entrancy check + Assert( !s_ppParams ); + + s_ppParams = ppParams; + s_pShaderInit = pShaderInit; + s_pTextureGroupName = pTextureGroupName; + + OnInitShaderInstance( ppParams, pShaderInit, pMaterialName ); + + s_pTextureGroupName = NULL; + s_ppParams = NULL; + s_pShaderInit = NULL; +} + +void CBaseShader::DrawElements( IMaterialVar **ppParams, int nModulationFlags, + IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) +{ + VPROF("CBaseShader::DrawElements"); + // Re-entrancy check + Assert( !s_ppParams ); + + s_ppParams = ppParams; + s_pShaderAPI = pShaderAPI; + s_pShaderShadow = pShaderShadow; + s_nModulationFlags = nModulationFlags; + s_pMeshBuilder = pShaderAPI ? pShaderAPI->GetVertexModifyBuilder() : NULL; + + if ( IsSnapshotting() ) + { + // Set up the shadow state + SetInitialShadowState( ); + } + + OnDrawElements( ppParams, pShaderShadow, pShaderAPI, vertexCompression, pContextDataPtr ); + + s_nModulationFlags = 0; + s_ppParams = NULL; + s_pShaderAPI = NULL; + s_pShaderShadow = NULL; + s_pMeshBuilder = NULL; +} + + +//----------------------------------------------------------------------------- +// Sets the default shadow state +//----------------------------------------------------------------------------- +void CBaseShader::SetInitialShadowState( ) +{ + // Set the default state + s_pShaderShadow->SetDefaultState(); + + // Init the standard states... + int flags = s_ppParams[FLAGS]->GetIntValue(); + if (flags & MATERIAL_VAR_IGNOREZ) + { + s_pShaderShadow->EnableDepthTest( false ); + s_pShaderShadow->EnableDepthWrites( false ); + } + + if (flags & MATERIAL_VAR_DECAL) + { + s_pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL ); + s_pShaderShadow->EnableDepthWrites( false ); + } + + if (flags & MATERIAL_VAR_NOCULL) + { + s_pShaderShadow->EnableCulling( false ); + } + + if (flags & MATERIAL_VAR_ZNEARER) + { + s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_NEARER ); + } + + if (flags & MATERIAL_VAR_WIREFRAME) + { + s_pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE ); + } + + // Set alpha to coverage + if (flags & MATERIAL_VAR_ALLOWALPHATOCOVERAGE) + { + // Force the bit on and then check against alpha blend and test states in CShaderShadowDX8::ComputeAggregateShadowState() + s_pShaderShadow->EnableAlphaToCoverage( true ); + } +} + + +//----------------------------------------------------------------------------- +// Draws a snapshot +//----------------------------------------------------------------------------- +void CBaseShader::Draw( bool bMakeActualDrawCall ) +{ + if ( IsSnapshotting() ) + { + // Turn off transparency if we're asked to.... + if (g_pConfig->bNoTransparency && + ((s_ppParams[FLAGS]->GetIntValue() & MATERIAL_VAR_NO_DEBUG_OVERRIDE) == 0)) + { + s_pShaderShadow->EnableDepthWrites( true ); + s_pShaderShadow->EnableBlending( false ); + } + + GetShaderSystem()->TakeSnapshot(); + } + else + { + GetShaderSystem()->DrawSnapshot( bMakeActualDrawCall ); + } +} + + +//----------------------------------------------------------------------------- +// Finds a particular parameter (works because the lowest parameters match the shader) +//----------------------------------------------------------------------------- +int CBaseShader::FindParamIndex( const char *pName ) const +{ + int numParams = GetNumParams(); + for( int i = 0; i < numParams; i++ ) + { + if( Q_strnicmp( GetParamName( i ), pName, 64 ) == 0 ) + { + return i; + } + } + return -1; +} + + +//----------------------------------------------------------------------------- +// Are we using graphics? +//----------------------------------------------------------------------------- +bool CBaseShader::IsUsingGraphics() +{ + return GetShaderSystem()->IsUsingGraphics(); +} + + +//----------------------------------------------------------------------------- +// Are we using graphics? +//----------------------------------------------------------------------------- +bool CBaseShader::CanUseEditorMaterials() +{ + return GetShaderSystem()->CanUseEditorMaterials(); +} + + +//----------------------------------------------------------------------------- +// Gets the builder... +//----------------------------------------------------------------------------- +CMeshBuilder* CBaseShader::MeshBuilder() +{ + return s_pMeshBuilder; +} + + +//----------------------------------------------------------------------------- +// Loads a texture +//----------------------------------------------------------------------------- +void CBaseShader::LoadTexture( int nTextureVar, int nAdditionalCreationFlags /* = 0 */ ) +{ + if ((!s_ppParams) || (nTextureVar == -1)) + return; + + IMaterialVar* pNameVar = s_ppParams[nTextureVar]; + if( pNameVar && pNameVar->IsDefined() ) + { + s_pShaderInit->LoadTexture( pNameVar, s_pTextureGroupName, nAdditionalCreationFlags ); + } +} + + +//----------------------------------------------------------------------------- +// Loads a bumpmap +//----------------------------------------------------------------------------- +void CBaseShader::LoadBumpMap( int nTextureVar ) +{ + if ((!s_ppParams) || (nTextureVar == -1)) + return; + + IMaterialVar* pNameVar = s_ppParams[nTextureVar]; + if( pNameVar && pNameVar->IsDefined() ) + { + s_pShaderInit->LoadBumpMap( pNameVar, s_pTextureGroupName ); + } +} + + +//----------------------------------------------------------------------------- +// Loads a cubemap +//----------------------------------------------------------------------------- +void CBaseShader::LoadCubeMap( int nTextureVar, int nAdditionalCreationFlags /* = 0 */ ) +{ + if ((!s_ppParams) || (nTextureVar == -1)) + return; + + IMaterialVar* pNameVar = s_ppParams[nTextureVar]; + if( pNameVar && pNameVar->IsDefined() ) + { + s_pShaderInit->LoadCubeMap( s_ppParams, pNameVar, nAdditionalCreationFlags ); + } +} + + +ShaderAPITextureHandle_t CBaseShader::GetShaderAPITextureBindHandle( int nTextureVar, int nFrameVar, int nTextureChannel ) +{ +// Assert( !IsSnapshotting() ); + Assert( nTextureVar != -1 ); + Assert ( s_ppParams ); + + IMaterialVar* pTextureVar = s_ppParams[nTextureVar]; + IMaterialVar* pFrameVar = (nFrameVar != -1) ? s_ppParams[nFrameVar] : NULL; + int nFrame = pFrameVar ? pFrameVar->GetIntValue() : 0; + return GetShaderSystem()->GetShaderAPITextureBindHandle( pTextureVar->GetTextureValue(), nFrame, nTextureChannel ); +} + + +//----------------------------------------------------------------------------- +// Four different flavors of BindTexture(), handling the two-sampler +// case as well as ITexture* versus textureVar forms +//----------------------------------------------------------------------------- + +void CBaseShader::BindTexture( Sampler_t sampler1, int nTextureVar, int nFrameVar /* = -1 */ ) +{ + BindTexture( sampler1, (Sampler_t) -1, nTextureVar, nFrameVar ); +} + + +void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, int nTextureVar, int nFrameVar /* = -1 */ ) +{ + Assert( !IsSnapshotting() ); + Assert( nTextureVar != -1 ); + Assert ( s_ppParams ); + + IMaterialVar* pTextureVar = s_ppParams[nTextureVar]; + IMaterialVar* pFrameVar = (nFrameVar != -1) ? s_ppParams[nFrameVar] : NULL; + if (pTextureVar) + { + int nFrame = pFrameVar ? pFrameVar->GetIntValue() : 0; + + if ( sampler2 == Sampler_t(-1) ) + { + GetShaderSystem()->BindTexture( sampler1, pTextureVar->GetTextureValue(), nFrame ); + } + else + { + GetShaderSystem()->BindTexture( sampler1, sampler2, pTextureVar->GetTextureValue(), nFrame ); + } + } +} + + +void CBaseShader::BindTexture( Sampler_t sampler1, ITexture *pTexture, int nFrame /* = 0 */ ) +{ + BindTexture( sampler1, (Sampler_t) -1, pTexture, nFrame ); +} + +void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, ITexture *pTexture, int nFrame /* = 0 */ ) +{ + Assert( !IsSnapshotting() ); + + if ( sampler2 == Sampler_t(-1 ) ) + { + GetShaderSystem()->BindTexture( sampler1, pTexture, nFrame ); + } + else + { + GetShaderSystem()->BindTexture( sampler1, sampler2, pTexture, nFrame ); + } +} + +void CBaseShader::GetTextureDimensions( float* pOutWidth, float* pOutHeight, int nTextureVar ) +{ + Assert( pOutWidth && pOutHeight ); // Outputs must be provided. + Assert( nTextureVar != -1 ); + + IMaterialVar* pTextureVar = s_ppParams[nTextureVar]; + + if (pTextureVar && pTextureVar->GetTextureValue()) + { + *pOutWidth = (float) (pTextureVar->GetTextureValue()->GetActualWidth()); + *pOutHeight = (float) (pTextureVar->GetTextureValue()->GetActualHeight()); + } +} + + +//----------------------------------------------------------------------------- +// Does the texture store translucency in its alpha channel? +//----------------------------------------------------------------------------- +bool CBaseShader::TextureIsTranslucent( int textureVar, bool isBaseTexture ) +{ + if (textureVar < 0) + return false; + + IMaterialVar** params = s_ppParams; + if (params[textureVar]->GetType() == MATERIAL_VAR_TYPE_TEXTURE) + { + if (!isBaseTexture) + { + return params[textureVar]->GetTextureValue()->IsTranslucent(); + } + else + { + // Override translucency settings if this flag is set. + if (IS_FLAG_SET(MATERIAL_VAR_OPAQUETEXTURE)) + return false; + + if ( (CurrentMaterialVarFlags() & (MATERIAL_VAR_SELFILLUM | MATERIAL_VAR_BASEALPHAENVMAPMASK)) == 0) + { + if ((CurrentMaterialVarFlags() & MATERIAL_VAR_TRANSLUCENT) || + (CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST)) + { + return params[textureVar]->GetTextureValue()->IsTranslucent(); + } + } + } + } + + return false; +} + + +//----------------------------------------------------------------------------- +// +// Helper methods for color modulation +// +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Are we alpha or color modulating? +//----------------------------------------------------------------------------- +bool CBaseShader::IsAlphaModulating() +{ + return (s_nModulationFlags & SHADER_USING_ALPHA_MODULATION) != 0; +} + +bool CBaseShader::IsColorModulating() +{ + return (s_nModulationFlags & SHADER_USING_COLOR_MODULATION) != 0; +} + + +void CBaseShader::GetColorParameter( IMaterialVar **params, float *pColorOut ) const +{ + float flColor2[3]; + params[COLOR]->GetVecValue( pColorOut, 3 ); + params[COLOR2]->GetVecValue( flColor2, 3 ); + + pColorOut[0] *= flColor2[0]; + pColorOut[1] *= flColor2[1]; + pColorOut[2] *= flColor2[2]; + + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + { + float flSRGBTint[3]; + params[SRGBTINT]->GetVecValue( flSRGBTint, 3 ); + + pColorOut[0] *= flSRGBTint[0]; + pColorOut[1] *= flSRGBTint[1]; + pColorOut[2] *= flSRGBTint[2]; + } + +} + +//----------------------------------------------------------------------------- +// FIXME: Figure out a better way to do this? +//----------------------------------------------------------------------------- +int CBaseShader::ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI ) +{ + s_pShaderAPI = pShaderAPI; + + int mod = 0; + if ( GetAlpha(params) < 1.0f ) + { + mod |= SHADER_USING_ALPHA_MODULATION; + } + + float color[3]; + GetColorParameter( params, color ); + + if ((color[0] != 1.0) || (color[1] != 1.0) || (color[2] != 1.0)) + { + mod |= SHADER_USING_COLOR_MODULATION; + } + + if( UsingFlashlight(params) ) + { + mod |= SHADER_USING_FLASHLIGHT; + } + + if ( UsingEditor(params) ) + { + mod |= SHADER_USING_EDITOR; + } + + if( IS_FLAG2_SET( MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING ) ) + { + AssertOnce( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) ); + if( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) ) + { + mod |= SHADER_USING_FIXED_FUNCTION_BAKED_LIGHTING; + } + } + + s_pShaderAPI = NULL; + + return mod; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CBaseShader::NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const +{ + return CShader_IsFlag2Set( params, MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CBaseShader::NeedsFullFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const +{ + return CShader_IsFlag2Set( params, MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CBaseShader::IsTranslucent( IMaterialVar **params ) const +{ + return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ); +} + +//----------------------------------------------------------------------------- +// Returns the translucency... +//----------------------------------------------------------------------------- +float CBaseShader::GetAlpha( IMaterialVar** ppParams ) +{ + if ( !ppParams ) + { + ppParams = s_ppParams; + } + + if (!ppParams) + return 1.0f; + + if ( ppParams[FLAGS]->GetIntValue() & MATERIAL_VAR_NOALPHAMOD ) + return 1.0f; + + float flAlpha = ppParams[ALPHA]->GetFloatValue(); + return clamp( flAlpha, 0.0f, 1.0f ); +} + + +//----------------------------------------------------------------------------- +// Sets the color + transparency +//----------------------------------------------------------------------------- +void CBaseShader::SetColorState( int colorVar, bool setAlpha ) +{ + Assert( !IsSnapshotting() ); + if ( !s_ppParams ) + return; + + // Use tint instead of color if it was specified... + IMaterialVar* pColorVar = (colorVar != -1) ? s_ppParams[colorVar] : 0; + + float color[4] = { 1.0, 1.0, 1.0, 1.0 }; + if (pColorVar) + { + if (pColorVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pColorVar->GetVecValue( color, 3 ); + } + else + { + color[0] = color[1] = color[2] = pColorVar->GetFloatValue(); + } + + if ( !g_pHardwareConfig->SupportsPixelShaders_1_4() ) // Clamp 0..1 for ps_1_1 and below + { + color[0] = clamp( color[0], 0.0f, 1.0f ); + color[1] = clamp( color[1], 0.0f, 1.0f ); + color[2] = clamp( color[2], 0.0f, 1.0f ); + } + else if ( !g_pHardwareConfig->SupportsPixelShaders_2_0() ) // Clamp 0..8 for ps_1_4 + { + color[0] = clamp( color[0], 0.0f, 8.0f ); + color[1] = clamp( color[1], 0.0f, 8.0f ); + color[2] = clamp( color[2], 0.0f, 8.0f ); + } + } + ApplyColor2Factor( color ); + color[3] = setAlpha ? GetAlpha() : 1.0f; + s_pShaderAPI->Color4fv( color ); +} + + +void CBaseShader::SetModulationShadowState( int tintVar ) +{ + // Have have no control over the tint var... + bool doModulation = (tintVar != -1); + + // We activate color modulating when we're alpha or color modulating + doModulation = doModulation || IsAlphaModulating() || IsColorModulating(); + + s_pShaderShadow->EnableConstantColor( doModulation ); +} + +void CBaseShader::SetModulationDynamicState( int tintVar ) +{ + if (tintVar != -1) + { + SetColorState( tintVar, true ); + } + else + { + SetColorState( COLOR, true ); + } +} + +void CBaseShader::ApplyColor2Factor( float *pColorOut ) const // (*pColorOut) *= COLOR2 +{ + IMaterialVar* pColor2Var = s_ppParams[COLOR2]; + if (pColor2Var->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + float flColor2[3]; + pColor2Var->GetVecValue( flColor2, 3 ); + + pColorOut[0] *= flColor2[0]; + pColorOut[1] *= flColor2[1]; + pColorOut[2] *= flColor2[2]; + } + if ( g_pHardwareConfig->UsesSRGBCorrectBlending() ) + { + IMaterialVar* pSRGBVar = s_ppParams[SRGBTINT]; + if (pSRGBVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + float flSRGB[3]; + pSRGBVar->GetVecValue( flSRGB, 3 ); + + pColorOut[0] *= flSRGB[0]; + pColorOut[1] *= flSRGB[1]; + pColorOut[2] *= flSRGB[2]; + } + } +} + +void CBaseShader::ComputeModulationColor( float* color ) +{ + Assert( !IsSnapshotting() ); + if (!s_ppParams) + return; + + IMaterialVar* pColorVar = s_ppParams[COLOR]; + if (pColorVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + pColorVar->GetVecValue( color, 3 ); + } + else + { + color[0] = color[1] = color[2] = pColorVar->GetFloatValue(); + } + + ApplyColor2Factor( color ); + + if( !g_pConfig->bShowDiffuse ) + { + color[0] = color[1] = color[2] = 0.0f; + } + if( mat_fullbright.GetInt() == 2 ) + { + color[0] = color[1] = color[2] = 1.0f; + } + color[3] = GetAlpha(); +} + + +//----------------------------------------------------------------------------- +// +// Helper methods for alpha blending.... +// +//----------------------------------------------------------------------------- +void CBaseShader::EnableAlphaBlending( ShaderBlendFactor_t src, ShaderBlendFactor_t dst ) +{ + Assert( IsSnapshotting() ); + s_pShaderShadow->EnableBlending( true ); + s_pShaderShadow->BlendFunc( src, dst ); + s_pShaderShadow->EnableDepthWrites(false); +} + +void CBaseShader::DisableAlphaBlending() +{ + Assert( IsSnapshotting() ); + s_pShaderShadow->EnableBlending( false ); +} + +void CBaseShader::SetNormalBlendingShadowState( int textureVar, bool isBaseTexture ) +{ + Assert( IsSnapshotting() ); + + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + if (isTranslucent) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + DisableAlphaBlending(); + } +} + +//ConVar mat_debug_flashlight_only( "mat_debug_flashlight_only", "0" ); +void CBaseShader::SetAdditiveBlendingShadowState( int textureVar, bool isBaseTexture ) +{ + Assert( IsSnapshotting() ); + + // Either we've got a constant modulation + bool isTranslucent = IsAlphaModulating(); + + // Or we've got a vertex alpha + isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA); + + // Or we've got a texture alpha + isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) && + !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) ); + + /* + if ( mat_debug_flashlight_only.GetBool() ) + { + if (isTranslucent) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA); + //s_pShaderShadow->EnableAlphaTest( true ); + //s_pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.99f ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ZERO); + } + } + else + */ + { + if (isTranslucent) + { + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + } + else + { + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + } + } +} + +void CBaseShader::SetDefaultBlendingShadowState( int textureVar, bool isBaseTexture ) +{ + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + SetAdditiveBlendingShadowState( textureVar, isBaseTexture ); + } + else + { + SetNormalBlendingShadowState( textureVar, isBaseTexture ); + } +} + +void CBaseShader::SetBlendingShadowState( BlendType_t nMode ) +{ + switch ( nMode ) + { + case BT_NONE: + DisableAlphaBlending(); + break; + + case BT_BLEND: + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + break; + + case BT_ADD: + EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); + break; + + case BT_BLENDADD: + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE ); + break; + } +} + + + +//----------------------------------------------------------------------------- +// Sets lightmap blending mode for single texturing +//----------------------------------------------------------------------------- +void CBaseShader::SingleTextureLightmapBlendMode( ) +{ + Assert( IsSnapshotting() ); + + s_pShaderShadow->EnableBlending( true ); + s_pShaderShadow->BlendFunc( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); +} + + +//----------------------------------------------------------------------------- +// Loads the identity transform into a matrix +//----------------------------------------------------------------------------- +void CBaseShader::LoadIdentity( MaterialMatrixMode_t matrixMode ) +{ + Assert( !IsSnapshotting() ); + + s_pShaderAPI->MatrixMode( matrixMode ); + s_pShaderAPI->LoadIdentity( ); +} + + +//----------------------------------------------------------------------------- +// Loads the camera to world transform into a matrix +//----------------------------------------------------------------------------- +void CBaseShader::LoadCameraToWorldTransform( MaterialMatrixMode_t matrixMode ) +{ + s_pShaderAPI->MatrixMode( matrixMode ); + s_pShaderAPI->LoadCameraToWorld(); +} + +void CBaseShader::LoadCameraSpaceSphereMapTransform( MaterialMatrixMode_t matrixMode ) +{ + static float mat[4][4] = + { + { 0.5f, 0.0f, 0.0f, 0.0f }, + { 0.0f, -0.5f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.5f, -0.5f, 0.0f, 1.0f }, + }; + + s_pShaderAPI->MatrixMode( matrixMode ); + s_pShaderAPI->LoadMatrix( (float*)mat ); +} + + +//----------------------------------------------------------------------------- +// +// Sets a texture translation transform +// +//----------------------------------------------------------------------------- +void CBaseShader::SetFixedFunctionTextureTranslation( MaterialMatrixMode_t textureTransform, int translationVar ) +{ + Assert( !IsSnapshotting() ); + + // handle scrolling of base texture + Vector2D vDelta( 0, 0 ); + + if (translationVar != -1) + { + s_ppParams[translationVar]->GetVecValue( vDelta.Base(), 2 ); + } + + if( vDelta[0] != 0.0f || vDelta[1] != 0.0f ) + { + s_pShaderAPI->MatrixMode( textureTransform ); + + // only do the upper 3x3 since this is a 2D matrix + float mat[16]; + mat[0] = 1.0f; mat[1] = 0.0f; mat[2] = 0.0f; + mat[4] = 0.0f; mat[5] = 1.0f; mat[6] = 0.0f; + mat[8] = vDelta[0]; mat[9] = vDelta[1]; mat[10] = 1.0f; + + // Better set the stuff we don't set with some sort of value! + mat[3] = mat[7] = mat[11] = 0; + mat[12] = mat[13] = mat[14] = 0; + mat[15] = 1; + + s_pShaderAPI->LoadMatrix( mat ); + } + else + { + LoadIdentity( textureTransform ); + } +} + +void CBaseShader::SetFixedFunctionTextureScale( MaterialMatrixMode_t textureTransform, int scaleVar ) +{ + Assert( !IsSnapshotting() ); + + // handle scrolling of base texture + Vector2D vScale; + s_ppParams[scaleVar]->GetVecValue( vScale.Base(), 2 ); + if( vScale[0] != 0.0f || vScale[1] != 0.0f ) + { + s_pShaderAPI->MatrixMode( textureTransform ); + + // only do the upper 3x3 since this is a 2D matrix + float mat[16]; + mat[0] = vScale[0]; mat[1] = 0.0f; mat[2] = 0.0f; + mat[4] = 0.0f; mat[5] = vScale[1]; mat[6] = 0.0f; + mat[8] = 0.0f; mat[9] = 0.0f; mat[10] = 1.0f; + + // Better set the stuff we don't set with some sort of value! + mat[3] = mat[7] = mat[11] = 0; + mat[12] = mat[13] = mat[14] = 0; + mat[15] = 1; + + s_pShaderAPI->LoadMatrix( mat ); + } + else + { + LoadIdentity( textureTransform ); + } +} + +void CBaseShader::SetFixedFunctionTextureTransform( MaterialMatrixMode_t textureTransform, int transformVar ) +{ + Assert( !IsSnapshotting() ); + + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + s_pShaderAPI->MatrixMode( textureTransform ); + + const VMatrix &transformation = pTransformationVar->GetMatrixValue(); + + // only do the upper 3x3 since this is a 2D matrix + float mat[16]; + mat[0] = transformation[0][0]; mat[1] = transformation[1][0]; mat[2] = transformation[3][0]; + mat[4] = transformation[0][1]; mat[5] = transformation[1][1]; mat[6] = transformation[3][1]; + mat[8] = transformation[0][3]; mat[9] = transformation[1][3]; mat[10] = transformation[3][3]; + + // Better set the stuff we don't set with some sort of value! + mat[3] = mat[7] = mat[11] = 0; + mat[12] = mat[13] = mat[14] = 0; + mat[15] = 1; + + s_pShaderAPI->LoadMatrix( mat ); + } + else + { + LoadIdentity( textureTransform ); + } +} + +void CBaseShader::SetFixedFunctionTextureScaledTransform( MaterialMatrixMode_t textureTransform, + int transformVar, int scaleVar ) +{ + Assert( !IsSnapshotting() ); + + float mat[16]; + IMaterialVar* pTransformationVar = s_ppParams[transformVar]; + if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)) + { + Vector2D scale( 1, 1 ); + IMaterialVar* pScaleVar = s_ppParams[scaleVar]; + if (pScaleVar) + { + if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR) + pScaleVar->GetVecValue( scale.Base(), 2 ); + else if (pScaleVar->IsDefined()) + scale[0] = scale[1] = pScaleVar->GetFloatValue(); + } + + s_pShaderAPI->MatrixMode( textureTransform ); + + const VMatrix &transformation = pTransformationVar->GetMatrixValue(); + + // only do the upper 3x3 since this is a 2D matrix + mat[0] = transformation[0][0] * scale[0]; mat[1] = transformation[1][0] * scale[0]; mat[2] = transformation[3][0] * scale[0]; + mat[4] = transformation[0][1] * scale[1]; mat[5] = transformation[1][1] * scale[1]; mat[6] = transformation[3][1] * scale[1]; + mat[8] = transformation[0][3]; mat[9] = transformation[1][3]; mat[10] = transformation[3][3]; + + // Better set the stuff we don't set with some sort of value! + mat[3] = mat[7] = mat[11] = 0; + mat[12] = mat[13] = mat[14] = 0; + mat[15] = 1; + + s_pShaderAPI->LoadMatrix( mat ); + } + else + { + SetFixedFunctionTextureScale( textureTransform, scaleVar ); + } +} + + +//----------------------------------------------------------------------------- +// +// Helper methods for fog +// +//----------------------------------------------------------------------------- +void CBaseShader::FogToOOOverbright( void ) +{ + Assert( IsSnapshotting() ); + if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0) + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_OO_OVERBRIGHT ); + } + else + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + } +} + +void CBaseShader::FogToWhite( void ) +{ + Assert( IsSnapshotting() ); + if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0) + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_WHITE ); + } + else + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + } +} +void CBaseShader::FogToBlack( void ) +{ + Assert( IsSnapshotting() ); + if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0) + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_BLACK ); + } + else + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + } +} + +void CBaseShader::FogToGrey( void ) +{ + Assert( IsSnapshotting() ); + if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0) + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_GREY ); + } + else + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + } +} + +void CBaseShader::FogToFogColor( void ) +{ + Assert( IsSnapshotting() ); + if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0) + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_FOGCOLOR ); + } + else + { + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); + } +} + +void CBaseShader::DisableFog( void ) +{ + Assert( IsSnapshotting() ); + s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED ); +} + +void CBaseShader::DefaultFog( void ) +{ + if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE ) + { + FogToBlack(); + } + else + { + FogToFogColor(); + } +} + + +//----------------------------------------------------------------------------- +// Fixed function multiply by detail texture pass +//----------------------------------------------------------------------------- +void CBaseShader::FixedFunctionMultiplyByDetailPass( int baseTextureVar, int frameVar, + int textureTransformVar, int detailVar, int detailScaleVar ) +{ + IMaterialVar** params = s_ppParams; + + if (!params[detailVar]->IsDefined()) + return; + + if (IsSnapshotting()) + { + SetInitialShadowState(); + + s_pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + bool translucentTexture = TextureIsTranslucent( baseTextureVar, true ) || + IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, false ); + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, false ); + + // Mod 2x blend here + EnableAlphaBlending( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR ); + + s_pShaderShadow->EnableCustomPixelPipe( true ); + s_pShaderShadow->CustomTextureStages( 2 ); + + // We need to blend towards grey based on alpha... + // We can never get the perfect alpha (vertex alpha * cc alpha * texture alpha) + // so we'll just choose to use cc alpha * texture alpha + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1; + + // Compute alpha, stage 0 is used, stage 1 isn't. + if ( translucentTexture ) + { + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + flags |= SHADER_DRAW_TEXCOORD0; + } + else + { + bool hasVertexAlpha = (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA) != 0; + if (hasVertexAlpha) + { + flags |= SHADER_DRAW_COLOR; + } + + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, hasVertexAlpha ? SHADER_TEXOP_MODULATE : SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_VERTEXCOLOR ); + } + + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + + // This here will perform color = vertex light * alpha + 0.5f * (1 - alpha) + // Stage 0 really doesn't do anything + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_BLEND_PREVIOUSSTAGEALPHA, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + s_pShaderShadow->DrawFlags( flags ); + FogToGrey(); + Draw( ); + + s_pShaderShadow->EnableCustomPixelPipe( false ); + DisableAlphaBlending(); + } + else + { + if (TextureIsTranslucent( baseTextureVar, true ) ) + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, textureTransformVar ); + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + } + else + { + // Unnecessary... but we get strange colors if we don't put something on stage 0 + BindTexture( SHADER_SAMPLER0, detailVar, frameVar ); + } + + BindTexture( SHADER_SAMPLER1, detailVar, frameVar ); + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE1, textureTransformVar, detailScaleVar ); + float alpha = GetAlpha(); + s_pShaderAPI->Color4ub( 128, 128, 128, 255 * alpha ); + + Draw( ); + } +} + + +//----------------------------------------------------------------------------- +// Multiply by lightmap pass +//----------------------------------------------------------------------------- +void CBaseShader::FixedFunctionMultiplyByLightmapPass( int baseTextureVar, + int frameVar, int baseTextureTransformVar, float alphaOverride ) +{ + if (IsSnapshotting()) + { + SetInitialShadowState(); + + s_pShaderShadow->EnableAlphaTest( false ); + + s_pShaderShadow->EnableBlending( true ); + SingleTextureLightmapBlendMode(); + + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, false ); + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, false ); + + s_pShaderShadow->EnableCustomPixelPipe( true ); + s_pShaderShadow->CustomTextureStages( 2 ); + + // Stage zero color is not used, this op doesn't matter + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_CONSTANTCOLOR ); + + // This here will perform color = lightmap * (cc alpha) + 1 * (1- cc alpha) + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_BLEND_PREVIOUSSTAGEALPHA, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_LIGHTMAP_TEXCOORD1; + + // Multiply the constant alpha by the texture alpha for total alpha + if (TextureIsTranslucent(baseTextureVar, true)) + { + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + + flags |= SHADER_DRAW_TEXCOORD0; + } + else + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG2, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + } + + // Alpha isn't used, it doesn't matter what we set it to. + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_NONE ); + + s_pShaderShadow->DrawFlags( flags ); + + FogToOOOverbright(); + Draw(); + + s_pShaderShadow->EnableCustomPixelPipe( false ); + } + else + { + s_pShaderAPI->SetDefaultState(); + + // Put the alpha in the color channel to modulate the color down.... + float alpha = (alphaOverride < 0) ? GetAlpha() : alphaOverride; + + // NOTE: 128 is a more exact OO_OVERBRIGHT; it prevents some artifacts +// s_pShaderAPI->Color4f( OO_OVERBRIGHT, OO_OVERBRIGHT, OO_OVERBRIGHT, alpha ); + s_pShaderAPI->Color4ub( 128, 128, 128, (int)(alpha * 255)); + + if (TextureIsTranslucent(baseTextureVar, true)) + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, baseTextureTransformVar ); + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + } + + LoadIdentity( MATERIAL_TEXTURE1 ); + s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + Draw(); + } +} + + +//----------------------------------------------------------------------------- +// Fixed function Self illumination pass +//----------------------------------------------------------------------------- +void CBaseShader::FixedFunctionSelfIlluminationPass( Sampler_t sampler, + int baseTextureVar, int frameVar, int baseTextureTransformVar, int selfIllumTintVar ) +{ +// IMaterialVar** params = s_ppParams; + + if ( IsSnapshotting() ) + { + SetInitialShadowState(); + + // A little setup for self illum here... + SetModulationShadowState( selfIllumTintVar ); + + s_pShaderShadow->EnableTexture( sampler, true ); + + // No overbrighting + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, 1.0f ); + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + + // Don't bother with z writes here... + s_pShaderShadow->EnableDepthWrites( false ); + + // We're always blending + EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); + + int flags = SHADER_DRAW_POSITION; + if ( sampler == SHADER_SAMPLER0 ) + flags |= SHADER_DRAW_TEXCOORD0; + else + flags |= SHADER_DRAW_TEXCOORD1; + + s_pShaderShadow->DrawFlags( flags ); + FogToFogColor(); + } + else + { + s_pShaderAPI->SetDefaultState(); + + SetFixedFunctionTextureTransform( + (sampler == SHADER_SAMPLER0) ? MATERIAL_TEXTURE0 : MATERIAL_TEXTURE1, + baseTextureTransformVar ); + BindTexture( sampler, baseTextureVar, frameVar ); + + // NOTE: Texture + texture offset are set from BaseTimesLightmap + SetModulationDynamicState( selfIllumTintVar ); + } + Draw(); +} + + +//----------------------------------------------------------------------------- +// Fixed function Base * detail pass +//----------------------------------------------------------------------------- +void CBaseShader::FixedFunctionBaseTimesDetailPass( int baseTextureVar, + int frameVar, int baseTextureTransformVar, int detailVar, int detailScaleVar ) +{ + IMaterialVar** params = s_ppParams; + + // We can't do this one one pass if CC and VC are both active... + bool hasDetail = (detailVar != -1) && params[detailVar]->IsDefined(); + bool detailInSecondPass = hasDetail && IsColorModulating() && + (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) || IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA)); + + if (IsSnapshotting()) + { + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, false ); + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, false ); + + // alpha test + s_pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Alpha blending + SetDefaultBlendingShadowState( baseTextureVar, true ); + + // independently configure alpha and color + s_pShaderShadow->EnableAlphaPipe( true ); + + // Here's the color states (NOTE: SHADER_DRAW_COLOR == use Vertex Color) + s_pShaderShadow->EnableConstantColor( IsColorModulating() ); + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD0; + + // Detail texture.. + if (hasDetail && (!detailInSecondPass)) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Force mod2x + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 2.0f ); + + flags |= SHADER_DRAW_TEXCOORD1; + } + + // Here's the alpha states + s_pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + s_pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) ); + s_pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, TextureIsTranslucent(baseTextureVar, true) ); + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + flags |= SHADER_DRAW_COLOR; + s_pShaderShadow->DrawFlags( flags ); + + DefaultFog(); + + Draw(); + + s_pShaderShadow->EnableAlphaPipe( false ); + } + else + { + SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, baseTextureTransformVar ); + BindTexture( SHADER_SAMPLER0, baseTextureVar, frameVar ); + + // Detail texture.. + if (hasDetail && (!detailInSecondPass)) + { + BindTexture( SHADER_SAMPLER1, detailVar, frameVar ); + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE1, baseTextureTransformVar, detailScaleVar ); + } + + SetModulationDynamicState(); + + Draw(); + } + + if (detailInSecondPass) + { + FixedFunctionMultiplyByDetailPass( baseTextureVar, frameVar, baseTextureTransformVar, detailVar, detailScaleVar ); + } +} + + +//----------------------------------------------------------------------------- +// Helpers for environment mapping... +//----------------------------------------------------------------------------- +int CBaseShader::SetShadowEnvMappingState( int envMapMaskVar, int tintVar ) +{ + Assert( IsSnapshotting() ); + IMaterialVar** params = s_ppParams; + + int varFlags = params[FLAGS]->GetIntValue(); + + s_pShaderShadow->EnableAlphaTest( false ); + + // envmap on stage 0 + s_pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + s_pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + if ( (varFlags & MATERIAL_VAR_ENVMAPSPHERE) == 0 ) + s_pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_CAMERASPACEREFLECTIONVECTOR ); + else + s_pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_SPHERE_MAP ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_NORMAL; + + // mask on stage 1 + if (params[envMapMaskVar]->IsDefined() || (varFlags & MATERIAL_VAR_BASEALPHAENVMAPMASK)) + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + flags |= SHADER_DRAW_TEXCOORD1; + } + else + { + s_pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + } + + if (varFlags & MATERIAL_VAR_BASEALPHAENVMAPMASK) + { + s_pShaderShadow->EnableCustomPixelPipe( true ); + s_pShaderShadow->CustomTextureStages( 2 ); + + // Color = base texture * envmaptint * (1 - mask alpha) + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, SHADER_TEXARG_TEXTURE, SHADER_TEXARG_CONSTANTCOLOR ); + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_MODULATE, SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_INVTEXTUREALPHA ); + + // Use alpha modulation * vertex alpha * env map alpha + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_MODULATE, SHADER_TEXARG_VERTEXCOLOR, SHADER_TEXARG_TEXTURE ); + s_pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1, SHADER_TEXARG_PREVIOUSSTAGE, SHADER_TEXARG_CONSTANTCOLOR ); + } + else + { + s_pShaderShadow->EnableAlphaPipe( true ); + + // Color = base texture * envmaptint * mask + s_pShaderShadow->EnableConstantColor( tintVar >= 0 ); + + // Alpha = vertex alpha * constant alpha * env map alpha * mask alpha (only if it's not a base alpha mask) + s_pShaderShadow->EnableConstantAlpha( IsAlphaModulating() ); + s_pShaderShadow->EnableVertexAlpha( (varFlags & MATERIAL_VAR_VERTEXALPHA) != 0 ); + s_pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, true ); + s_pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, params[envMapMaskVar]->IsTexture() ); + } + + return flags; +} + +void CBaseShader::SetDynamicEnvMappingState( int envMapVar, int envMapMaskVar, + int baseTextureVar, int envMapFrameVar, int envMapMaskFrameVar, int frameVar, + int maskOffsetVar, int maskScaleVar, int tintVar ) +{ + Assert( !IsSnapshotting() ); + + IMaterialVar** params = s_ppParams; + int varFlags = params[FLAGS]->GetIntValue(); + + if( (varFlags & MATERIAL_VAR_ENVMAPSPHERE) == 0 ) + { + if ( (varFlags & MATERIAL_VAR_ENVMAPCAMERASPACE) == 0 ) + { + LoadCameraToWorldTransform( MATERIAL_TEXTURE0 ); + } + else + { + LoadIdentity( MATERIAL_TEXTURE0 ); + } + } + else + { + LoadCameraSpaceSphereMapTransform( MATERIAL_TEXTURE0 ); + } + + BindTexture( SHADER_SAMPLER0, envMapVar, envMapFrameVar ); + + if (params[envMapMaskVar]->IsTexture()) + { + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE1, + maskOffsetVar, maskScaleVar ); + BindTexture( SHADER_SAMPLER1, envMapMaskVar, envMapMaskFrameVar ); + } + else if (varFlags & MATERIAL_VAR_BASEALPHAENVMAPMASK) + { + SetFixedFunctionTextureScaledTransform( MATERIAL_TEXTURE1, + maskOffsetVar, maskScaleVar ); + BindTexture( SHADER_SAMPLER1, baseTextureVar, frameVar ); + } + + SetModulationDynamicState( tintVar ); +} + + +//----------------------------------------------------------------------------- +// Masked environment map +//----------------------------------------------------------------------------- +void CBaseShader::FixedFunctionMaskedEnvmapPass( int envMapVar, int envMapMaskVar, + int baseTextureVar, int envMapFrameVar, int envMapMaskFrameVar, + int frameVar, int maskOffsetVar, int maskScaleVar, int envMapTintVar ) +{ +// IMaterialVar** params = ShaderState().m_ppParams; + + if (IsSnapshotting()) + { + // Alpha blending + SetDefaultBlendingShadowState( envMapMaskVar, false ); + + // Disable overbright + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, 1.0f ); + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + + int flags = SetShadowEnvMappingState( envMapMaskVar, envMapTintVar ); + s_pShaderShadow->DrawFlags( flags ); + + DefaultFog(); + Draw(); + + s_pShaderShadow->EnableCustomPixelPipe( false ); + s_pShaderShadow->EnableAlphaPipe( false ); + } + else + { + SetDynamicEnvMappingState( envMapVar, envMapMaskVar, baseTextureVar, + envMapFrameVar, envMapMaskFrameVar, frameVar, + maskOffsetVar, maskScaleVar, envMapTintVar ); + + Draw(); + } +} + + +//----------------------------------------------------------------------------- +// Add masked environment map +//----------------------------------------------------------------------------- +void CBaseShader::FixedFunctionAdditiveMaskedEnvmapPass( int envMapVar, int envMapMaskVar, + int baseTextureVar, int envMapFrameVar, int envMapMaskFrameVar, + int frameVar, int maskOffsetVar, int maskScaleVar, int envMapTintVar ) +{ +// IMaterialVar** params = ShaderState().m_ppParams; + + if (IsSnapshotting()) + { + SetInitialShadowState(); + + // Alpha blending + SetAdditiveBlendingShadowState( envMapMaskVar, false ); + + // Disable overbright + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, 1.0f ); + s_pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE1, 1.0f ); + + // Don't bother with z writes here... + s_pShaderShadow->EnableDepthWrites( false ); + + int flags = SetShadowEnvMappingState( envMapMaskVar, envMapTintVar ); + s_pShaderShadow->DrawFlags( flags ); + + FogToBlack(); + Draw(); + + s_pShaderShadow->EnableCustomPixelPipe( false ); + s_pShaderShadow->EnableAlphaPipe( false ); + } + else + { + SetDynamicEnvMappingState( envMapVar, envMapMaskVar, baseTextureVar, + envMapFrameVar, envMapMaskFrameVar, frameVar, + maskOffsetVar, maskScaleVar, envMapTintVar ); + + Draw(); + } +} + + +void CBaseShader::CleanupDynamicStateFixedFunction( ) +{ + Assert( !IsSnapshotting() ); + LoadIdentity( MATERIAL_TEXTURE0 ); +} + +bool CBaseShader::UsingFlashlight( IMaterialVar **params ) const +{ + if( IsSnapshotting() ) + { + return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_FLASHLIGHT ); + } + else + { + return s_pShaderAPI->InFlashlightMode(); + } +} + +bool CBaseShader::UsingEditor( IMaterialVar **params ) const +{ + if( IsSnapshotting() ) + { + return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_EDITOR ); + } + else + { + return s_pShaderAPI->InEditorMode(); + } +} + +void CBaseShader::DrawFlashlight_dx70( + IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, + int flashlightTextureVar, int flashlightTextureFrameVar, + bool suppress_lighting ) +{ + SHADOW_STATE + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT ); + pShaderShadow->EnableDepthWrites( false ); + pShaderShadow->EnableAlphaWrites( false ); + + // Alpha test +// pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) ); + bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0; + 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. + s_pShaderShadow->EnableAlphaTest( false ); + s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL ); + } + + // Alpha blend + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + + int flags = SHADER_DRAW_POSITION | SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_COLOR | SHADER_DRAW_NORMAL; + pShaderShadow->DrawFlags( flags ); + FogToBlack(); + + if ( !suppress_lighting ) + pShaderShadow->EnableLighting( true ); + + pShaderShadow->EnableCustomPixelPipe( true ); + pShaderShadow->CustomTextureStages( 2 ); + + // color stage 0 + // projected texture * vertex color (lighting) + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, + SHADER_TEXARG_VERTEXCOLOR ); + + // color stage 1 + // * base texture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_COLOR, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + // alpha stage 0 + // get alpha from constant alpha + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_SELECTARG1, + SHADER_TEXARG_CONSTANTCOLOR, SHADER_TEXARG_NONE ); + + // alpha stage 1 + // get alpha from $basetexture + pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE1, + SHADER_TEXCHANNEL_ALPHA, + SHADER_TEXOP_MODULATE, + SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Shove the view position into texcoord 0 before the texture matrix. + pShaderShadow->TexGen( SHADER_TEXTURE_STAGE0, SHADER_TEXGENPARAM_EYE_LINEAR ); + pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, true ); + } + DYNAMIC_STATE + { + SetFlashlightFixedFunctionTextureTransform( MATERIAL_TEXTURE0 ); + + // NOTE: This has to come after the loadmatrix since the loadmatrix screws with the + // transform flags!!!!!! + // Specify that we have XYZ texcoords that need to be divided by W before the pixel shader. + // NOTE Tried to divide XY by Z, but doesn't work. + pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 3, true ); + + BindTexture( SHADER_SAMPLER0, flashlightTextureVar, flashlightTextureFrameVar ); + if( params[BASETEXTURE]->IsTexture() ) + { + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + } + else + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + } + + SetModulationDynamicState(); + } + Draw(); +} + +void CBaseShader::SetFlashlightFixedFunctionTextureTransform( MaterialMatrixMode_t matrix ) +{ + VMatrix worldToTexture; + s_pShaderAPI->GetFlashlightState( worldToTexture ); + + VMatrix worldToView, viewToWorld, viewToTexture; + s_pShaderAPI->GetMatrix( MATERIAL_VIEW, &worldToView[0][0] ); + // The matrix that we get back from the shader api is transposed. . . yuck. + MatrixTranspose( worldToView, worldToView ); + MatrixInverseGeneral( worldToView, viewToWorld ); + MatrixMultiply( worldToTexture, viewToWorld, viewToTexture ); + + s_pShaderAPI->MatrixMode( matrix ); + // tranpose before going into the shaderapi. . . suck + MatrixTranspose( viewToTexture, viewToTexture ); + s_pShaderAPI->LoadMatrix( &viewToTexture[0][0] ); +} + +bool CBaseShader::IsHDREnabled( void ) +{ + // HDRFIXME! Need to fix this for vgui materials + HDRType_t hdr_mode=g_pHardwareConfig->GetHDRType(); + switch(hdr_mode) + { + case HDR_TYPE_NONE: + return false; + + case HDR_TYPE_INTEGER: + return true; + + case HDR_TYPE_FLOAT: + { + ITexture *pRT = s_pShaderAPI->GetRenderTargetEx( 0 ); + if( pRT && pRT->GetImageFormat() == IMAGE_FORMAT_RGBA16161616F ) + { + return true; + } + } + } + return false; +} + -- cgit v1.2.3