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.
1826 lines
55 KiB
1826 lines
55 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//===========================================================================// |
|
|
|
#define DISABLE_PROTECTED_THINGS |
|
#include "togl/rendermechanism.h" |
|
#include "shadershadowdx8.h" |
|
#include "locald3dtypes.h" |
|
#include "utlvector.h" |
|
#include "shaderapi/ishaderutil.h" |
|
#include "shaderapidx8_global.h" |
|
#include "shaderapidx8.h" |
|
#include "materialsystem/imaterialsystemhardwareconfig.h" |
|
#include "materialsystem/imaterialsystem.h" |
|
#include "imeshdx8.h" |
|
#include "materialsystem/materialsystem_config.h" |
|
#include "vertexshaderdx8.h" |
|
|
|
// NOTE: This must be the last file included! |
|
#include "tier0/memdbgon.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// The DX8 implementation of the shader setup interface |
|
//----------------------------------------------------------------------------- |
|
class CShaderShadowDX8 : public IShaderShadowDX8 |
|
{ |
|
public: |
|
// constructor, destructor |
|
CShaderShadowDX8( ); |
|
virtual ~CShaderShadowDX8(); |
|
|
|
// Initialize render state |
|
void Init( ); |
|
|
|
// Sets the default state |
|
void SetDefaultState(); |
|
|
|
// Methods related to depth buffering |
|
void DepthFunc( ShaderDepthFunc_t depthFunc ); |
|
void EnableDepthWrites( bool bEnable ); |
|
void EnableDepthTest( bool bEnable ); |
|
void EnablePolyOffset( PolygonOffsetMode_t nOffsetMode ); |
|
|
|
// Methods related to stencil. obsolete |
|
virtual void EnableStencil( bool bEnable ) |
|
{ |
|
} |
|
virtual void StencilFunc( ShaderStencilFunc_t stencilFunc ) |
|
{ |
|
} |
|
virtual void StencilPassOp( ShaderStencilOp_t stencilOp ) |
|
{ |
|
} |
|
virtual void StencilFailOp( ShaderStencilOp_t stencilOp ) |
|
{ |
|
} |
|
virtual void StencilDepthFailOp( ShaderStencilOp_t stencilOp ) |
|
{ |
|
} |
|
virtual void StencilReference( int nReference ) |
|
{ |
|
} |
|
virtual void StencilMask( int nMask ) |
|
{ |
|
} |
|
virtual void StencilWriteMask( int nMask ) |
|
{ |
|
} |
|
|
|
// Suppresses/activates color writing |
|
void EnableColorWrites( bool bEnable ); |
|
void EnableAlphaWrites( bool bEnable ); |
|
|
|
// Methods related to alpha blending |
|
void EnableBlending( bool bEnable ); |
|
|
|
void BlendFunc( ShaderBlendFactor_t srcFactor, ShaderBlendFactor_t dstFactor ); |
|
void BlendOp( ShaderBlendOp_t blendOp ); |
|
void BlendOpSeparateAlpha( ShaderBlendOp_t blendOp ); |
|
|
|
// Alpha testing |
|
void EnableAlphaTest( bool bEnable ); |
|
void AlphaFunc( ShaderAlphaFunc_t alphaFunc, float alphaRef /* [0-1] */ ); |
|
|
|
// Wireframe/filled polygons |
|
void PolyMode( ShaderPolyModeFace_t face, ShaderPolyMode_t polyMode ); |
|
|
|
// Back face culling |
|
void EnableCulling( bool bEnable ); |
|
|
|
// constant color |
|
void EnableConstantColor( bool bEnable ); |
|
|
|
// Indicates we're going to light the model |
|
void EnableLighting( bool bEnable ); |
|
|
|
// Indicates specular lighting is going to be used |
|
void EnableSpecular( bool bEnable ); |
|
|
|
// Convert from linear to gamma color space on writes to frame buffer. |
|
void EnableSRGBWrite( bool bEnable ); |
|
|
|
// Convert from gamma to linear on texture fetch. |
|
void EnableSRGBRead( Sampler_t stage, bool bEnable ); |
|
|
|
// Set up appropriate shadow filtering state (such as Fetch4 on ATI) |
|
void SetShadowDepthFiltering( Sampler_t stage ); |
|
|
|
// Computes the vertex format |
|
virtual void VertexShaderVertexFormat( unsigned int nFlags, |
|
int nTexCoordCount, int* pTexCoordDimensions, int nUserDataSize ); |
|
|
|
// Pixel and vertex shader methods |
|
virtual void SetVertexShader( const char* pFileName, int nStaticVshIndex ); |
|
virtual void SetPixelShader( const char* pFileName, int nStaticPshIndex ); |
|
|
|
// Indicates we're going to be using the ambient cube |
|
void EnableAmbientLightCubeOnStage0( bool bEnable ); |
|
|
|
// Activate/deactivate skinning |
|
void EnableVertexBlend( bool bEnable ); |
|
|
|
// per texture unit stuff |
|
void OverbrightValue( TextureStage_t stage, float value ); |
|
void EnableTexture( Sampler_t stage, bool bEnable ); |
|
void EnableTexGen( TextureStage_t stage, bool bEnable ); |
|
void TexGen( TextureStage_t stage, ShaderTexGenParam_t param ); |
|
void TextureCoordinate( TextureStage_t stage, int useCoord ); |
|
|
|
// alternate method of specifying per-texture unit stuff, more flexible and more complicated |
|
// Can be used to specify different operation per channel (alpha/color)... |
|
void EnableCustomPixelPipe( bool bEnable ); |
|
void CustomTextureStages( int stageCount ); |
|
void CustomTextureOperation( TextureStage_t stage, ShaderTexChannel_t channel, |
|
ShaderTexOp_t op, ShaderTexArg_t arg1, ShaderTexArg_t arg2 ); |
|
|
|
// A simpler method of dealing with alpha modulation |
|
void EnableAlphaPipe( bool bEnable ); |
|
void EnableConstantAlpha( bool bEnable ); |
|
void EnableVertexAlpha( bool bEnable ); |
|
void EnableTextureAlpha( TextureStage_t stage, bool bEnable ); |
|
|
|
// helper functions |
|
void EnableSphereMapping( TextureStage_t stage, bool bEnable ); |
|
|
|
// Last call to be make before snapshotting |
|
void ComputeAggregateShadowState( ); |
|
|
|
// Gets at the shadow state |
|
const ShadowState_t & GetShadowState(); |
|
const ShadowShaderState_t & GetShadowShaderState(); |
|
|
|
// GR - Separate alpha blending |
|
void EnableBlendingSeparateAlpha( bool bEnable ); |
|
void BlendFuncSeparateAlpha( ShaderBlendFactor_t srcFactor, ShaderBlendFactor_t dstFactor ); |
|
|
|
void FogMode( ShaderFogMode_t fogMode ); |
|
void DisableFogGammaCorrection( bool bDisable ); |
|
|
|
void SetDiffuseMaterialSource( ShaderMaterialSource_t materialSource ); |
|
virtual void SetMorphFormat( MorphFormat_t flags ); |
|
|
|
// Alpha to coverage |
|
void EnableAlphaToCoverage( bool bEnable ); |
|
|
|
private: |
|
struct TextureStageState_t |
|
{ |
|
int m_TexCoordIndex; |
|
int m_TexCoordinate; |
|
float m_OverbrightVal; |
|
ShaderTexArg_t m_Arg[2][2]; |
|
ShaderTexOp_t m_Op[2]; |
|
unsigned char m_TexGenEnable:1; |
|
unsigned char m_TextureAlphaEnable:1; |
|
}; |
|
|
|
struct SamplerState_t |
|
{ |
|
bool m_TextureEnable : 1; |
|
}; |
|
|
|
// Computes the blend factor |
|
D3DBLEND BlendFuncValue( ShaderBlendFactor_t factor ) const; |
|
|
|
// Computes the blend op |
|
D3DBLENDOP BlendOpValue( ShaderBlendOp_t blendOp ) const; |
|
|
|
// Configures the FVF vertex shader |
|
void ConfigureFVFVertexShader( unsigned int flags ); |
|
void ConfigureCustomFVFVertexShader( unsigned int flags ); |
|
|
|
// Configures our texture indices |
|
void ConfigureTextureCoordinates( unsigned int flags ); |
|
|
|
// Returns a blend value based on overbrighting |
|
D3DTEXTUREOP OverbrightBlendValue( TextureStage_t stage ); |
|
|
|
// Sets the desired color and alpha op state |
|
void DrawFlags( unsigned int flags ); |
|
|
|
// Computes a vertex format for the draw flags |
|
VertexFormat_t FlagsToVertexFormat( int flags ) const; |
|
|
|
// Indicates we've got a constant color specified |
|
bool HasConstantColor() const; |
|
|
|
// Configures the alpha pipe |
|
void ConfigureAlphaPipe( unsigned int flags ); |
|
|
|
// returns true if we're using texture coordinates at a given stage |
|
bool IsUsingTextureCoordinates( Sampler_t stage ) const; |
|
|
|
// Recomputes the tex coord index |
|
void RecomputeTexCoordIndex( TextureStage_t stage ); |
|
|
|
|
|
// State needed to create the snapshots |
|
IMaterialSystemHardwareConfig* m_pHardwareConfig; |
|
|
|
// Separate alpha control? |
|
bool m_AlphaPipe; |
|
|
|
// Constant color state |
|
bool m_HasConstantColor; |
|
bool m_HasConstantAlpha; |
|
|
|
// Vertex color state |
|
bool m_HasVertexAlpha; |
|
|
|
// funky custom method of specifying shader state |
|
bool m_CustomTextureStageState; |
|
|
|
// Number of stages used by the custom pipeline |
|
int m_CustomTextureStages; |
|
|
|
// Number of bones... |
|
int m_NumBlendVertices; |
|
|
|
// Draw flags |
|
int m_DrawFlags; |
|
|
|
// Alpha blending... |
|
D3DBLEND m_SrcBlend; |
|
D3DBLEND m_DestBlend; |
|
D3DBLENDOP m_BlendOp; |
|
|
|
// GR - Separate alpha blending... |
|
D3DBLEND m_SrcBlendAlpha; |
|
D3DBLEND m_DestBlendAlpha; |
|
D3DBLENDOP m_BlendOpAlpha; |
|
|
|
// Alpha testing |
|
D3DCMPFUNC m_AlphaFunc; |
|
int m_AlphaRef; |
|
|
|
// Stencil |
|
D3DCMPFUNC m_StencilFunc; |
|
int m_StencilRef; |
|
int m_StencilMask; |
|
DWORD m_StencilFail; |
|
DWORD m_StencilZFail; |
|
DWORD m_StencilPass; |
|
int m_StencilWriteMask; |
|
|
|
// The current shadow state |
|
ShadowState_t m_ShadowState; |
|
ShadowShaderState_t m_ShadowShaderState; |
|
|
|
// State info stores with each texture stage |
|
TextureStageState_t m_TextureStage[MAX_TEXTURE_STAGES]; |
|
SamplerState_t m_SamplerState[MAX_SAMPLERS]; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Class factory |
|
//----------------------------------------------------------------------------- |
|
static CShaderShadowDX8 g_ShaderShadow; |
|
IShaderShadowDX8 *g_pShaderShadowDx8 = &g_ShaderShadow; |
|
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderShadowDX8, IShaderShadow, |
|
SHADERSHADOW_INTERFACE_VERSION, g_ShaderShadow ) |
|
|
|
//----------------------------------------------------------------------------- |
|
// Global instance |
|
//----------------------------------------------------------------------------- |
|
IShaderShadowDX8* ShaderShadow() |
|
{ |
|
return &g_ShaderShadow; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor, destructor |
|
//----------------------------------------------------------------------------- |
|
CShaderShadowDX8::CShaderShadowDX8( ) : |
|
m_DrawFlags(0), m_pHardwareConfig(0), m_HasConstantColor(false) |
|
{ |
|
memset( &m_ShadowState, 0, sizeof(m_ShadowState) ); |
|
memset( &m_TextureStage, 0, sizeof(m_TextureStage) ); |
|
} |
|
|
|
CShaderShadowDX8::~CShaderShadowDX8() |
|
{ |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Initialize render state |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::Init( ) |
|
{ |
|
m_pHardwareConfig = HardwareConfig(); |
|
|
|
// Clear out the shadow state |
|
memset( &m_ShadowState, 0, sizeof(m_ShadowState) ); |
|
|
|
// No funky custom methods.. |
|
m_CustomTextureStageState = false; |
|
|
|
// No constant color modulation |
|
m_HasConstantColor = false; |
|
m_HasConstantAlpha = false; |
|
m_HasVertexAlpha = false; |
|
|
|
m_ShadowShaderState.m_ModulateConstantColor = false; |
|
|
|
m_ShadowState.m_bDisableFogGammaCorrection = false; |
|
|
|
// By default we're using fixed function |
|
m_ShadowState.m_UsingFixedFunction = true; |
|
|
|
// Lighting off by default |
|
m_ShadowState.m_Lighting = false; |
|
|
|
// Pixel + vertex shaders |
|
m_ShadowShaderState.m_VertexShader = INVALID_SHADER; |
|
m_ShadowShaderState.m_PixelShader = INVALID_SHADER; |
|
m_ShadowShaderState.m_nStaticPshIndex = 0; |
|
m_ShadowShaderState.m_nStaticVshIndex = 0; |
|
m_ShadowShaderState.m_VertexUsage = 0; |
|
|
|
// Drawing nothing.. |
|
m_DrawFlags = 0; |
|
|
|
// No alpha control |
|
m_AlphaPipe = false; |
|
|
|
// Vertex blending |
|
m_NumBlendVertices = 0; |
|
m_ShadowState.m_VertexBlendEnable = false; |
|
|
|
// NOTE: If you change these defaults, change the code in ComputeAggregateShadowState + CreateTransitionTableEntry |
|
int i; |
|
for (i = 0; i < MAX_TEXTURE_STAGES; ++i) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_ColorOp = D3DTOP_DISABLE; |
|
m_ShadowState.m_TextureStage[i].m_ColorArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_ColorArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_DISABLE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_TexCoordIndex = i; |
|
} |
|
|
|
for (i = 0; i < MAX_SAMPLERS; ++i) |
|
{ |
|
m_ShadowState.m_SamplerState[i].m_TextureEnable = false; |
|
m_ShadowState.m_SamplerState[i].m_SRGBReadEnable = false; |
|
m_ShadowState.m_SamplerState[i].m_Fetch4Enable = false; |
|
#ifdef DX_TO_GL_ABSTRACTION |
|
m_ShadowState.m_SamplerState[i].m_ShadowFilterEnable = false; |
|
#endif |
|
// A *real* measure if the texture stage is being used. |
|
// we sometimes have to set the shadow state to not mirror this. |
|
m_SamplerState[i].m_TextureEnable = false; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets the default state |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::SetDefaultState() |
|
{ |
|
DepthFunc( SHADER_DEPTHFUNC_NEAREROREQUAL ); |
|
EnableDepthWrites( true ); |
|
EnableDepthTest( true ); |
|
EnableColorWrites( true ); |
|
EnableAlphaWrites( false ); |
|
EnableAlphaTest( false ); |
|
EnableLighting( false ); |
|
EnableConstantColor( false ); |
|
EnableBlending( false ); |
|
BlendFunc( SHADER_BLEND_ONE, SHADER_BLEND_ZERO ); |
|
BlendOp( SHADER_BLEND_OP_ADD ); |
|
// GR - separate alpha |
|
EnableBlendingSeparateAlpha( false ); |
|
BlendFuncSeparateAlpha( SHADER_BLEND_ONE, SHADER_BLEND_ZERO ); |
|
BlendOpSeparateAlpha( SHADER_BLEND_OP_ADD ); |
|
AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, 0.7f ); |
|
PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_FILL ); |
|
EnableCulling( true ); |
|
EnableAlphaToCoverage( false ); |
|
EnablePolyOffset( SHADER_POLYOFFSET_DISABLE ); |
|
EnableVertexBlend( false ); |
|
EnableSpecular( false ); |
|
EnableSRGBWrite( false ); |
|
DrawFlags( SHADER_DRAW_POSITION ); |
|
EnableCustomPixelPipe( false ); |
|
CustomTextureStages( 0 ); |
|
EnableAlphaPipe( false ); |
|
EnableConstantAlpha( false ); |
|
EnableVertexAlpha( false ); |
|
SetVertexShader( NULL, 0 ); |
|
SetPixelShader( NULL, 0 ); |
|
FogMode( SHADER_FOGMODE_DISABLED ); |
|
DisableFogGammaCorrection( false ); |
|
SetDiffuseMaterialSource( SHADER_MATERIALSOURCE_MATERIAL ); |
|
EnableStencil( false ); |
|
StencilFunc( SHADER_STENCILFUNC_ALWAYS ); |
|
StencilPassOp( SHADER_STENCILOP_KEEP ); |
|
StencilFailOp( SHADER_STENCILOP_KEEP ); |
|
StencilDepthFailOp( SHADER_STENCILOP_KEEP ); |
|
StencilReference( 0 ); |
|
StencilMask( 0xFFFFFFFF ); |
|
StencilWriteMask( 0xFFFFFFFF ); |
|
m_ShadowShaderState.m_VertexUsage = 0; |
|
|
|
int i; |
|
int nSamplerCount = HardwareConfig()->GetSamplerCount(); |
|
for( i = 0; i < nSamplerCount; i++ ) |
|
{ |
|
EnableTexture( (Sampler_t)i, false ); |
|
EnableSRGBRead( (Sampler_t)i, false ); |
|
} |
|
|
|
int nTextureStageCount = HardwareConfig()->GetTextureStageCount(); |
|
for( i = 0; i < nTextureStageCount; i++ ) |
|
{ |
|
EnableTexGen( (TextureStage_t)i, false ); |
|
OverbrightValue( (TextureStage_t)i, 1.0f ); |
|
EnableTextureAlpha( (TextureStage_t)i, false ); |
|
CustomTextureOperation( (TextureStage_t)i, SHADER_TEXCHANNEL_COLOR, |
|
SHADER_TEXOP_DISABLE, SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); |
|
CustomTextureOperation( (TextureStage_t)i, SHADER_TEXCHANNEL_ALPHA, |
|
SHADER_TEXOP_DISABLE, SHADER_TEXARG_TEXTURE, SHADER_TEXARG_PREVIOUSSTAGE ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets at the shadow state |
|
//----------------------------------------------------------------------------- |
|
const ShadowState_t &CShaderShadowDX8::GetShadowState() |
|
{ |
|
return m_ShadowState; |
|
} |
|
|
|
const ShadowShaderState_t &CShaderShadowDX8::GetShadowShaderState() |
|
{ |
|
return m_ShadowShaderState; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Depth functions... |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::DepthFunc( ShaderDepthFunc_t depthFunc ) |
|
{ |
|
D3DCMPFUNC zFunc; |
|
|
|
switch( depthFunc ) |
|
{ |
|
case SHADER_DEPTHFUNC_NEVER: |
|
zFunc = D3DCMP_NEVER; |
|
break; |
|
case SHADER_DEPTHFUNC_NEARER: |
|
zFunc = (ShaderUtil()->GetConfig().bReverseDepth ^ ReverseDepthOnX360()) ? D3DCMP_GREATER : D3DCMP_LESS; |
|
break; |
|
case SHADER_DEPTHFUNC_EQUAL: |
|
zFunc = D3DCMP_EQUAL; |
|
break; |
|
case SHADER_DEPTHFUNC_NEAREROREQUAL: |
|
zFunc = (ShaderUtil()->GetConfig().bReverseDepth ^ ReverseDepthOnX360()) ? D3DCMP_GREATEREQUAL : D3DCMP_LESSEQUAL; |
|
break; |
|
case SHADER_DEPTHFUNC_FARTHER: |
|
zFunc = (ShaderUtil()->GetConfig().bReverseDepth ^ ReverseDepthOnX360()) ? D3DCMP_LESS : D3DCMP_GREATER; |
|
break; |
|
case SHADER_DEPTHFUNC_NOTEQUAL: |
|
zFunc = D3DCMP_NOTEQUAL; |
|
break; |
|
case SHADER_DEPTHFUNC_FARTHEROREQUAL: |
|
zFunc = (ShaderUtil()->GetConfig().bReverseDepth ^ ReverseDepthOnX360()) ? D3DCMP_LESSEQUAL : D3DCMP_GREATEREQUAL; |
|
break; |
|
case SHADER_DEPTHFUNC_ALWAYS: |
|
zFunc = D3DCMP_ALWAYS; |
|
break; |
|
default: |
|
zFunc = D3DCMP_ALWAYS; |
|
Warning( "DepthFunc: invalid param\n" ); |
|
break; |
|
} |
|
|
|
m_ShadowState.m_ZFunc = zFunc; |
|
} |
|
|
|
void CShaderShadowDX8::EnableDepthWrites( bool bEnable ) |
|
{ |
|
m_ShadowState.m_ZWriteEnable = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::EnableDepthTest( bool bEnable ) |
|
{ |
|
m_ShadowState.m_ZEnable = bEnable ? D3DZB_TRUE : D3DZB_FALSE; |
|
} |
|
|
|
void CShaderShadowDX8::EnablePolyOffset( PolygonOffsetMode_t nOffsetMode ) |
|
{ |
|
m_ShadowState.m_ZBias = nOffsetMode; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Color write state |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableColorWrites( bool bEnable ) |
|
{ |
|
if (bEnable) |
|
{ |
|
m_ShadowState.m_ColorWriteEnable |= D3DCOLORWRITEENABLE_BLUE | |
|
D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_ColorWriteEnable &= ~( D3DCOLORWRITEENABLE_BLUE | |
|
D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED ); |
|
} |
|
} |
|
|
|
void CShaderShadowDX8::EnableAlphaWrites( bool bEnable ) |
|
{ |
|
if (bEnable) |
|
{ |
|
m_ShadowState.m_ColorWriteEnable |= D3DCOLORWRITEENABLE_ALPHA; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_ColorWriteEnable &= ~D3DCOLORWRITEENABLE_ALPHA; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Alpha blending states |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableBlending( bool bEnable ) |
|
{ |
|
m_ShadowState.m_AlphaBlendEnable = bEnable; |
|
} |
|
|
|
// GR - separate alpha |
|
void CShaderShadowDX8::EnableBlendingSeparateAlpha( bool bEnable ) |
|
{ |
|
m_ShadowState.m_SeparateAlphaBlendEnable = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::EnableAlphaTest( bool bEnable ) |
|
{ |
|
m_ShadowState.m_AlphaTestEnable = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::AlphaFunc( ShaderAlphaFunc_t alphaFunc, float alphaRef /* [0-1] */ ) |
|
{ |
|
D3DCMPFUNC d3dCmpFunc; |
|
|
|
switch( alphaFunc ) |
|
{ |
|
case SHADER_ALPHAFUNC_NEVER: |
|
d3dCmpFunc = D3DCMP_NEVER; |
|
break; |
|
case SHADER_ALPHAFUNC_LESS: |
|
d3dCmpFunc = D3DCMP_LESS; |
|
break; |
|
case SHADER_ALPHAFUNC_EQUAL: |
|
d3dCmpFunc = D3DCMP_EQUAL; |
|
break; |
|
case SHADER_ALPHAFUNC_LEQUAL: |
|
d3dCmpFunc = D3DCMP_LESSEQUAL; |
|
break; |
|
case SHADER_ALPHAFUNC_GREATER: |
|
d3dCmpFunc = D3DCMP_GREATER; |
|
break; |
|
case SHADER_ALPHAFUNC_NOTEQUAL: |
|
d3dCmpFunc = D3DCMP_NOTEQUAL; |
|
break; |
|
case SHADER_ALPHAFUNC_GEQUAL: |
|
d3dCmpFunc = D3DCMP_GREATEREQUAL; |
|
break; |
|
case SHADER_ALPHAFUNC_ALWAYS: |
|
d3dCmpFunc = D3DCMP_ALWAYS; |
|
break; |
|
default: |
|
Warning( "AlphaFunc: invalid param\n" ); |
|
return; |
|
} |
|
|
|
m_AlphaFunc = d3dCmpFunc; |
|
m_AlphaRef = (int)(alphaRef * 255); |
|
} |
|
|
|
D3DBLEND CShaderShadowDX8::BlendFuncValue( ShaderBlendFactor_t factor ) const |
|
{ |
|
switch( factor ) |
|
{ |
|
case SHADER_BLEND_ZERO: |
|
return D3DBLEND_ZERO; |
|
|
|
case SHADER_BLEND_ONE: |
|
return D3DBLEND_ONE; |
|
|
|
case SHADER_BLEND_DST_COLOR: |
|
return D3DBLEND_DESTCOLOR; |
|
|
|
case SHADER_BLEND_ONE_MINUS_DST_COLOR: |
|
return D3DBLEND_INVDESTCOLOR; |
|
|
|
case SHADER_BLEND_SRC_ALPHA: |
|
return D3DBLEND_SRCALPHA; |
|
|
|
case SHADER_BLEND_ONE_MINUS_SRC_ALPHA: |
|
return D3DBLEND_INVSRCALPHA; |
|
|
|
case SHADER_BLEND_DST_ALPHA: |
|
return D3DBLEND_DESTALPHA; |
|
|
|
case SHADER_BLEND_ONE_MINUS_DST_ALPHA: |
|
return D3DBLEND_INVDESTALPHA; |
|
|
|
case SHADER_BLEND_SRC_ALPHA_SATURATE: |
|
return D3DBLEND_SRCALPHASAT; |
|
|
|
case SHADER_BLEND_SRC_COLOR: |
|
return D3DBLEND_SRCCOLOR; |
|
|
|
case SHADER_BLEND_ONE_MINUS_SRC_COLOR: |
|
return D3DBLEND_INVSRCCOLOR; |
|
} |
|
|
|
Warning( "BlendFunc: invalid factor\n" ); |
|
return D3DBLEND_ONE; |
|
} |
|
|
|
D3DBLENDOP CShaderShadowDX8::BlendOpValue( ShaderBlendOp_t blendOp ) const |
|
{ |
|
switch( blendOp ) |
|
{ |
|
case SHADER_BLEND_OP_ADD: |
|
return D3DBLENDOP_ADD; |
|
|
|
case SHADER_BLEND_OP_SUBTRACT: |
|
return D3DBLENDOP_SUBTRACT; |
|
|
|
case SHADER_BLEND_OP_REVSUBTRACT: |
|
return D3DBLENDOP_REVSUBTRACT; |
|
|
|
case SHADER_BLEND_OP_MIN: |
|
return D3DBLENDOP_MIN; |
|
|
|
case SHADER_BLEND_OP_MAX: |
|
return D3DBLENDOP_MAX; |
|
} |
|
|
|
Warning( "BlendOp: invalid op\n" ); |
|
return D3DBLENDOP_ADD; |
|
} |
|
|
|
void CShaderShadowDX8::BlendFunc( ShaderBlendFactor_t srcFactor, ShaderBlendFactor_t dstFactor ) |
|
{ |
|
D3DBLEND d3dSrcFactor = BlendFuncValue( srcFactor ); |
|
D3DBLEND d3dDstFactor = BlendFuncValue( dstFactor ); |
|
m_SrcBlend = d3dSrcFactor; |
|
m_DestBlend = d3dDstFactor; |
|
} |
|
|
|
// GR - separate alpha blend |
|
void CShaderShadowDX8::BlendFuncSeparateAlpha( ShaderBlendFactor_t srcFactor, ShaderBlendFactor_t dstFactor ) |
|
{ |
|
D3DBLEND d3dSrcFactor = BlendFuncValue( srcFactor ); |
|
D3DBLEND d3dDstFactor = BlendFuncValue( dstFactor ); |
|
m_SrcBlendAlpha = d3dSrcFactor; |
|
m_DestBlendAlpha = d3dDstFactor; |
|
} |
|
|
|
void CShaderShadowDX8::BlendOp( ShaderBlendOp_t blendOp ) |
|
{ |
|
m_BlendOp = BlendOpValue( blendOp ); |
|
} |
|
|
|
void CShaderShadowDX8::BlendOpSeparateAlpha( ShaderBlendOp_t blendOp ) |
|
{ |
|
m_BlendOpAlpha = BlendOpValue( blendOp ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Polygon fill mode states |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::PolyMode( ShaderPolyModeFace_t face, ShaderPolyMode_t polyMode ) |
|
{ |
|
// DX8 can't handle different modes on front and back faces |
|
// FIXME: Assert( face == SHADER_POLYMODEFACE_FRONT_AND_BACK ); |
|
if (face == SHADER_POLYMODEFACE_BACK) |
|
return; |
|
|
|
D3DFILLMODE fillMode; |
|
switch( polyMode ) |
|
{ |
|
case SHADER_POLYMODE_POINT: |
|
fillMode = D3DFILL_POINT; |
|
break; |
|
case SHADER_POLYMODE_LINE: |
|
fillMode = D3DFILL_WIREFRAME; |
|
break; |
|
case SHADER_POLYMODE_FILL: |
|
fillMode = D3DFILL_SOLID; |
|
break; |
|
default: |
|
Warning( "PolyMode: invalid poly mode\n" ); |
|
return; |
|
} |
|
|
|
m_ShadowState.m_FillMode = fillMode; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Backface cull states |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableCulling( bool bEnable ) |
|
{ |
|
m_ShadowState.m_CullEnable = bEnable; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Alpha to coverage |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableAlphaToCoverage( bool bEnable ) |
|
{ |
|
m_ShadowState.m_EnableAlphaToCoverage = bEnable; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Indicates we've got a constant color specified |
|
//----------------------------------------------------------------------------- |
|
bool CShaderShadowDX8::HasConstantColor() const |
|
{ |
|
return m_HasConstantColor; |
|
} |
|
|
|
void CShaderShadowDX8::EnableConstantColor( bool bEnable ) |
|
{ |
|
m_HasConstantColor = bEnable; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// A simpler method of dealing with alpha modulation |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableAlphaPipe( bool bEnable ) |
|
{ |
|
m_AlphaPipe = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::EnableConstantAlpha( bool bEnable ) |
|
{ |
|
m_HasConstantAlpha = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::EnableVertexAlpha( bool bEnable ) |
|
{ |
|
m_HasVertexAlpha = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::EnableTextureAlpha( TextureStage_t stage, bool bEnable ) |
|
{ |
|
if ( stage < m_pHardwareConfig->GetSamplerCount() ) |
|
{ |
|
m_TextureStage[stage].m_TextureAlphaEnable = bEnable; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Indicates we're going to light the model |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableLighting( bool bEnable ) |
|
{ |
|
m_ShadowState.m_Lighting = bEnable; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Enables specular lighting (lighting has also got to be enabled) |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableSpecular( bool bEnable ) |
|
{ |
|
m_ShadowState.m_SpecularEnable = bEnable; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Enables auto-conversion from linear to gamma space on write to framebuffer. |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableSRGBWrite( bool bEnable ) |
|
{ |
|
if ( m_pHardwareConfig->SupportsSRGB() ) |
|
{ |
|
m_ShadowState.m_SRGBWriteEnable = bEnable; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_SRGBWriteEnable = false; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Activate/deactivate skinning |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableVertexBlend( bool bEnable ) |
|
{ |
|
// Activate/deactivate skinning. Indexed blending is automatically |
|
// enabled if it's available for this hardware. When blending is enabled, |
|
// we allocate enough room for 3 weights (max allowed) |
|
if ((m_pHardwareConfig->MaxBlendMatrices() > 0) || (!bEnable)) |
|
{ |
|
m_ShadowState.m_VertexBlendEnable = bEnable; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Texturemapping state |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableTexture( Sampler_t sampler, bool bEnable ) |
|
{ |
|
if ( sampler < m_pHardwareConfig->GetSamplerCount() ) |
|
{ |
|
m_SamplerState[sampler].m_TextureEnable = bEnable; |
|
} |
|
else |
|
{ |
|
Warning( "Attempting to bind a texture to an invalid sampler (%d)!\n", sampler ); |
|
} |
|
} |
|
|
|
void CShaderShadowDX8::EnableSRGBRead( Sampler_t sampler, bool bEnable ) |
|
{ |
|
if ( !m_pHardwareConfig->SupportsSRGB() ) |
|
{ |
|
m_ShadowState.m_SamplerState[sampler].m_SRGBReadEnable = false; |
|
return; |
|
} |
|
|
|
if ( sampler < m_pHardwareConfig->GetSamplerCount() ) |
|
{ |
|
m_ShadowState.m_SamplerState[sampler].m_SRGBReadEnable = bEnable; |
|
} |
|
else |
|
{ |
|
Warning( "Attempting set SRGBRead state on an invalid sampler (%d)!\n", sampler ); |
|
} |
|
} |
|
|
|
void CShaderShadowDX8::SetShadowDepthFiltering( Sampler_t stage ) |
|
{ |
|
#ifdef DX_TO_GL_ABSTRACTION |
|
if ( stage < m_pHardwareConfig->GetSamplerCount() ) |
|
{ |
|
m_ShadowState.m_SamplerState[stage].m_ShadowFilterEnable = true; |
|
return; |
|
} |
|
#else |
|
if ( !m_pHardwareConfig->SupportsFetch4() ) |
|
{ |
|
m_ShadowState.m_SamplerState[stage].m_Fetch4Enable = false; |
|
return; |
|
} |
|
|
|
if ( stage < m_pHardwareConfig->GetSamplerCount() ) |
|
{ |
|
m_ShadowState.m_SamplerState[stage].m_Fetch4Enable = true; |
|
return; |
|
} |
|
#endif |
|
|
|
Warning( "Attempting set shadow filtering state on an invalid sampler (%d)!\n", stage ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Binds texture coordinates to a particular stage... |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::TextureCoordinate( TextureStage_t stage, int useTexCoord ) |
|
{ |
|
if ( stage < m_pHardwareConfig->GetTextureStageCount() ) |
|
{ |
|
m_TextureStage[stage].m_TexCoordinate = useTexCoord; |
|
|
|
// Need to recompute the texCoordIndex, since that's affected by this |
|
RecomputeTexCoordIndex(stage); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Automatic texture coordinate generation |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::RecomputeTexCoordIndex( TextureStage_t stage ) |
|
{ |
|
int texCoordIndex = m_TextureStage[stage].m_TexCoordinate; |
|
if (m_TextureStage[stage].m_TexGenEnable) |
|
texCoordIndex |= m_TextureStage[stage].m_TexCoordIndex; |
|
m_ShadowState.m_TextureStage[stage].m_TexCoordIndex = texCoordIndex; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Automatic texture coordinate generation |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableTexGen( TextureStage_t stage, bool bEnable ) |
|
{ |
|
if ( stage >= m_pHardwareConfig->GetTextureStageCount() ) |
|
{ |
|
Assert( 0 ); |
|
return; |
|
} |
|
|
|
m_TextureStage[stage].m_TexGenEnable = bEnable; |
|
RecomputeTexCoordIndex(stage); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Automatic texture coordinate generation |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::TexGen( TextureStage_t stage, ShaderTexGenParam_t param ) |
|
{ |
|
#ifdef FIXED_FUNCTION_PIPELINE |
|
if ( stage >= m_pHardwareConfig->GetTextureStageCount() ) |
|
return; |
|
|
|
switch( param ) |
|
{ |
|
case SHADER_TEXGENPARAM_OBJECT_LINEAR: |
|
m_TextureStage[stage].m_TexCoordIndex = 0; |
|
break; |
|
case SHADER_TEXGENPARAM_EYE_LINEAR: |
|
m_TextureStage[stage].m_TexCoordIndex = D3DTSS_TCI_CAMERASPACEPOSITION; |
|
break; |
|
case SHADER_TEXGENPARAM_SPHERE_MAP: |
|
if ( m_pHardwareConfig->SupportsSpheremapping() ) |
|
{ |
|
m_TextureStage[stage].m_TexCoordIndex = D3DTSS_TCI_SPHEREMAP; |
|
} |
|
else |
|
{ |
|
m_TextureStage[stage].m_TexCoordIndex = D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR; |
|
} |
|
break; |
|
case SHADER_TEXGENPARAM_CAMERASPACEREFLECTIONVECTOR: |
|
m_TextureStage[stage].m_TexCoordIndex = D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR; |
|
break; |
|
case SHADER_TEXGENPARAM_CAMERASPACENORMAL: |
|
m_TextureStage[stage].m_TexCoordIndex = D3DTSS_TCI_CAMERASPACENORMAL; |
|
break; |
|
} |
|
|
|
// Set the board state... |
|
RecomputeTexCoordIndex(stage); |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Overbrighting |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::OverbrightValue( TextureStage_t stage, float value ) |
|
{ |
|
if ( m_pHardwareConfig->SupportsOverbright() && |
|
( stage < m_pHardwareConfig->GetTextureStageCount() ) ) |
|
{ |
|
m_TextureStage[stage].m_OverbrightVal = value; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// alternate method of specifying per-texture unit stuff, more flexible and more complicated |
|
// Can be used to specify different operation per channel (alpha/color)... |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::EnableCustomPixelPipe( bool bEnable ) |
|
{ |
|
m_CustomTextureStageState = bEnable; |
|
} |
|
|
|
void CShaderShadowDX8::CustomTextureStages( int stageCount ) |
|
{ |
|
m_CustomTextureStages = stageCount; |
|
Assert( stageCount <= m_pHardwareConfig->GetTextureStageCount() ); |
|
if ( stageCount > m_pHardwareConfig->GetTextureStageCount() ) |
|
stageCount = m_pHardwareConfig->GetTextureStageCount(); |
|
} |
|
|
|
void CShaderShadowDX8::CustomTextureOperation( TextureStage_t stage, |
|
ShaderTexChannel_t channel, ShaderTexOp_t op, ShaderTexArg_t arg1, ShaderTexArg_t arg2 ) |
|
{ |
|
m_TextureStage[stage].m_Op[channel]= op; |
|
m_TextureStage[stage].m_Arg[channel][0] = arg1; |
|
m_TextureStage[stage].m_Arg[channel][1] = arg2; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Compute the vertex format from vertex descriptor flags |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::VertexShaderVertexFormat( unsigned int nFlags, |
|
int nTexCoordCount, int* pTexCoordDimensions, int nUserDataSize ) |
|
{ |
|
// Code that creates a Mesh should specify whether it contains bone weights+indices, *not* the shader. |
|
Assert( ( nFlags & VERTEX_BONE_INDEX ) == 0 ); |
|
nFlags &= ~VERTEX_BONE_INDEX; |
|
|
|
// This indicates we're using a vertex shader |
|
nFlags |= VERTEX_FORMAT_VERTEX_SHADER; |
|
m_ShadowShaderState.m_VertexUsage = MeshMgr()->ComputeVertexFormat( nFlags, nTexCoordCount, |
|
pTexCoordDimensions, 0, nUserDataSize ); |
|
m_ShadowState.m_UsingFixedFunction = false; |
|
|
|
// Avoid an error if vertex stream 0 is too narrow |
|
if ( CVertexBufferBase::VertexFormatSize( m_ShadowShaderState.m_VertexUsage ) <= 16 ) |
|
{ |
|
// FIXME: this is only necessary because we |
|
// (a) put the flex normal/position stream in ALL vertex decls |
|
// (b) bind stream 0's VB to stream 2 if there is no actual flex data |
|
// ...it would be far more sensible to not add stream 2 to all vertex decls. |
|
static bool bComplained = false; |
|
if( !bComplained ) |
|
{ |
|
Warning( "ERROR: shader asking for a too-narrow vertex format - you will see errors if running with debug D3D DLLs!\n\tPadding the vertex format with extra texcoords\n\tWill not warn again.\n" ); |
|
bComplained = true; |
|
} |
|
// All vertex formats should contain position... |
|
Assert( nFlags & VERTEX_POSITION ); |
|
nFlags |= VERTEX_POSITION; |
|
// This error should occur only if we have zero texcoords, or if we have a single, 1-D texcoord |
|
Assert( ( nTexCoordCount == 0 ) || |
|
( ( nTexCoordCount == 1 ) && pTexCoordDimensions && ( pTexCoordDimensions[0] == 1 ) ) ); |
|
nTexCoordCount = 1; |
|
m_ShadowShaderState.m_VertexUsage = MeshMgr()->ComputeVertexFormat( nFlags, nTexCoordCount, NULL, 0, nUserDataSize ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Compute the vertex format from vertex descriptor flags |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::SetMorphFormat( MorphFormat_t flags ) |
|
{ |
|
m_ShadowShaderState.m_MorphUsage = flags; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Pixel and vertex shader methods |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::SetVertexShader( const char* pFileName, int nStaticVshIndex ) |
|
{ |
|
char debugLabel[500] = ""; |
|
#ifdef DX_TO_GL_ABSTRACTION |
|
Q_snprintf( debugLabel, sizeof(debugLabel), "vs-file %s vs-index %d", pFileName, nStaticVshIndex ); |
|
#endif |
|
|
|
m_ShadowShaderState.m_VertexShader = ShaderManager()->CreateVertexShader( pFileName, nStaticVshIndex, debugLabel ); |
|
m_ShadowShaderState.m_nStaticVshIndex = nStaticVshIndex; |
|
} |
|
|
|
void CShaderShadowDX8::SetPixelShader( const char* pFileName, int nStaticPshIndex ) |
|
{ |
|
char debugLabel[500] = ""; |
|
#ifdef DX_TO_GL_ABSTRACTION |
|
Q_snprintf( debugLabel, sizeof(debugLabel), "ps-file %s ps-index %d", pFileName, nStaticPshIndex ); |
|
#endif |
|
|
|
m_ShadowShaderState.m_PixelShader = ShaderManager()->CreatePixelShader( pFileName, nStaticPshIndex, debugLabel ); |
|
m_ShadowShaderState.m_nStaticPshIndex = nStaticPshIndex; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// NOTE: See Version 5 of this file for NVidia 8-stage shader stuff |
|
//----------------------------------------------------------------------------- |
|
inline bool CShaderShadowDX8::IsUsingTextureCoordinates( Sampler_t sampler ) const |
|
{ |
|
return m_SamplerState[sampler].m_TextureEnable; |
|
} |
|
|
|
inline D3DTEXTUREOP CShaderShadowDX8::OverbrightBlendValue( TextureStage_t stage ) |
|
{ |
|
D3DTEXTUREOP colorop; |
|
if (m_TextureStage[stage].m_OverbrightVal < 2.0F) |
|
colorop = D3DTOP_MODULATE; |
|
else if (m_TextureStage[stage].m_OverbrightVal < 4.0F) |
|
colorop = D3DTOP_MODULATE2X; |
|
else |
|
colorop = D3DTOP_MODULATE4X; |
|
return colorop; |
|
} |
|
|
|
static inline int ComputeArg( ShaderTexArg_t arg ) |
|
{ |
|
switch(arg) |
|
{ |
|
case SHADER_TEXARG_TEXTURE: |
|
return D3DTA_TEXTURE; |
|
|
|
case SHADER_TEXARG_ZERO: |
|
return D3DTA_SPECULAR | D3DTA_COMPLEMENT; |
|
|
|
case SHADER_TEXARG_ONE: |
|
return D3DTA_SPECULAR; |
|
|
|
case SHADER_TEXARG_TEXTUREALPHA: |
|
return D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE; |
|
|
|
case SHADER_TEXARG_INVTEXTUREALPHA: |
|
return D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE | D3DTA_COMPLEMENT; |
|
|
|
case SHADER_TEXARG_NONE: |
|
case SHADER_TEXARG_VERTEXCOLOR: |
|
return D3DTA_DIFFUSE; |
|
|
|
case SHADER_TEXARG_SPECULARCOLOR: |
|
return D3DTA_SPECULAR; |
|
|
|
case SHADER_TEXARG_CONSTANTCOLOR: |
|
return D3DTA_TFACTOR; |
|
|
|
case SHADER_TEXARG_PREVIOUSSTAGE: |
|
return D3DTA_CURRENT; |
|
} |
|
|
|
Assert(0); |
|
return D3DTA_TEXTURE; |
|
} |
|
|
|
static inline D3DTEXTUREOP ComputeOp( ShaderTexOp_t op ) |
|
{ |
|
switch(op) |
|
{ |
|
case SHADER_TEXOP_MODULATE: |
|
return D3DTOP_MODULATE; |
|
|
|
case SHADER_TEXOP_MODULATE2X: |
|
return D3DTOP_MODULATE2X; |
|
|
|
case SHADER_TEXOP_MODULATE4X: |
|
return D3DTOP_MODULATE4X; |
|
|
|
case SHADER_TEXOP_SELECTARG1: |
|
return D3DTOP_SELECTARG1; |
|
|
|
case SHADER_TEXOP_SELECTARG2: |
|
return D3DTOP_SELECTARG2; |
|
|
|
case SHADER_TEXOP_ADD: |
|
return D3DTOP_ADD; |
|
|
|
case SHADER_TEXOP_SUBTRACT: |
|
return D3DTOP_SUBTRACT; |
|
|
|
case SHADER_TEXOP_ADDSIGNED2X: |
|
return D3DTOP_ADDSIGNED2X; |
|
|
|
case SHADER_TEXOP_BLEND_CONSTANTALPHA: |
|
return D3DTOP_BLENDFACTORALPHA; |
|
|
|
case SHADER_TEXOP_BLEND_PREVIOUSSTAGEALPHA: |
|
return D3DTOP_BLENDCURRENTALPHA; |
|
|
|
case SHADER_TEXOP_BLEND_TEXTUREALPHA: |
|
return D3DTOP_BLENDTEXTUREALPHA; |
|
|
|
case SHADER_TEXOP_MODULATECOLOR_ADDALPHA: |
|
return D3DTOP_MODULATECOLOR_ADDALPHA; |
|
|
|
case SHADER_TEXOP_MODULATEINVCOLOR_ADDALPHA: |
|
return D3DTOP_MODULATEINVCOLOR_ADDALPHA; |
|
|
|
case SHADER_TEXOP_DOTPRODUCT3: |
|
return D3DTOP_DOTPRODUCT3; |
|
|
|
case SHADER_TEXOP_DISABLE: |
|
return D3DTOP_DISABLE; |
|
} |
|
|
|
Assert(0); |
|
return D3DTOP_MODULATE; |
|
} |
|
|
|
void CShaderShadowDX8::ConfigureCustomFVFVertexShader( unsigned int flags ) |
|
{ |
|
int i; |
|
for ( i = 0; i < m_CustomTextureStages; ++i) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_ColorArg1 = ComputeArg( m_TextureStage[i].m_Arg[0][0] ); |
|
m_ShadowState.m_TextureStage[i].m_ColorArg2 = ComputeArg( m_TextureStage[i].m_Arg[0][1] ); |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = ComputeArg( m_TextureStage[i].m_Arg[1][0] ); |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = ComputeArg( m_TextureStage[i].m_Arg[1][1] ); |
|
m_ShadowState.m_TextureStage[i].m_ColorOp = ComputeOp( m_TextureStage[i].m_Op[0] ); |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = ComputeOp( m_TextureStage[i].m_Op[1] ); |
|
} |
|
|
|
// Deal with texture stage 1 -> n |
|
for ( i = m_CustomTextureStages; i < m_pHardwareConfig->GetTextureStageCount(); ++i ) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_ColorArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_ColorArg2 = D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_ColorOp = D3DTOP_DISABLE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_DISABLE; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets up the alpha texture stage state |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::ConfigureAlphaPipe( unsigned int flags ) |
|
{ |
|
// Are we using color? |
|
bool isUsingVertexAlpha = m_HasVertexAlpha && ((flags & SHADER_DRAW_COLOR) != 0); |
|
bool isUsingConstantAlpha = m_HasConstantAlpha; |
|
|
|
int lastTextureStage = m_pHardwareConfig->GetTextureStageCount() - 1; |
|
while ( lastTextureStage >= 0 ) |
|
{ |
|
if ( m_TextureStage[lastTextureStage].m_TextureAlphaEnable ) |
|
break; |
|
--lastTextureStage; |
|
} |
|
|
|
for ( int i = 0; i < m_pHardwareConfig->GetTextureStageCount(); ++i ) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_MODULATE; |
|
if ( m_TextureStage[i].m_TextureAlphaEnable ) |
|
{ |
|
if (i == 0) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = |
|
isUsingConstantAlpha ? D3DTA_TFACTOR : D3DTA_DIFFUSE; |
|
if (!isUsingConstantAlpha && !isUsingVertexAlpha) |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_SELECTARG1; |
|
if (isUsingConstantAlpha) |
|
isUsingConstantAlpha = false; |
|
else if (isUsingVertexAlpha) |
|
isUsingVertexAlpha = false; |
|
} |
|
else |
|
{ |
|
// Deal with texture stage 0 |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_CURRENT; |
|
} |
|
} |
|
else |
|
{ |
|
// Blat out unused stages |
|
if ((i > lastTextureStage) && !isUsingVertexAlpha && !isUsingConstantAlpha) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_DISABLE; |
|
continue; |
|
} |
|
|
|
// No texture coordinates; try to fold in vertex or constant alpha |
|
if (i == 0) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_DIFFUSE; |
|
if (isUsingVertexAlpha) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = |
|
isUsingConstantAlpha ? D3DTOP_MODULATE : D3DTOP_SELECTARG2; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_SELECTARG1; |
|
} |
|
isUsingVertexAlpha = false; |
|
isUsingConstantAlpha = false; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_CURRENT; |
|
if (isUsingConstantAlpha) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_TFACTOR; |
|
isUsingConstantAlpha = false; |
|
} |
|
else if (isUsingVertexAlpha) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_DIFFUSE; |
|
isUsingVertexAlpha = false; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_DIFFUSE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_SELECTARG1; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets up the texture stage state |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::ConfigureFVFVertexShader( unsigned int flags ) |
|
{ |
|
// For non-modulation, we can't really use the path below... |
|
if (m_CustomTextureStageState) |
|
{ |
|
ConfigureCustomFVFVertexShader( flags ); |
|
return; |
|
} |
|
|
|
// Deal with texture stage 0 |
|
m_ShadowState.m_TextureStage[0].m_ColorArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[0].m_ColorArg2 = D3DTA_DIFFUSE; |
|
m_ShadowState.m_TextureStage[0].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[0].m_AlphaArg2 = D3DTA_DIFFUSE; |
|
|
|
// Are we using color? |
|
bool isUsingVertexColor = (flags & SHADER_DRAW_COLOR) != 0; |
|
bool isUsingConstantColor = (flags & SHADER_HAS_CONSTANT_COLOR) != 0; |
|
|
|
// Are we using texture coordinates? |
|
if ( IsUsingTextureCoordinates( SHADER_SAMPLER0 ) ) |
|
{ |
|
if (isUsingVertexColor) |
|
{ |
|
m_ShadowState.m_TextureStage[0].m_ColorOp = OverbrightBlendValue(SHADER_TEXTURE_STAGE0); |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_MODULATE; |
|
} |
|
else |
|
{ |
|
// Just blend in the constant color here, and don't blend it in below |
|
m_ShadowState.m_TextureStage[0].m_ColorArg2 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_AlphaArg2 = D3DTA_TFACTOR; |
|
isUsingConstantColor = false; |
|
|
|
m_ShadowState.m_TextureStage[0].m_ColorOp = OverbrightBlendValue(SHADER_TEXTURE_STAGE0); |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_MODULATE; |
|
} |
|
} |
|
else |
|
{ |
|
// Are we using color? |
|
if (isUsingVertexColor) |
|
{ |
|
// Color, but no texture |
|
if ( m_TextureStage[0].m_OverbrightVal < 2.0f ) |
|
{ |
|
// Use diffuse * constant color, if we have a constant color |
|
if (isUsingConstantColor) |
|
{ |
|
m_ShadowState.m_TextureStage[0].m_ColorArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_AlphaArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_ColorOp = OverbrightBlendValue((TextureStage_t)0); |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_MODULATE; |
|
|
|
// This'll make sure we don't apply the constant color again below |
|
isUsingConstantColor = false; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_TextureStage[0].m_ColorOp = D3DTOP_SELECTARG2; |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_SELECTARG2; |
|
} |
|
} |
|
else if (m_TextureStage[0].m_OverbrightVal < 4.0f) |
|
{ |
|
// Produce diffuse + diffuse |
|
m_ShadowState.m_TextureStage[0].m_ColorArg1 = D3DTA_DIFFUSE; |
|
m_ShadowState.m_TextureStage[0].m_ColorOp = D3DTOP_ADD; |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_SELECTARG2; |
|
} |
|
else |
|
{ |
|
// no 4x overbright yet! |
|
Assert(0); |
|
} |
|
} |
|
else |
|
{ |
|
// No texture, no color |
|
if (isUsingConstantColor) |
|
{ |
|
m_ShadowState.m_TextureStage[0].m_ColorArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_AlphaArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_ColorOp = D3DTOP_SELECTARG1; |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_SELECTARG1; |
|
|
|
// This'll make sure we don't apply the constant color again below |
|
isUsingConstantColor = false; |
|
} |
|
else |
|
{ |
|
// Deal with texture stage 0 |
|
m_ShadowState.m_TextureStage[0].m_ColorArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_AlphaArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[0].m_ColorOp = D3DTOP_SELECTARG1; |
|
m_ShadowState.m_TextureStage[0].m_AlphaOp = D3DTOP_SELECTARG1; |
|
} |
|
} |
|
} |
|
|
|
// Deal with texture stage 1 -> n |
|
int lastUsedTextureStage = 0; |
|
for ( int i = 1; i < m_pHardwareConfig->GetTextureStageCount(); ++i ) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_ColorArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_ColorArg2 = D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = D3DTA_CURRENT; |
|
|
|
// Not doing anything? Disable the stage |
|
if ( !IsUsingTextureCoordinates( (Sampler_t)i ) ) |
|
{ |
|
if (m_TextureStage[i].m_OverbrightVal < 2.0f) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_ColorOp = D3DTOP_DISABLE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_DISABLE; |
|
} |
|
else |
|
{ |
|
// Here, we're modulating. Add in the constant color if we need to... |
|
m_ShadowState.m_TextureStage[i].m_ColorArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TFACTOR; |
|
|
|
m_ShadowState.m_TextureStage[i].m_ColorOp = OverbrightBlendValue((TextureStage_t)i); |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_MODULATE; |
|
|
|
isUsingConstantColor = false; |
|
lastUsedTextureStage = i; |
|
} |
|
} |
|
else |
|
{ |
|
// Here, we're modulating. Keep track of the last modulation stage, |
|
// cause the constant color modulation comes in the stage after that |
|
lastUsedTextureStage = i; |
|
m_ShadowState.m_TextureStage[i].m_ColorOp = OverbrightBlendValue((TextureStage_t)i); |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_MODULATE; |
|
} |
|
} |
|
|
|
// massive amounts of suck: gotta overbright here if we really |
|
// wanted to overbright stage0 but couldn't because of the add. |
|
// This isn't totally correct, but there's no way around putting it here |
|
// because we can't texture out of stage2 on low or medium end hardware |
|
m_ShadowShaderState.m_ModulateConstantColor = false; |
|
if (isUsingConstantColor) |
|
{ |
|
++lastUsedTextureStage; |
|
|
|
if (isUsingConstantColor && |
|
(lastUsedTextureStage >= m_pHardwareConfig->GetTextureStageCount())) |
|
{ |
|
// This is the case where we'd want to modulate in a particular texture |
|
// stage, but we can't because there aren't enough. In this case, we're gonna |
|
// need to do the modulation in the per-vertex color. |
|
m_ShadowShaderState.m_ModulateConstantColor = true; |
|
} |
|
else |
|
{ |
|
AssertOnce (lastUsedTextureStage < 2); |
|
|
|
// Here, we've got enough texture stages to do the modulation |
|
m_ShadowState.m_TextureStage[lastUsedTextureStage].m_ColorArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[lastUsedTextureStage].m_ColorArg2 = D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[lastUsedTextureStage].m_AlphaArg1 = D3DTA_TFACTOR; |
|
m_ShadowState.m_TextureStage[lastUsedTextureStage].m_AlphaArg2 = D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[lastUsedTextureStage].m_ColorOp = D3DTOP_MODULATE; |
|
m_ShadowState.m_TextureStage[lastUsedTextureStage].m_AlphaOp = D3DTOP_MODULATE; |
|
} |
|
} |
|
|
|
// Overwrite the alpha stuff if we asked to independently control it |
|
if (m_AlphaPipe) |
|
{ |
|
ConfigureAlphaPipe( flags ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Makes sure we report if we're getting garbage. |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::DrawFlags( unsigned int flags ) |
|
{ |
|
m_DrawFlags = flags; |
|
m_ShadowState.m_UsingFixedFunction = true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Compute texture coordinates |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::ConfigureTextureCoordinates( unsigned int flags ) |
|
{ |
|
// default... |
|
for (int i = 0; i < m_pHardwareConfig->GetTextureStageCount(); ++i) |
|
{ |
|
TextureCoordinate( (TextureStage_t)i, i ); |
|
} |
|
|
|
if (flags & SHADER_DRAW_TEXCOORD0) |
|
{ |
|
Assert( (flags & SHADER_DRAW_LIGHTMAP_TEXCOORD0) == 0 ); |
|
TextureCoordinate( SHADER_TEXTURE_STAGE0, 0 ); |
|
} |
|
else if (flags & SHADER_DRAW_LIGHTMAP_TEXCOORD0) |
|
{ |
|
TextureCoordinate( SHADER_TEXTURE_STAGE0, 1 ); |
|
} |
|
else if (flags & SHADER_DRAW_SECONDARY_TEXCOORD0 ) |
|
{ |
|
TextureCoordinate( SHADER_TEXTURE_STAGE0, 2 ); |
|
} |
|
|
|
if (flags & SHADER_DRAW_TEXCOORD1) |
|
{ |
|
Assert( (flags & SHADER_DRAW_LIGHTMAP_TEXCOORD1) == 0 ); |
|
TextureCoordinate( SHADER_TEXTURE_STAGE1, 0 ); |
|
} |
|
else if (flags & SHADER_DRAW_LIGHTMAP_TEXCOORD1) |
|
{ |
|
TextureCoordinate( SHADER_TEXTURE_STAGE1, 1 ); |
|
} |
|
else if (flags & SHADER_DRAW_SECONDARY_TEXCOORD1 ) |
|
{ |
|
TextureCoordinate( SHADER_TEXTURE_STAGE1, 2 ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Converts draw flags into vertex format |
|
//----------------------------------------------------------------------------- |
|
VertexFormat_t CShaderShadowDX8::FlagsToVertexFormat( int flags ) const |
|
{ |
|
// Flags -1 occurs when there's an error condition; |
|
// we'll just give em the max space and let them fill it in. |
|
int formatFlags = 0; |
|
int texCoordSize[VERTEX_MAX_TEXTURE_COORDINATES] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
|
int userDataSize = 0; |
|
int numBones = 0; |
|
|
|
// Flags -1 occurs when there's an error condition; |
|
// we'll just give em the max space and let them fill it in. |
|
if (flags == -1) |
|
{ |
|
formatFlags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_COLOR | |
|
VERTEX_TANGENT_S | VERTEX_TANGENT_T; |
|
texCoordSize[0] = texCoordSize[1] = texCoordSize[2] = 2; |
|
} |
|
else |
|
{ |
|
if (flags & SHADER_DRAW_POSITION) |
|
formatFlags |= VERTEX_POSITION; |
|
|
|
if (flags & SHADER_DRAW_NORMAL) |
|
formatFlags |= VERTEX_NORMAL; |
|
|
|
if (flags & SHADER_DRAW_COLOR) |
|
formatFlags |= VERTEX_COLOR; |
|
|
|
if( flags & SHADER_DRAW_SPECULAR ) |
|
formatFlags |= VERTEX_SPECULAR; |
|
|
|
if (flags & SHADER_TEXCOORD_MASK) |
|
{ |
|
// normal texture coords into texture 0 |
|
texCoordSize[0] = 2; |
|
} |
|
|
|
if (flags & SHADER_LIGHTMAP_TEXCOORD_MASK) |
|
{ |
|
// lightmaps go into texcoord 1 |
|
texCoordSize[1] = 2; |
|
} |
|
|
|
if (flags & SHADER_SECONDARY_TEXCOORD_MASK) |
|
{ |
|
// any texgen, or secondary texture coordinate is put into texcoord 2 |
|
texCoordSize[2] = 2; |
|
} |
|
} |
|
|
|
// Hardware skinning... always store space for up to 3 bones |
|
// and always assume index blend enabled if available |
|
if (m_ShadowState.m_VertexBlendEnable) |
|
{ |
|
if (HardwareConfig()->MaxBlendMatrixIndices() > 0) |
|
formatFlags |= VERTEX_BONE_INDEX; |
|
|
|
if (HardwareConfig()->MaxBlendMatrices() > 2) |
|
numBones = 2; // the third bone weight is implied |
|
else |
|
numBones = HardwareConfig()->MaxBlendMatrices() - 1; |
|
} |
|
|
|
return MeshMgr()->ComputeVertexFormat( formatFlags, VERTEX_MAX_TEXTURE_COORDINATES, |
|
texCoordSize, numBones, userDataSize ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Computes shadow state based on bunches of other parameters |
|
//----------------------------------------------------------------------------- |
|
void CShaderShadowDX8::ComputeAggregateShadowState( ) |
|
{ |
|
unsigned int flags = 0; |
|
|
|
// Initialize the texture stage usage; this may get changed later |
|
for (int i = 0; i < m_pHardwareConfig->GetSamplerCount(); ++i) |
|
{ |
|
m_ShadowState.m_SamplerState[i].m_TextureEnable = |
|
IsUsingTextureCoordinates( (Sampler_t)i ); |
|
|
|
// Deal with the alpha pipe |
|
if ( m_ShadowState.m_UsingFixedFunction && m_AlphaPipe ) |
|
{ |
|
if ( m_TextureStage[i].m_TextureAlphaEnable ) |
|
{ |
|
m_ShadowState.m_SamplerState[i].m_TextureEnable = true; |
|
} |
|
} |
|
} |
|
|
|
// Always use the same alpha src + dest if it's disabled |
|
// NOTE: This is essential for stateblocks to work |
|
if ( m_ShadowState.m_AlphaBlendEnable ) |
|
{ |
|
m_ShadowState.m_SrcBlend = m_SrcBlend; |
|
m_ShadowState.m_DestBlend = m_DestBlend; |
|
m_ShadowState.m_BlendOp = m_BlendOp; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_SrcBlend = D3DBLEND_ONE; |
|
m_ShadowState.m_DestBlend = D3DBLEND_ZERO; |
|
m_ShadowState.m_BlendOp = D3DBLENDOP_ADD; |
|
} |
|
|
|
// GR |
|
if (m_ShadowState.m_SeparateAlphaBlendEnable) |
|
{ |
|
m_ShadowState.m_SrcBlendAlpha = m_SrcBlendAlpha; |
|
m_ShadowState.m_DestBlendAlpha = m_DestBlendAlpha; |
|
m_ShadowState.m_BlendOpAlpha = m_BlendOpAlpha; |
|
} |
|
else |
|
{ |
|
m_ShadowState.m_SrcBlendAlpha = D3DBLEND_ONE; |
|
m_ShadowState.m_DestBlendAlpha = D3DBLEND_ZERO; |
|
m_ShadowState.m_BlendOpAlpha = D3DBLENDOP_ADD; |
|
} |
|
|
|
// Use the same func if it's disabled |
|
if (m_ShadowState.m_AlphaTestEnable) |
|
{ |
|
// If alpha test is enabled, just use the values set |
|
m_ShadowState.m_AlphaFunc = m_AlphaFunc; |
|
m_ShadowState.m_AlphaRef = m_AlphaRef; |
|
} |
|
else |
|
{ |
|
// A default value |
|
m_ShadowState.m_AlphaFunc = D3DCMP_GREATEREQUAL; |
|
m_ShadowState.m_AlphaRef = 0; |
|
|
|
// If not alpha testing and doing a standard alpha blend, force on alpha testing |
|
if ( m_ShadowState.m_AlphaBlendEnable ) |
|
{ |
|
if ( ( m_ShadowState.m_SrcBlend == D3DBLEND_SRCALPHA ) && ( m_ShadowState.m_DestBlend == D3DBLEND_INVSRCALPHA ) ) |
|
{ |
|
m_ShadowState.m_AlphaFunc = D3DCMP_GREATEREQUAL; |
|
m_ShadowState.m_AlphaRef = 1; |
|
} |
|
} |
|
} |
|
if ( m_ShadowState.m_UsingFixedFunction ) |
|
{ |
|
flags = m_DrawFlags; |
|
|
|
// We need to take this bad boy into account |
|
if (HasConstantColor()) |
|
flags |= SHADER_HAS_CONSTANT_COLOR; |
|
|
|
// We need to take lighting into account.. |
|
if ( m_ShadowState.m_Lighting ) |
|
flags |= SHADER_DRAW_NORMAL; |
|
|
|
if (m_ShadowState.m_Lighting) |
|
flags |= SHADER_DRAW_COLOR; |
|
|
|
// Look for inconsistency in the shadow state (can't have texgen & |
|
// SHADER_DRAW_TEXCOORD or SHADER_DRAW_SECONDARY_TEXCOORD0 on the same stage) |
|
if (flags & (SHADER_DRAW_TEXCOORD0 | SHADER_DRAW_SECONDARY_TEXCOORD0)) |
|
{ |
|
Assert( (m_ShadowState.m_TextureStage[0].m_TexCoordIndex & 0xFFFF0000) == 0 ); |
|
} |
|
if (flags & (SHADER_DRAW_TEXCOORD1 | SHADER_DRAW_SECONDARY_TEXCOORD1)) |
|
{ |
|
Assert( (m_ShadowState.m_TextureStage[1].m_TexCoordIndex & 0xFFFF0000) == 0 ); |
|
} |
|
if (flags & (SHADER_DRAW_TEXCOORD2 | SHADER_DRAW_SECONDARY_TEXCOORD2)) |
|
{ |
|
Assert( (m_ShadowState.m_TextureStage[2].m_TexCoordIndex & 0xFFFF0000) == 0 ); |
|
} |
|
if (flags & (SHADER_DRAW_TEXCOORD3 | SHADER_DRAW_SECONDARY_TEXCOORD3)) |
|
{ |
|
Assert( (m_ShadowState.m_TextureStage[3].m_TexCoordIndex & 0xFFFF0000) == 0 ); |
|
} |
|
|
|
// Vertex usage has already been set for pixel + vertex shaders |
|
m_ShadowShaderState.m_VertexUsage = FlagsToVertexFormat( flags ); |
|
|
|
// Configure the texture stages |
|
ConfigureFVFVertexShader(flags); |
|
|
|
#if 0 |
|
//#ifdef _DEBUG |
|
// NOTE: This must be true for stateblocks to work |
|
for ( i = 0; i < m_pHardwareConfig->GetTextureStageCount(); ++i ) |
|
{ |
|
if ( m_ShadowState.m_TextureStage[i].m_ColorOp == D3DTOP_DISABLE ) |
|
{ |
|
Assert( m_ShadowState.m_TextureStage[i].m_ColorArg1 == D3DTA_TEXTURE ); |
|
Assert( m_ShadowState.m_TextureStage[i].m_ColorArg2 == ((i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT) ); |
|
} |
|
|
|
if ( m_ShadowState.m_TextureStage[i].m_AlphaOp == D3DTOP_DISABLE ) |
|
{ |
|
Assert( m_ShadowState.m_TextureStage[i].m_AlphaArg1 == D3DTA_TEXTURE ); |
|
Assert( m_ShadowState.m_TextureStage[i].m_AlphaArg2 == ((i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT) ); |
|
} |
|
} |
|
#endif |
|
} |
|
else |
|
{ |
|
// Pixel shaders, disable everything so as to prevent unnecessary state changes.... |
|
for ( int i = 0; i < m_pHardwareConfig->GetTextureStageCount(); ++i ) |
|
{ |
|
m_ShadowState.m_TextureStage[i].m_ColorArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_ColorArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg1 = D3DTA_TEXTURE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT; |
|
m_ShadowState.m_TextureStage[i].m_ColorOp = D3DTOP_DISABLE; |
|
m_ShadowState.m_TextureStage[i].m_AlphaOp = D3DTOP_DISABLE; |
|
m_ShadowState.m_TextureStage[i].m_TexCoordIndex = i; |
|
} |
|
m_ShadowState.m_Lighting = false; |
|
m_ShadowState.m_SpecularEnable = false; |
|
m_ShadowState.m_VertexBlendEnable = false; |
|
m_ShadowShaderState.m_ModulateConstantColor = false; |
|
} |
|
|
|
// Compute texture coordinates |
|
ConfigureTextureCoordinates(flags); |
|
|
|
// Alpha to coverage |
|
if ( m_ShadowState.m_EnableAlphaToCoverage ) |
|
{ |
|
// Only allow this to be enabled if blending is disabled and testing is enabled |
|
if ( ( m_ShadowState.m_AlphaBlendEnable == true ) || ( m_ShadowState.m_AlphaTestEnable == false ) ) |
|
{ |
|
m_ShadowState.m_EnableAlphaToCoverage = false; |
|
} |
|
} |
|
} |
|
|
|
void CShaderShadowDX8::FogMode( ShaderFogMode_t fogMode ) |
|
{ |
|
Assert( fogMode >= 0 && fogMode < SHADER_FOGMODE_NUMFOGMODES ); |
|
m_ShadowState.m_FogMode = fogMode; |
|
} |
|
|
|
void CShaderShadowDX8::DisableFogGammaCorrection( bool bDisable ) |
|
{ |
|
m_ShadowState.m_bDisableFogGammaCorrection = bDisable; |
|
} |
|
|
|
void CShaderShadowDX8::SetDiffuseMaterialSource( ShaderMaterialSource_t materialSource ) |
|
{ |
|
COMPILE_TIME_ASSERT( ( int )D3DMCS_MATERIAL == ( int )SHADER_MATERIALSOURCE_MATERIAL ); |
|
COMPILE_TIME_ASSERT( ( int )D3DMCS_COLOR1 == ( int )SHADER_MATERIALSOURCE_COLOR1 ); |
|
COMPILE_TIME_ASSERT( ( int )D3DMCS_COLOR2 == ( int )SHADER_MATERIALSOURCE_COLOR2 ); |
|
Assert( materialSource == SHADER_MATERIALSOURCE_MATERIAL || |
|
materialSource == SHADER_MATERIALSOURCE_COLOR1 || |
|
materialSource == SHADER_MATERIALSOURCE_COLOR2 ); |
|
m_ShadowState.m_DiffuseMaterialSource = ( D3DMATERIALCOLORSOURCE )materialSource; |
|
}
|
|
|