You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1026 lines
31 KiB
1026 lines
31 KiB
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
|
|
#include "shaderlib/BaseShader.h"
|
|
#include "shaderlib/ShaderDLL.h"
|
|
#include "tier0/dbg.h"
|
|
#include "shaderDLL_Global.h"
|
|
#include "materialsystem/ishadersystem.h"
|
|
#include "materialsystem/imaterial.h"
|
|
#include "materialsystem/itexture.h"
|
|
#include "materialsystem/ishaderapi.h"
|
|
#include "materialsystem/materialsystem_config.h"
|
|
#include "shaderlib/cshader.h"
|
|
#include "shaderlib/commandbuilder.h"
|
|
#include "renderparm.h"
|
|
#include "mathlib/vmatrix.h"
|
|
#include "tier1/strtools.h"
|
|
#include "convar.h"
|
|
#include "tier0/vprof.h"
|
|
#include "shaderapifast.h"
|
|
|
|
// NOTE: This must be the last include file in a .cpp file!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Storage buffer used for instance command buffers
|
|
//-----------------------------------------------------------------------------
|
|
class CPerInstanceContextData : public CBasePerInstanceContextData
|
|
{
|
|
public:
|
|
CPerInstanceContextData() : m_pCommandBuffer( NULL ), m_nSize( 0 ) {}
|
|
virtual ~CPerInstanceContextData()
|
|
{
|
|
if ( m_pCommandBuffer )
|
|
{
|
|
delete m_pCommandBuffer;
|
|
}
|
|
}
|
|
|
|
virtual unsigned char* GetInstanceCommandBuffer()
|
|
{
|
|
return m_pCommandBuffer;
|
|
}
|
|
|
|
unsigned char *m_pCommandBuffer;
|
|
int m_nSize;
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Globals
|
|
//-----------------------------------------------------------------------------
|
|
const char *CBaseShader::s_pTextureGroupName = NULL;
|
|
IMaterialVar **CBaseShader::s_ppParams = NULL;
|
|
IShaderShadow *CBaseShader::s_pShaderShadow;
|
|
IShaderDynamicAPI *CBaseShader::s_pShaderAPI;
|
|
IShaderInit *CBaseShader::s_pShaderInit;
|
|
int CBaseShader::s_nModulationFlags;
|
|
int CBaseShader::s_nPassCount = 0;
|
|
CPerInstanceContextData** CBaseShader::s_pInstanceDataPtr = NULL;
|
|
static bool s_bBuildingInstanceCommandBuffer = false;
|
|
static CInstanceCommandBufferBuilder< CFixedCommandStorageBuffer< 512 > > s_InstanceCommandBuffer;
|
|
|
|
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::GetParamCount( ) const
|
|
{
|
|
return NUM_SHADER_MATERIAL_VARS;
|
|
}
|
|
|
|
const ShaderParamInfo_t &CBaseShader::GetParamInfo( int nParamIndex ) const
|
|
{
|
|
Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS );
|
|
return s_StandardParams[nParamIndex];
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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, CBasePerInstanceContextData** pInstanceDataPtr )
|
|
{
|
|
VPROF("CBaseShader::DrawElements");
|
|
// Re-entrancy check
|
|
Assert( !s_ppParams );
|
|
|
|
s_ppParams = ppParams;
|
|
s_pShaderAPI = pShaderAPI;
|
|
s_pShaderShadow = pShaderShadow;
|
|
s_nModulationFlags = nModulationFlags;
|
|
s_pInstanceDataPtr = (CPerInstanceContextData**)( pInstanceDataPtr );
|
|
s_nPassCount = 0;
|
|
|
|
if ( IsSnapshotting() )
|
|
{
|
|
// Set up the shadow state
|
|
SetInitialShadowState( );
|
|
}
|
|
|
|
OnDrawElements( ppParams, pShaderShadow, pShaderAPI, vertexCompression, pContextDataPtr );
|
|
|
|
s_pInstanceDataPtr = NULL;
|
|
s_nPassCount = 0;
|
|
s_nModulationFlags = 0;
|
|
s_ppParams = NULL;
|
|
s_pShaderAPI = NULL;
|
|
s_pShaderShadow = 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 )
|
|
{
|
|
// You forgot to call PI_EndCommandBuffer
|
|
Assert( !s_bBuildingInstanceCommandBuffer );
|
|
|
|
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();
|
|
|
|
// Automagically add skinning + vertex lighting
|
|
if ( !s_pInstanceDataPtr[s_nPassCount] )
|
|
{
|
|
bool bIsSkinning = CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_SUPPORTS_HW_SKINNING );
|
|
bool bIsVertexLit = CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_LIGHTING_VERTEX_LIT );
|
|
if ( bIsSkinning || bIsVertexLit )
|
|
{
|
|
PI_BeginCommandBuffer();
|
|
|
|
// NOTE: EndCommandBuffer will insert the appropriate commands
|
|
PI_EndCommandBuffer();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//SNPROF("CBaseShader::Draw");
|
|
|
|
GetShaderSystem()->DrawSnapshot( s_pInstanceDataPtr[s_nPassCount] ?
|
|
s_pInstanceDataPtr[s_nPassCount]->m_pCommandBuffer : NULL, bMakeActualDrawCall );
|
|
}
|
|
|
|
++s_nPassCount;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods related to building per-instance command buffers
|
|
//-----------------------------------------------------------------------------
|
|
void CBaseShader::PI_BeginCommandBuffer()
|
|
{
|
|
// NOTE: This assertion is here because the memory allocation strategy
|
|
// is perhaps not the best if this is used in dynamic states; we should
|
|
// rethink in that case.
|
|
Assert( IsSnapshotting() );
|
|
|
|
Assert( !s_bBuildingInstanceCommandBuffer );
|
|
s_bBuildingInstanceCommandBuffer = true;
|
|
s_InstanceCommandBuffer.Reset();
|
|
}
|
|
|
|
void CBaseShader::PI_EndCommandBuffer()
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
|
|
// Automagically add skinning
|
|
if ( CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_SUPPORTS_HW_SKINNING ) )
|
|
{
|
|
PI_SetSkinningMatrices();
|
|
}
|
|
|
|
if ( CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_LIGHTING_VERTEX_LIT ) )
|
|
{
|
|
PI_SetVertexShaderLocalLighting();
|
|
}
|
|
|
|
s_bBuildingInstanceCommandBuffer = false;
|
|
s_InstanceCommandBuffer.End();
|
|
int nSize = s_InstanceCommandBuffer.Size();
|
|
if ( nSize > 0 )
|
|
{
|
|
CPerInstanceContextData *pContextData = s_pInstanceDataPtr[ s_nPassCount ];
|
|
if ( !pContextData )
|
|
{
|
|
pContextData = new CPerInstanceContextData;
|
|
s_pInstanceDataPtr[ s_nPassCount ] = pContextData;
|
|
}
|
|
unsigned char *pBuf = pContextData->m_pCommandBuffer;
|
|
if ( pContextData->m_nSize < nSize )
|
|
{
|
|
if ( pContextData->m_pCommandBuffer )
|
|
{
|
|
delete pContextData->m_pCommandBuffer;
|
|
}
|
|
pBuf = new unsigned char[nSize];
|
|
pContextData->m_pCommandBuffer = pBuf;
|
|
pContextData->m_nSize = nSize;
|
|
}
|
|
memcpy( pBuf, s_InstanceCommandBuffer.Base(), nSize );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Queues commands onto the instance command buffer
|
|
//-----------------------------------------------------------------------------
|
|
void CBaseShader::PI_SetPixelShaderAmbientLightCube( int nFirstRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetPixelShaderAmbientLightCube( nFirstRegister );
|
|
}
|
|
|
|
void CBaseShader::PI_SetPixelShaderLocalLighting( int nFirstRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetPixelShaderLocalLighting( nFirstRegister );
|
|
}
|
|
|
|
void CBaseShader::PI_SetVertexShaderAmbientLightCube( /*int nFirstRegister*/ )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetVertexShaderAmbientLightCube( /*nFirstRegister*/ );
|
|
}
|
|
|
|
void CBaseShader::PI_SetVertexShaderLocalLighting()
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetVertexShaderLocalLighting( );
|
|
}
|
|
|
|
void CBaseShader::PI_SetSkinningMatrices()
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetSkinningMatrices();
|
|
}
|
|
|
|
void CBaseShader::PI_SetPixelShaderAmbientLightCubeLuminance( int nFirstRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetPixelShaderAmbientLightCubeLuminance( nFirstRegister );
|
|
}
|
|
|
|
void CBaseShader::PI_SetPixelShaderGlintDamping( int nFirstRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetPixelShaderGlintDamping( nFirstRegister );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int nRegister, float scale )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base(), true );
|
|
s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( nRegister, color2, scale );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearScale( int nRegister, float scale )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base() );
|
|
s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearScale( nRegister, color2, scale );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( int nRegister, float scale )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base() );
|
|
s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( nRegister, color2, scale );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearColorSpace( int nRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base(), true );
|
|
s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearColorSpace( nRegister, color2 );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationPixelShaderDynamicState( int nRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base() );
|
|
s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState( nRegister, color2 );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationVertexShaderDynamicState()
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base() );
|
|
s_InstanceCommandBuffer.SetModulationVertexShaderDynamicState( VERTEX_SHADER_MODULATION_COLOR, color2 );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationVertexShaderDynamicState_LinearScale( float flScale )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
Vector color2( 1.0f, 1.0f, 1.0f );
|
|
ApplyColor2Factor( color2.Base() );
|
|
s_InstanceCommandBuffer.SetModulationVertexShaderDynamicState_LinearScale( VERTEX_SHADER_MODULATION_COLOR, color2, flScale );
|
|
}
|
|
|
|
void CBaseShader::PI_SetModulationPixelShaderDynamicState_Identity( int nRegister )
|
|
{
|
|
Assert( s_bBuildingInstanceCommandBuffer );
|
|
s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_Identity( nRegister );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Finds a particular parameter (works because the lowest parameters match the shader)
|
|
//-----------------------------------------------------------------------------
|
|
int CBaseShader::FindParamIndex( const char *pName ) const
|
|
{
|
|
int numParams = GetParamCount();
|
|
for( int i = 0; i < numParams; i++ )
|
|
{
|
|
if( Q_strnicmp( GetParamInfo( i ).m_pName, pName, 64 ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Are we using graphics?
|
|
//-----------------------------------------------------------------------------
|
|
bool CBaseShader::IsUsingGraphics()
|
|
{
|
|
return GetShaderSystem()->IsUsingGraphics();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Are we using graphics?
|
|
//-----------------------------------------------------------------------------
|
|
bool CBaseShader::CanUseEditorMaterials() const
|
|
{
|
|
return GetShaderSystem()->CanUseEditorMaterials();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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, int nAdditionalCreationFlags )
|
|
{
|
|
if ((!s_ppParams) || (nTextureVar == -1))
|
|
return;
|
|
|
|
IMaterialVar* pNameVar = s_ppParams[nTextureVar];
|
|
if( pNameVar && pNameVar->IsDefined() )
|
|
{
|
|
s_pShaderInit->LoadBumpMap( pNameVar, s_pTextureGroupName, nAdditionalCreationFlags );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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 );
|
|
}
|
|
|
|
void CBaseShader::BindVertexTexture( VertexTextureSampler_t vtSampler, int nTextureVar, int nFrame /* = 0 */)
|
|
{
|
|
Assert( !IsSnapshotting() );
|
|
|
|
IMaterialVar* pTextureVar = s_ppParams[nTextureVar];
|
|
if ( !pTextureVar )
|
|
return;
|
|
|
|
GetShaderSystem()->BindVertexTexture( vtSampler, pTextureVar->GetTextureValue() );
|
|
}
|
|
|
|
ShaderAPITextureHandle_t CBaseShader::GetShaderAPITextureBindHandle( ITexture *pTexture, int nFrame, int nTextureChannel )
|
|
{
|
|
return GetShaderSystem()->GetShaderAPITextureBindHandle( pTexture, 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, TextureBindFlags_t nBindFlags, int nTextureVar, int nFrameVar /* = -1 */ )
|
|
{
|
|
BindTexture( sampler1, SHADER_SAMPLER_INVALID, nBindFlags, nTextureVar, nFrameVar );
|
|
}
|
|
|
|
|
|
void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, TextureBindFlags_t nBindFlags, 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 == -1 )
|
|
{
|
|
GetShaderSystem()->BindTexture( sampler1, nBindFlags, pTextureVar->GetTextureValue(), nFrame );
|
|
}
|
|
else
|
|
{
|
|
GetShaderSystem()->BindTexture( sampler1, sampler2, nBindFlags, pTextureVar->GetTextureValue(), nFrame );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CBaseShader::BindTexture( Sampler_t sampler1, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame /* = 0 */ )
|
|
{
|
|
BindTexture( sampler1, SHADER_SAMPLER_INVALID, nBindFlags, pTexture, nFrame );
|
|
}
|
|
|
|
void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame /* = 0 */ )
|
|
{
|
|
Assert( !IsSnapshotting() );
|
|
|
|
if ( sampler2 == -1 )
|
|
{
|
|
GetShaderSystem()->BindTexture( sampler1, nBindFlags, pTexture, nFrame );
|
|
}
|
|
else
|
|
{
|
|
GetShaderSystem()->BindTexture( sampler1, sampler2, nBindFlags, pTexture, nFrame );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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;
|
|
|
|
bool bHasSelfIllum = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_SELFILLUM ) != 0 );
|
|
bool bHasSelfIllumMask = ( ( CurrentMaterialVarFlags2() & MATERIAL_VAR2_SELFILLUMMASK ) != 0 );
|
|
bool bHasBaseAlphaEnvmapMask = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_BASEALPHAENVMAPMASK ) != 0 );
|
|
bool bUsingBaseTextureAlphaForSelfIllum = bHasSelfIllum && !bHasSelfIllumMask;
|
|
// Check if we are using base texture alpha for something other than translucency.
|
|
if ( !bUsingBaseTextureAlphaForSelfIllum && !bHasBaseAlphaEnvmapMask )
|
|
{
|
|
// We aren't using base alpha for anything other than trancluceny.
|
|
|
|
// check if the material is marked as translucent or alpha test.
|
|
if ((CurrentMaterialVarFlags() & MATERIAL_VAR_TRANSLUCENT) ||
|
|
(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST))
|
|
{
|
|
// Make sure the texture has an alpha channel.
|
|
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;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// FIXME: Figure out a better way to do this?
|
|
//-----------------------------------------------------------------------------
|
|
int CBaseShader::ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI )
|
|
{
|
|
s_pShaderAPI = pShaderAPI;
|
|
|
|
int mod = 0;
|
|
if ( UsingFlashlight(params) )
|
|
{
|
|
mod |= SHADER_USING_FLASHLIGHT;
|
|
}
|
|
|
|
if ( UsingEditor(params) )
|
|
{
|
|
mod |= SHADER_USING_EDITOR;
|
|
}
|
|
|
|
if ( IsRenderingPaint(params) )
|
|
{
|
|
mod |= SHADER_USING_PAINT;
|
|
}
|
|
|
|
if ( IsSnapshotting() )
|
|
{
|
|
if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) )
|
|
mod |= SHADER_USING_GBUFFER0;
|
|
if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ) )
|
|
mod |= SHADER_USING_GBUFFER1;
|
|
}
|
|
else
|
|
{
|
|
int nFixedLightingMode = ShaderApiFast( pShaderAPI )->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );
|
|
if ( nFixedLightingMode & 1 )
|
|
mod |= SHADER_USING_GBUFFER0;
|
|
if ( nFixedLightingMode & 2 )
|
|
mod |= SHADER_USING_GBUFFER1;
|
|
}
|
|
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...
|
|
//-----------------------------------------------------------------------------
|
|
void CBaseShader::ApplyColor2Factor( float *pColorOut, bool isLinearSpace ) const // (*pColorOut) *= COLOR2
|
|
{
|
|
if ( !g_pConfig->bShowDiffuse )
|
|
{
|
|
pColorOut[0] = pColorOut[1] = pColorOut[2] = 0.0f;
|
|
return;
|
|
}
|
|
|
|
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];
|
|
}
|
|
#ifndef _PS3
|
|
if ( g_pHardwareConfig->UsesSRGBCorrectBlending() )
|
|
{
|
|
IMaterialVar* pSRGBVar = s_ppParams[SRGBTINT];
|
|
if (pSRGBVar->GetType() == MATERIAL_VAR_TYPE_VECTOR)
|
|
{
|
|
float flSRGB[3];
|
|
pSRGBVar->GetVecValue( flSRGB, 3 );
|
|
|
|
if ( isLinearSpace )
|
|
{
|
|
pColorOut[0] *= flSRGB[0];
|
|
pColorOut[1] *= flSRGB[1];
|
|
pColorOut[2] *= flSRGB[2];
|
|
}
|
|
else
|
|
{
|
|
pColorOut[0] *= GammaToLinearFullRange( flSRGB[0] );
|
|
pColorOut[1] *= GammaToLinearFullRange( flSRGB[1] );
|
|
pColorOut[2] *= GammaToLinearFullRange( flSRGB[2] );
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// 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 );
|
|
}
|
|
|
|
FORCEINLINE void CBaseShader::SetFogMode( ShaderFogMode_t fogMode )
|
|
{
|
|
bool bVertexFog = ((CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXFOG) != 0);
|
|
|
|
if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0)
|
|
{
|
|
s_pShaderShadow->FogMode( fogMode, bVertexFog );
|
|
}
|
|
else
|
|
{
|
|
s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, bVertexFog );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Helper methods for fog
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CBaseShader::FogToOOOverbright( void )
|
|
{
|
|
Assert( IsSnapshotting() );
|
|
SetFogMode( SHADER_FOGMODE_OO_OVERBRIGHT );
|
|
}
|
|
|
|
void CBaseShader::FogToWhite( void )
|
|
{
|
|
Assert( IsSnapshotting() );
|
|
SetFogMode( SHADER_FOGMODE_WHITE );
|
|
}
|
|
void CBaseShader::FogToBlack( void )
|
|
{
|
|
Assert( IsSnapshotting() );
|
|
SetFogMode( SHADER_FOGMODE_BLACK );
|
|
}
|
|
|
|
void CBaseShader::FogToGrey( void )
|
|
{
|
|
Assert( IsSnapshotting() );
|
|
SetFogMode( SHADER_FOGMODE_GREY );
|
|
}
|
|
|
|
void CBaseShader::FogToFogColor( void )
|
|
{
|
|
Assert( IsSnapshotting() );
|
|
SetFogMode( SHADER_FOGMODE_FOGCOLOR );
|
|
}
|
|
|
|
void CBaseShader::DisableFog( void )
|
|
{
|
|
Assert( IsSnapshotting() );
|
|
s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false );
|
|
}
|
|
|
|
void CBaseShader::DefaultFog( void )
|
|
{
|
|
if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE )
|
|
{
|
|
FogToBlack();
|
|
}
|
|
else
|
|
{
|
|
FogToFogColor();
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
bool CBaseShader::IsRenderingPaint( IMaterialVar **params ) const
|
|
{
|
|
if( IsSnapshotting() )
|
|
{
|
|
// NOTE: This only works because IsRenderingPaint
|
|
// really only affects lightmappedgeneric in a specific way.
|
|
// If we make it used more generally, then we'll need a pattern
|
|
// more similar to UsingEditor or UsingFlashlight
|
|
return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_PAINT );
|
|
}
|
|
else
|
|
{
|
|
if ( !g_pConfig->m_bPaintInGame || !g_pConfig->m_bPaintInMap )
|
|
return false;
|
|
return s_pShaderAPI->IsRenderingPaint();
|
|
}
|
|
}
|
|
|
|
bool CBaseShader::IsHDREnabled( void )
|
|
{
|
|
#ifdef _PS3
|
|
return true;
|
|
#else
|
|
// HDRFIXME! Need to fix this for vgui materials
|
|
HDRType_t hdr_mode = g_pHardwareConfig->GetHDRType();
|
|
return ( hdr_mode == HDR_TYPE_INTEGER ) || ( hdr_mode == HDR_TYPE_FLOAT );
|
|
#endif
|
|
}
|