summaryrefslogtreecommitdiff
path: root/materialsystem/shaderapidx9/shadershadowdx8.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'materialsystem/shaderapidx9/shadershadowdx8.cpp')
-rw-r--r--materialsystem/shaderapidx9/shadershadowdx8.cpp1826
1 files changed, 1826 insertions, 0 deletions
diff --git a/materialsystem/shaderapidx9/shadershadowdx8.cpp b/materialsystem/shaderapidx9/shadershadowdx8.cpp
new file mode 100644
index 0000000..8c231c9
--- /dev/null
+++ b/materialsystem/shaderapidx9/shadershadowdx8.cpp
@@ -0,0 +1,1826 @@
+//========= 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;
+}