示例#1
0
	void SetSpriteCommonDynamicState( unsigned int shaderFlags )
	{
		IShaderDynamicAPI *pShaderAPI = s_pShaderAPI;
		bool bSRGB = s_ppParams[NOSRGB]->GetIntValue() == 0;

		BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME );

		MaterialFogMode_t fogType = s_pShaderAPI->GetSceneFogMode();
		int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;
		DECLARE_DYNAMIC_VERTEX_SHADER( jl_sprite_vs20 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,  fogIndex );
		SET_DYNAMIC_VERTEX_SHADER( jl_sprite_vs20 );

		if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // Always send GL down this path
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( jl_sprite_ps20b );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER( jl_sprite_ps20b );
		}
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( jl_sprite_ps20 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( HDRENABLED, IsHDREnabled() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER( jl_sprite_ps20 );
		}

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		float vEyePos_SpecExponent[4];
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );
		vEyePos_SpecExponent[3] = 0.0f;
		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

		if( shaderFlags & SHADER_USE_CONSTANT_COLOR )
		{
			if ( bSRGB )
				SetPixelShaderConstantGammaToLinear( 0, COLOR, ALPHA );
			else
				SetPixelShaderConstant( 0, COLOR, ALPHA );
		}

		if( IsHDREnabled() )
		{
			if ( bSRGB )
				SetPixelShaderConstantGammaToLinear( 1, HDRCOLORSCALE );
			else
				SetPixelShaderConstant( 1, HDRCOLORSCALE );
		}
	}
示例#2
0
	inline void DrawPass( IMaterialVar **params, IShaderShadow* pShaderShadow,
		IShaderDynamicAPI* pShaderAPI, int nPass, VertexCompressionType_t vertexCompression ) 
	{
		bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL );
		bool bHasEnvmap = params[ENVMAP]->IsTexture();
		bool bHasFlowmap = params[FLOWMAP]->IsTexture();
		bool bHasCoreColorTexture = params[CORECOLORTEXTURE]->IsTexture();

		SHADOW_STATE
		{
			SetInitialShadowState( );

			if( nPass == 0 )
			{
				// Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState
				pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) );
			}
			else
			{
				pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
				EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE );
			}

			// If envmap is not specified, the alpha channel is the translucency
			// (If envmap *is* specified, alpha channel is the reflection amount)
			if ( params[NORMALMAP]->IsTexture() && !bHasEnvmap )
			{
				SetDefaultBlendingShadowState( NORMALMAP, false );
			}

			// source render target that contains the image that we are warping.
			pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
			if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER )
			{
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );
			}

			// normal map
			pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
			if( bHasEnvmap )
			{
				// envmap
				pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );
				}
			}

			if( bHasFlowmap )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
			}

			if( bHasCoreColorTexture )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
			}

			if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
			{
				pShaderShadow->EnableSRGBWrite( true );
			}

			unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
			int userDataSize = 0;
			int nTexCoordCount = 1;
			if( bIsModel )
			{
				userDataSize = 4;
			}
			else
			{
				flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T;
			}

			// This shader supports compressed vertices, so OR in that flag:
			flags |= VERTEX_FORMAT_COMPRESSED;

			pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

			DECLARE_STATIC_VERTEX_SHADER( sdk_core_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
			SET_STATIC_VERTEX_SHADER( sdk_core_vs20 );

			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_STATIC_PIXEL_SHADER( sdk_core_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  bHasEnvmap && ( nPass == 1 ) );
				SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap );
				SET_STATIC_PIXEL_SHADER_COMBO( CORECOLORTEXTURE, bHasCoreColorTexture && ( nPass == 0 ) );
				SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, nPass == 0 );
				SET_STATIC_PIXEL_SHADER( sdk_core_ps20b );
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( sdk_core_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  bHasEnvmap && ( nPass == 1 ) );
				SET_STATIC_PIXEL_SHADER_COMBO( FLOWMAP, bHasFlowmap );
				SET_STATIC_PIXEL_SHADER_COMBO( CORECOLORTEXTURE, bHasCoreColorTexture && ( nPass == 0 ) );
				SET_STATIC_PIXEL_SHADER_COMBO( REFRACT, nPass == 0 );
				SET_STATIC_PIXEL_SHADER( sdk_core_ps20 );
			}

			DefaultFog();
		}
		DYNAMIC_STATE
		{
			pShaderAPI->SetDefaultState();

			if ( params[BASETEXTURE]->IsTexture() )
			{
				BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME );
			}
			else
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 );
			}

			BindTexture( SHADER_SAMPLER3, NORMALMAP, BUMPFRAME );

			if( bHasEnvmap )
			{
				BindTexture( SHADER_SAMPLER4, ENVMAP, ENVMAPFRAME );
			}

			if( bHasFlowmap )
			{
				BindTexture( SHADER_SAMPLER6, FLOWMAP, FLOWMAPFRAME );
			}

			if( bHasCoreColorTexture )
			{
				BindTexture( SHADER_SAMPLER7, CORECOLORTEXTURE, CORECOLORTEXTUREFRAME );
			}

			DECLARE_DYNAMIC_VERTEX_SHADER( sdk_core_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,  pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( sdk_core_vs20 );

			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_core_ps20b );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER( sdk_core_ps20b );
			}
			else
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_core_ps20 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER( sdk_core_ps20 );
			}

			SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM );

			if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
			{
				SetPixelShaderConstant( 0, ENVMAPTINT );
				SetPixelShaderConstant( 1, REFRACTTINT );
			}
			else
			{
				SetPixelShaderConstantGammaToLinear( 0, ENVMAPTINT );
				SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT );
			}
			SetPixelShaderConstant( 2, ENVMAPCONTRAST );
			SetPixelShaderConstant( 3, ENVMAPSATURATION );
			float c5[4] = { params[REFRACTAMOUNT]->GetFloatValue(), 
				params[REFRACTAMOUNT]->GetFloatValue(), 0.0f, 0.0f };
			pShaderAPI->SetPixelShaderConstant( 5, c5, 1 );

			float eyePos[4];
			s_pShaderAPI->GetWorldSpaceCameraPosition( eyePos );
			s_pShaderAPI->SetPixelShaderConstant( 8, eyePos, 1 );
			pShaderAPI->SetPixelShaderFogParams( 11 );



			if( bHasFlowmap )
			{
				float curTime = pShaderAPI->CurrentTime();
				float timeVec[4] = { curTime, curTime, curTime, curTime };
				pShaderAPI->SetPixelShaderConstant( 6, timeVec, 1 );

				SetPixelShaderConstant( 7, FLOWMAPSCROLLRATE );

				SetPixelShaderConstant( 9, FLOWMAPTEXCOORDOFFSET );
			}
		}
		Draw();
	}
示例#3
0
	void DrawUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, VertexCompressionType_t vertexCompression )
	{
		bool hasBump = params[BUMPMAP]->IsTexture();

		BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true );
		bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use
		
		SHADOW_STATE
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );		// Base map

			int flags = VERTEX_POSITION | VERTEX_NORMAL;
			int nTexCoordCount = 1;
			int userDataSize = 0;

			if ( hasBump )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );	// Bump map
				pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );	// Normalization sampler for per-pixel lighting
				userDataSize = 4;										// tangent S
			}

			// This shader supports compressed vertices, so OR in that flag:
			flags |= VERTEX_FORMAT_COMPRESSED;
			pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

			if ( hasBump )
			{
#ifndef _X360
				if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
				{
					DECLARE_STATIC_VERTEX_SHADER( sdk_teeth_bump_vs20 );
					SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 );
					SET_STATIC_VERTEX_SHADER( sdk_teeth_bump_vs20 );

					// ps_2_b version which does phong
					if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
					{
						DECLARE_STATIC_PIXEL_SHADER( sdk_teeth_bump_ps20b );
						SET_STATIC_PIXEL_SHADER( sdk_teeth_bump_ps20b );
					}
					else
					{
						DECLARE_STATIC_PIXEL_SHADER( sdk_teeth_bump_ps20 );
						SET_STATIC_PIXEL_SHADER( sdk_teeth_bump_ps20 );
					}
				}
#ifndef _X360
				else
				{
					// The vertex shader uses the vertex id stream
					SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

					DECLARE_STATIC_VERTEX_SHADER( sdk_teeth_bump_vs30 );
					SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 );
					SET_STATIC_VERTEX_SHADER( sdk_teeth_bump_vs30 );

					DECLARE_STATIC_PIXEL_SHADER( sdk_teeth_bump_ps30 );
					SET_STATIC_PIXEL_SHADER( sdk_teeth_bump_ps30 );
				}
#endif
			}
			else
			{
#ifndef _X360
				if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
				{
					DECLARE_STATIC_VERTEX_SHADER( sdk_teeth_vs20 );
					SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 );
					SET_STATIC_VERTEX_SHADER( sdk_teeth_vs20 );

					if( g_pHardwareConfig->SupportsPixelShaders_2_b() )
					{
						DECLARE_STATIC_PIXEL_SHADER( sdk_teeth_ps20b );
						SET_STATIC_PIXEL_SHADER( sdk_teeth_ps20b );
					}
					else
					{
						DECLARE_STATIC_PIXEL_SHADER( sdk_teeth_ps20 );
						SET_STATIC_PIXEL_SHADER( sdk_teeth_ps20 );
					}
				}
#ifndef _X360
				else
				{
					// The vertex shader uses the vertex id stream
					SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

					DECLARE_STATIC_VERTEX_SHADER( sdk_teeth_vs30 );
					SET_STATIC_VERTEX_SHADER_COMBO( INTRO, params[INTRO]->GetIntValue() ? 1 : 0 );
					SET_STATIC_VERTEX_SHADER( sdk_teeth_vs30 );

					DECLARE_STATIC_PIXEL_SHADER( sdk_teeth_ps30 );
					SET_STATIC_PIXEL_SHADER( sdk_teeth_ps30 );
				}
#endif
			}

			// On DX9, do sRGB
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );
			pShaderShadow->EnableSRGBWrite( true );

			FogToFogColor();

			pShaderShadow->EnableAlphaWrites( bFullyOpaque );
		}
		DYNAMIC_STATE
		{
			BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME );
			if ( hasBump )
			{
				BindTexture( SHADER_SAMPLER1, BUMPMAP );
			}
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );
			pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE );
			pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY );

			Vector4D lighting;
			params[FORWARD]->GetVecValue( lighting.Base(), 3 );
			lighting[3] = params[ILLUMFACTOR]->GetFloatValue();
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() );

			LightState_t lightState;
			pShaderAPI->GetDX9LightState( &lightState );

			pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

			float vEyePos_SpecExponent[4];
			pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );
			vEyePos_SpecExponent[3] = 0.0f;
			pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

			if ( hasBump )
			{	
#ifndef _X360
				if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
				{
					DECLARE_DYNAMIC_VERTEX_SHADER( sdk_teeth_bump_vs20 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT,  lightState.m_bStaticLight  ? 1 : 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
					SET_DYNAMIC_VERTEX_SHADER( sdk_teeth_bump_vs20 );
		
					// ps_2_b version which does Phong
					if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
					{
						Vector4D vSpecExponent;
						vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue();

						pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 );

						DECLARE_DYNAMIC_PIXEL_SHADER( sdk_teeth_bump_ps20b );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS,  lightState.m_nNumLights );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
						SET_DYNAMIC_PIXEL_SHADER( sdk_teeth_bump_ps20b );
					}
					else
					{
						DECLARE_DYNAMIC_PIXEL_SHADER( sdk_teeth_bump_ps20 );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 );
						SET_DYNAMIC_PIXEL_SHADER( sdk_teeth_bump_ps20 );
					}
				}
#ifndef _X360
				else
				{
					SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );

					DECLARE_DYNAMIC_VERTEX_SHADER( sdk_teeth_bump_vs30 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT,  lightState.m_bStaticLight  ? 1 : 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING,  pShaderAPI->IsHWMorphingEnabled() );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
					SET_DYNAMIC_VERTEX_SHADER( sdk_teeth_bump_vs30 );

					Vector4D vSpecExponent;
					vSpecExponent[3] = params[PHONGEXPONENT]->GetFloatValue();
					pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vSpecExponent.Base(), 1 );

					DECLARE_DYNAMIC_PIXEL_SHADER( sdk_teeth_bump_ps30 );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS,  lightState.m_nNumLights );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
					SET_DYNAMIC_PIXEL_SHADER( sdk_teeth_bump_ps30 );
				}
#endif
			}
			else
			{
				// For non-bumped case, ambient cube is computed in the vertex shader
				SetAmbientCubeDynamicStateVertexShader();

#ifndef _X360
				if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
				{
					DECLARE_DYNAMIC_VERTEX_SHADER( sdk_teeth_vs20 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT,  lightState.m_bStaticLight  ? 1 : 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
					SET_DYNAMIC_VERTEX_SHADER( sdk_teeth_vs20 );

					if( g_pHardwareConfig->SupportsPixelShaders_2_b() )
					{
						DECLARE_DYNAMIC_PIXEL_SHADER( sdk_teeth_ps20b );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
						SET_DYNAMIC_PIXEL_SHADER( sdk_teeth_ps20b );
					}
					else
					{
						DECLARE_DYNAMIC_PIXEL_SHADER( sdk_teeth_ps20 );
						SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
						SET_DYNAMIC_PIXEL_SHADER( sdk_teeth_ps20 );
					}
				}
#ifndef _X360
				else
				{
					SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );

					DECLARE_DYNAMIC_VERTEX_SHADER( sdk_teeth_vs30 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT,  lightState.m_bStaticLight  ? 1 : 0 );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING,  pShaderAPI->IsHWMorphingEnabled() );
					SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
					SET_DYNAMIC_VERTEX_SHADER( sdk_teeth_vs30 );

					DECLARE_DYNAMIC_PIXEL_SHADER( sdk_teeth_ps30 );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
					SET_DYNAMIC_PIXEL_SHADER( sdk_teeth_ps30 );
				}
#endif
			}

			if( params[INTRO]->GetIntValue() )
			{
				float curTime = params[WARPPARAM]->GetFloatValue();
				float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime };
				Assert( params[ENTITYORIGIN]->IsDefined() );
				params[ENTITYORIGIN]->GetVecValue( timeVec, 3 );
				pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, timeVec, 1 );
			}
		}
		Draw();
	}
//-----------------------------------------------------------------------------
// Draws the shader
//-----------------------------------------------------------------------------
void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
	bool bHasFlashlight, VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression,
							CBasePerMaterialContextData **pContextDataPtr )
{
	bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture();
	bool bHasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture();

	bool bHasBaseTextureWrinkle = bHasBaseTexture && 
		(info.m_nWrinkle != -1) && params[info.m_nWrinkle]->IsTexture() &&
		(info.m_nStretch != -1) && params[info.m_nStretch]->IsTexture();

	bool bHasBumpWrinkle = bHasBump && 
		(info.m_nNormalWrinkle != -1) && params[info.m_nNormalWrinkle]->IsTexture() &&
		(info.m_nNormalStretch != -1) && params[info.m_nNormalStretch]->IsTexture();

	bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
	bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA );
	bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
	bool bHasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) != 0;
	bool bHasSelfIllumFresnel = ( bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 );
	bool bHasSelfIllumMask = ( bHasSelfIllum ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsTexture();

	// Tie these to specular
	bool bHasPhong = (info.m_nPhong != -1) && ( params[info.m_nPhong]->GetIntValue() != 0 );
	bool bHasSpecularExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture();
	bool bHasPhongTintMap = bHasSpecularExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 );
	bool bHasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture();
	bool bHasPhongWarp = (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsTexture();
	bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );

#if !defined( _X360 )
	bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL );
#endif

	// Rimlight must be set to non-zero to trigger rim light combo (also requires Phong)
	bool bHasRimLight = r_rimlight.GetBool() && bHasPhong && (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 );
	bool bHasRimMaskMap = bHasSpecularExponentTexture && bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 );

	float fBlendFactor=( info.m_nDetailTextureBlendFactor == -1 )? 1 : params[info.m_nDetailTextureBlendFactor]->GetFloatValue();
	bool hasDetailTexture = ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsTexture();
	int nDetailBlendMode = ( hasDetailTexture && info.m_nDetailTextureCombineMode != -1 ) ? params[info.m_nDetailTextureCombineMode]->GetIntValue() : 0;

	bool bBlendTintByBaseAlpha = IsBoolSet( info.m_nBlendTintByBaseAlpha, params ) && !bHasSelfIllum;	// Pixel shader can't do both BLENDTINTBYBASEALPHA and SELFILLUM, so let selfillum win

	float flTintReplacementAmount = GetFloatParam( info.m_nTintReplacesBaseColor, params );

	BlendType_t nBlendType= pShader->EvaluateBlendRequirements( bBlendTintByBaseAlpha ? -1 : info.m_nBaseTexture, true );

	bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlight; //dest alpha is free for special use

	CSkin_DX9_Context *pContextData = reinterpret_cast< CSkin_DX9_Context *> ( *pContextDataPtr );
	if ( ! pContextData )
	{
		pContextData = new CSkin_DX9_Context;
		*pContextDataPtr = pContextData;
	}

	if( pShader->IsSnapshotting() )
	{
		// look at color and alphamod stuff.
		// Unlit generic never uses the flashlight
		bool bHasEnvmap = !bHasFlashlight && params[info.m_nEnvmap]->IsTexture();
		bool bHasNormal = params[info.m_nBumpmap]->IsTexture();
		bool bCanUseBaseAlphaPhongMaskFastPath = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 );

		if ( ! ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() ) )
			bCanUseBaseAlphaPhongMaskFastPath = true;
		
		pContextData->m_bFastPath =
			(! bHasBump ) && 
			(! bHasSpecularExponentTexture ) &&
			(! bHasPhongTintMap ) &&
			(! bHasPhongWarp ) && 
			(! bHasRimLight ) && 
			(! hasDetailTexture ) &&
			bCanUseBaseAlphaPhongMaskFastPath &&
			(! bHasSelfIllum ) &&
			(! bBlendTintByBaseAlpha );
		
		// Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState
		pShaderShadow->EnableAlphaTest( bIsAlphaTested );

		if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
		{
			pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
		}

		int nShadowFilterMode = 0;
		if( bHasFlashlight )
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
			}

			if( bIsAlphaTested )
			{
				// disable alpha test and use the zfunc zequals since alpha isn't guaranteed to 
				// be the same on both the regular pass and the flashlight pass.
				pShaderShadow->EnableAlphaTest( false );
				pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
			}
			pShaderShadow->EnableBlending( true );
			pShaderShadow->EnableDepthWrites( false );

			// Be sure not to write to dest alpha
			pShaderShadow->EnableAlphaWrites( false );

			nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
		}
		else // not flashlight pass
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
			}

			if ( bHasEnvmap )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );	// Cubic environment map
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true );
				}
			}
		}
		
		unsigned int flags = VERTEX_POSITION;
		if( bHasNormal )
		{
			flags |= VERTEX_NORMAL;
		}

		int userDataSize = 0;

		// Always enable...will bind white if nothing specified...
		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );		// Base (albedo) map
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );

		if ( bHasBaseTextureWrinkle || bHasBumpWrinkle )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );	// Base (albedo) compression map
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true );
			pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );	// Base (albedo) expansion map
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, true );
		}

		if( bHasDiffuseWarp )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );	// Diffuse warp texture
		}

		if( bHasPhongWarp )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );	// Specular warp texture
		}

		// Specular exponent map or dummy
		pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Specular exponent map

		if( bHasFlashlight )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );	// Shadow depth map
			pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );	// Noise map
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Flashlight cookie
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true );
			userDataSize = 4; // tangent S
		}

		// Always enable, since flat normal will be bound
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );		// Normal map
		userDataSize = 4; // tangent S
		pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );		// Normalizing cube map

		if ( bHasBaseTextureWrinkle || bHasBumpWrinkle )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER11, true );	// Normal compression map
			pShaderShadow->EnableTexture( SHADER_SAMPLER12, true );	// Normal expansion map
		}

		if ( hasDetailTexture )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
			if ( nDetailBlendMode != 0 ) //Not Mod2X
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER13, true );
		}

		if ( bHasSelfIllum )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
		}

		if( bHasVertexColor || bHasVertexAlpha )
		{
			flags |= VERTEX_COLOR;
		}

		pShaderShadow->EnableSRGBWrite( true );
		
		// texcoord0 : base texcoord, texcoord2 : decal hw morph delta
		int pTexCoordDim[3] = { 2, 0, 3 };
		int nTexCoordCount = 1;

#ifndef _X360
		// Special morphed decal information 
		if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() )
		{
			nTexCoordCount = 3;
		}
#endif

		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize );


#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow();

			DECLARE_STATIC_VERTEX_SHADER( skin_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( USE_STATIC_CONTROL_FLOW, bUseStaticControlFlow );
			SET_STATIC_VERTEX_SHADER( skin_vs20 );

			// Assume we're only going to get in here if we support 2b
			DECLARE_STATIC_PIXEL_SHADER( skin_ps20b );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  bHasSelfIllum && !bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL,  bHasSelfIllumFresnel && !bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && bHasPhong );
			SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, bHasPhongWarp && bHasPhong );
			SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, bHasBaseTextureWrinkle || bHasBumpWrinkle );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bHasRimLight );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( FASTPATH_NOBUMP, pContextData->m_bFastPath );
			SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha );
			SET_STATIC_PIXEL_SHADER( skin_ps20b );
		}
#ifndef _X360
		else
		{
			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

			DECLARE_STATIC_VERTEX_SHADER( skin_vs30 );
			SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal );
			SET_STATIC_VERTEX_SHADER( skin_vs30 );

			DECLARE_STATIC_PIXEL_SHADER( skin_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  bHasSelfIllum && !bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL,  bHasSelfIllumFresnel && !bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bHasDiffuseWarp && bHasPhong );
			SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, bHasPhongWarp && bHasPhong );
			SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, bHasBaseTextureWrinkle || bHasBumpWrinkle );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bHasRimLight );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( FASTPATH_NOBUMP, pContextData->m_bFastPath );
			SET_STATIC_PIXEL_SHADER_COMBO( BLENDTINTBYBASEALPHA, bBlendTintByBaseAlpha );
			SET_STATIC_PIXEL_SHADER( skin_ps30 );
		}
#endif

		if( bHasFlashlight )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->DefaultFog();
		}

		// HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff
		pShaderShadow->EnableAlphaWrites( bFullyOpaque );
	}
	else // not snapshotting -- begin dynamic state
	{
		bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
		bool bHasEnvmap = !bHasFlashlight && params[info.m_nEnvmap]->IsTexture();

		if( bHasBaseTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
		}

		if ( bHasBaseTextureWrinkle )
		{
			pShader->BindTexture( SHADER_SAMPLER9, info.m_nWrinkle, info.m_nBaseTextureFrame );
			pShader->BindTexture( SHADER_SAMPLER10, info.m_nStretch, info.m_nBaseTextureFrame );
		}
		else if ( bHasBumpWrinkle )
		{
			pShader->BindTexture( SHADER_SAMPLER9, info.m_nBaseTexture, info.m_nBaseTextureFrame );
			pShader->BindTexture( SHADER_SAMPLER10, info.m_nBaseTexture, info.m_nBaseTextureFrame );
		}

		if( bHasDiffuseWarp && bHasPhong )
		{
			if ( r_lightwarpidentity.GetBool() )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_IDENTITY_LIGHTWARP );
			}
			else
			{
				pShader->BindTexture( SHADER_SAMPLER2, info.m_nDiffuseWarpTexture );
			}
		}

		if( bHasPhongWarp )
		{
			pShader->BindTexture( SHADER_SAMPLER1, info.m_nPhongWarpTexture );
		}

		if( bHasSpecularExponentTexture && bHasPhong )
		{
			pShader->BindTexture( SHADER_SAMPLER7, info.m_nPhongExponentTexture );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE );
		}

		if( !g_pConfig->m_bFastNoBump )
		{
			if( bHasBump )
				pShader->BindTexture( SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame );
			else
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT );

			if ( bHasBumpWrinkle )
			{
				pShader->BindTexture( SHADER_SAMPLER11, info.m_nNormalWrinkle, info.m_nBumpFrame );
				pShader->BindTexture( SHADER_SAMPLER12, info.m_nNormalStretch, info.m_nBumpFrame );
			}
			else if ( bHasBaseTextureWrinkle )
			{
				pShader->BindTexture( SHADER_SAMPLER11, info.m_nBumpmap, info.m_nBumpFrame );
				pShader->BindTexture( SHADER_SAMPLER12, info.m_nBumpmap, info.m_nBumpFrame );
			}
		}
		else
		{
			if( bHasBump )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT );
			}
			if ( bHasBaseTextureWrinkle || bHasBumpWrinkle )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER11, TEXTURE_NORMALMAP_FLAT );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER12, TEXTURE_NORMALMAP_FLAT );
			}
		}

		if ( hasDetailTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER13, info.m_nDetail, info.m_nDetailFrame );
		}

		if ( bHasSelfIllum )
		{
			if ( bHasSelfIllumMask )												// Separate texture for self illum?
			{
				pShader->BindTexture( SHADER_SAMPLER14, info.m_nSelfIllumMask );	// Bind it
			}
			else																	// else
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER14, TEXTURE_BLACK );	// Bind dummy
			}
		}

		LightState_t lightState = { 0, false, false };
		bool bFlashlightShadows = false;
		if( bHasFlashlight )
		{
			Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 );
			pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame );
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL );

			SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR );

			if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D );
			}
		}
		else // no flashlight
		{
			if ( bHasEnvmap	)
			{
				pShader->BindTexture( SHADER_SAMPLER8, info.m_nEnvmap, info.m_nEnvmapFrame );
			}

			pShaderAPI->GetDX9LightState( &lightState );
		}

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
		int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;
		int numBones = pShaderAPI->GetCurrentNumBones();

		// don't have an easy way to get this through to GLM, so just print it old school
		//printf("\n-D- DrawSkin_DX9_Internal numBones is %d", numBones );
		
		bool bWriteDepthToAlpha = false;
		bool bWriteWaterFogToAlpha = false;
		if( bFullyOpaque ) 
		{
			bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
			bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
			AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
		}

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow();

			DECLARE_DYNAMIC_VERTEX_SHADER( skin_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0);
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : lightState.m_nNumLights );
			SET_DYNAMIC_VERTEX_SHADER( skin_vs20 );

			DECLARE_DYNAMIC_PIXEL_SHADER( skin_ps20b );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER( skin_ps20b );
		}
#ifndef _X360
		else
		{
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );

			DECLARE_DYNAMIC_VERTEX_SHADER( skin_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0);
			SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( skin_vs30 );

			DECLARE_DYNAMIC_PIXEL_SHADER( skin_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS,  lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER( skin_ps30 );

			bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal };
			pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords );
		}
#endif

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );

		if( bHasBump )
		{
			pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
		}

		if ( hasDetailTexture )
		{
			if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) )
				pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4,
																info.m_nDetailTextureTransform, 
																info.m_nDetailScale );
			else
				pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4,
																info.m_nBaseTextureTransform, 
																info.m_nDetailScale );
		}

		pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
		pShader->SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, fBlendFactor );
		bool bInvertPhongMask = ( info.m_nInvertPhongMask != -1 ) && ( params[info.m_nInvertPhongMask]->GetIntValue() != 0 );
		float fInvertPhongMask = bInvertPhongMask ? 1 : 0;

		bool bHasBaseAlphaPhongMask = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 );
		float fHasBaseAlphaPhongMask = bHasBaseAlphaPhongMask ? 1 : 0;
		// Controls for lerp-style paths through shader code
		float vShaderControls[4] = { fHasBaseAlphaPhongMask, 0.0f/*unused*/, flTintReplacementAmount, fInvertPhongMask };
		pShaderAPI->SetPixelShaderConstant( PSREG_CONSTANT_27, vShaderControls, 1 );

		if ( hasDetailTexture )
		{
#if 0														// needs constant change
			if ( info.m_nDetailTint  != -1 )
				pShader->SetPixelShaderConstantGammaToLinear( 10, info.m_nDetailTint );
			else
			{
				float boring_tint[4]={1,1,1,1};
				pShaderAPI->SetPixelShaderConstant( 10, boring_tint, 1 );
			}
#endif
		}

		if ( bHasSelfIllumFresnel && !bHasFlashlight )
		{
			float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f };
			float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f;
			float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f;
			float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f;

			vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias
			vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale
			vConstScaleBiasExp[2] = flExp; // Exp
			vConstScaleBiasExp[3] = flMax; // Brightness

			pShaderAPI->SetPixelShaderConstant( PSREG_SELFILLUM_SCALE_BIAS_EXP, vConstScaleBiasExp, 1 );
		}

		pShader->SetAmbientCubeDynamicStateVertexShader();

		if( !bHasFlashlight )
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );

			// Setting .x to 1 means to apply Fresnel to env map.  Setting w to 1 means use separate selfillummask
			float vEnvMapFresnel_SelfIllumMask[4] = {0.0f, 0.0f, 0.0f, 0.0f};
			vEnvMapFresnel_SelfIllumMask[3] = bHasSelfIllumMask ? 1.0f : 0.0f;

			if( bHasEnvmap )
			{
				float vEnvMapTint_MaskControl[4] = {1.0f, 1.0f, 1.0f, 0.0f};

				// If we have a tint, grab it
				if ( (info.m_nEnvmapTint != -1) && params[info.m_nEnvmapTint]->IsDefined() )
					params[info.m_nEnvmapTint]->GetVecValue(vEnvMapTint_MaskControl, 3);

				// Set control for source of env map mask (normal alpha or base alpha)
				vEnvMapTint_MaskControl[3] = bHasNormalMapAlphaEnvmapMask ? 1.0f : 0.0f;

				if ( (info.m_nEnvmapFresnel != -1) && params[info.m_nEnvmapFresnel]->IsDefined() )
					vEnvMapFresnel_SelfIllumMask[0] = params[info.m_nEnvmapFresnel]->GetFloatValue();

				// Handle mat_fullbright 2 (diffuse lighting only with 50% gamma space basetexture)
				if( bLightingOnly )
				{
					vEnvMapTint_MaskControl[0] = vEnvMapTint_MaskControl[1] = vEnvMapTint_MaskControl[2] = 0.0f;
				}

				pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, vEnvMapTint_MaskControl, 1 );
			}

			pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_FRESNEL__SELFILLUMMASK, vEnvMapFresnel_SelfIllumMask, 1 );
		}

		pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight );	// Force to black if not bAmbientLight
		pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY );

		// Pack Phong exponent in with the eye position
		float vEyePos_SpecExponent[4], vFresnelRanges_SpecBoost[4] = {1, 0.5, 1, 1}, vRimBoost[4] = {1, 1, 1, 1};
		float vSpecularTint[4] = {1, 1, 1, 4};
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );

		// Use the alpha channel of the normal map for the exponent by default
		vEyePos_SpecExponent[3] = -1.f;
		if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() )
		{
			float fValue = params[info.m_nPhongExponent]->GetFloatValue();
			if ( fValue > 0.f )
			{
				// Nonzero value in material overrides map channel
				vEyePos_SpecExponent[3] = fValue;
			}
		}

		// Get the tint parameter
		if ( (info.m_nPhongTint != -1) && params[info.m_nPhongTint]->IsDefined() )
		{
			params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 3);
		}

		// Get the rim light power (goes in w of Phong tint)
		if ( bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() )
		{
			vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue();
			vSpecularTint[3] = max(vSpecularTint[3], 1.0f);	// Make sure this is at least 1
		}

		// Get the rim boost (goes in w of flashlight position)
		if ( bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() )
		{
			vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue();
		}

		if ( !bHasFlashlight )
		{
			float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code
			vRimMaskControl[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f;

			// Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 );
		}

		// If it's all zeros, there was no constant tint in the vmt
		if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) )
		{
			if ( bHasPhongTintMap )				// If we have a map to use, tell the shader
			{
				vSpecularTint[0] = -1;
			}
			else								// Otherwise, just tint with white
			{
				vSpecularTint[0] = 1.0f;
				vSpecularTint[1] = 1.0f;
				vSpecularTint[2] = 1.0f;
			}
		}

		// handle mat_fullbright 2 (diffuse lighting only)
		if( bLightingOnly )
		{
			// BASETEXTURE
			if( bHasSelfIllum && !bHasFlashlight )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO );
			}
			else
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );
			}

			// DETAILTEXTURE
			if ( hasDetailTexture )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER13, TEXTURE_GREY );
			}

			// turn off specularity
			vSpecularTint[0] = vSpecularTint[1] = vSpecularTint[2] = 0.0f;
		}

		if ( (info.m_nPhongFresnelRanges != -1) && params[info.m_nPhongFresnelRanges]->IsDefined() )
		{
			params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 );	// Grab optional Fresnel range parameters
			// Change fresnel range encoding from (min, mid, max) to ((mid-min)*2, mid, (max-mid)*2)
			vFresnelRanges_SpecBoost[0] = (vFresnelRanges_SpecBoost[1] - vFresnelRanges_SpecBoost[0]) * 2;
			vFresnelRanges_SpecBoost[2] = (vFresnelRanges_SpecBoost[2] - vFresnelRanges_SpecBoost[1]) * 2;
		}

		if ( (info.m_nPhongBoost != -1 ) && params[info.m_nPhongBoost]->IsDefined())		// Grab optional Phong boost param
			vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue();
		else
			vFresnelRanges_SpecBoost[3] = 1.0f;

		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );
		pShaderAPI->SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 );
		
		pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 );	// Rim boost in w on non-flashlight pass

		pShaderAPI->SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 );
		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		// flashlightfixme: put this in common code.
		if( bHasFlashlight )
		{
			VMatrix worldToTexture;
			float atten[4], pos[4], tweaks[4];

			const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture );
			SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR );

			pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );

			atten[0] = flashlightState.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZ;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 );

			pos[0] = flashlightState.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 );	// steps on rim boost

			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 );

			// Tweaks associated with a given flashlight
			tweaks[0] = ShadowFilterFromState( flashlightState );
			tweaks[1] = ShadowAttenFromState( flashlightState );
			pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );
			vScreenScale[0] = (float) nWidth  / 32.0f;
			vScreenScale[1] = (float) nHeight / 32.0f;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );

			if ( IsX360() )
			{
				pShaderAPI->SetBooleanPixelShaderConstant( 0, &flashlightState.m_nShadowQuality, 1 );
			}
		}
	}
	pShader->Draw();
}
void DrawMultiblend_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
				    IShaderShadow* pShaderShadow, Multiblend_DX9_Vars_t &info, VertexCompressionType_t vertexCompression,
					CBasePerMaterialContextData **pContextDataPtr )
{
	CMultiblend_DX9_Context *pContextData = reinterpret_cast< CMultiblend_DX9_Context * > ( *pContextDataPtr );//TODO: DISABLE?

	bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL );
	bool bHasFoW = ( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) );
	if ( bHasFoW == true )
	{
		ITexture *pTexture = params[ info.m_nFoW ]->GetTextureValue();
		if ( ( pTexture->GetFlags() & TEXTUREFLAGS_RENDERTARGET ) == 0 )
		{
			bHasFoW = false;
		}
	}
	int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 );
	bool bHasSpec1 = ( info.m_nSpecTexture != -1 && params[ info.m_nSpecTexture ]->IsDefined() );
	bool bHasSpec2 = ( info.m_nSpecTexture2 != -1 && params[ info.m_nSpecTexture2 ]->IsDefined() );
	bool bHasSpec3 = ( info.m_nSpecTexture3 != -1 && params[ info.m_nSpecTexture3 ]->IsDefined() );
	bool bHasSpec4 = ( info.m_nSpecTexture4 != -1 && params[ info.m_nSpecTexture4 ]->IsDefined() );
	bool bUsingEditor = pShader->CanUseEditorMaterials(); // pShader->UsingEditor( params );
	bool bSinglePassFlashlight = true;	//TODO: DISABLE?
	bool bHasFlashlight = pShader->UsingFlashlight( params );
	//TODO: DISABLE?
#if 1
	if ( pShader->IsSnapshotting() || ( !pContextData ) || ( pContextData->m_bMaterialVarsChanged ) )
	{
			if ( !pContextData )								// make sure allocated
			{
				pContextData = new CMultiblend_DX9_Context;
				*pContextDataPtr = pContextData;
			}

			// need to regenerate the semistatic cmds
			pContextData->m_SemiStaticCmdsOut.Reset();
			if ( bHasFlashlight )
			{
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 );

				CBCmdSetPixelShaderFlashlightState_t state;
				state.m_LightSampler = SHADER_SAMPLER13;
				state.m_DepthSampler = SHADER_SAMPLER14;
				state.m_ShadowNoiseSampler = SHADER_SAMPLER15;
				state.m_nColorConstant = 28;
				state.m_nAttenConstant = 13;
				state.m_nOriginConstant = 14;
				state.m_nDepthTweakConstant = 19;
				state.m_nScreenScaleConstant = 31;
				state.m_nWorldToTextureConstant = -1;
				state.m_bFlashlightNoLambert = false;
				state.m_bSinglePassFlashlight = bSinglePassFlashlight;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state );
			}

			pContextData->m_SemiStaticCmdsOut.End();
	}
#endif

	SHADOW_STATE
	{
		pShader->SetInitialShadowState( );

		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );

		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );	// Always SRGB read on base map 1
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );	// Always SRGB read on base map 2
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true );	// Always SRGB read on base map 3
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );	// Always SRGB read on base map 4
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true );	// Always SRGB read on spec map 1
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true );	// Always SRGB read on spec map 1
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true );	// Always SRGB read on spec map 1
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true );	// Always SRGB read on spec map 1

		if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
		{
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true );
		}
		else
		{
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, false );
		}
		if ( bHasFoW )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );
		}

		if( bHasFlashlight )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
			pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
			pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 );
			pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
		}

		pShaderShadow->EnableSRGBWrite( true );
		pShaderShadow->EnableAlphaWrites( true ); // writing water fog alpha always.

		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
		int nTexCoordCount = 8;
		static int s_TexCoordSize[]={	2,			// 
										2,			// 
										0,			// 
										4,			// alpha blend
										4,			// vertex / blend color 0
										4,			// vertex / blend color 1
										4,			// vertex / blend color 2
										4			// vertex / blend color 3
									};

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, s_TexCoordSize, 0 );
		int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_STATIC_VERTEX_SHADER( multiblend_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( SPECULAR, !bUsingEditor );
			SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW );
			SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_VERTEX_SHADER( multiblend_vs20 );

			DECLARE_STATIC_PIXEL_SHADER( multiblend_ps20b );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode );
			SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER( multiblend_ps20b );
		}
#ifndef _X360
		else
		{
			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

			DECLARE_STATIC_VERTEX_SHADER( multiblend_vs30 );
			SET_STATIC_VERTEX_SHADER_COMBO( SPECULAR, !bUsingEditor );
			SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW );
			SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_VERTEX_SHADER( multiblend_vs30 );

			// Bind ps_2_b shader so we can get Phong terms
			DECLARE_STATIC_PIXEL_SHADER( multiblend_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode );
			SET_STATIC_PIXEL_SHADER_COMBO( FOW, bHasFoW );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER( multiblend_ps30 );
		}
#endif

		pShader->DefaultFog();

		float flLScale = pShaderShadow->GetLightMapScaleFactor();

		// Lighting constants
		pShader->PI_BeginCommandBuffer();
		pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE );
//		pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY );
		pShader->PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( PSREG_CONSTANT_43, flLScale );
		pShader->PI_EndCommandBuffer();
	}
	DYNAMIC_STATE
	{
		pShaderAPI->SetDefaultState();

		// Bind textures
		pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture );							// Base Map 1
		pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture2 );							// Base Map 2
		pShader->BindTexture( SHADER_SAMPLER3, info.m_nBaseTexture3 );							// Base Map 3
		pShader->BindTexture( SHADER_SAMPLER4, info.m_nBaseTexture4 );							// Base Map 4
		if ( bHasSpec1 == true )
		{
			pShader->BindTexture( SHADER_SAMPLER6, info.m_nSpecTexture );						// Spec Map 1
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_BLACK );
		}
		if ( bHasSpec2 == true )
		{
			pShader->BindTexture( SHADER_SAMPLER7, info.m_nSpecTexture2 );						// Spec Map 2
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_BLACK );
		}
		if ( bHasSpec3 == true )
		{
			pShader->BindTexture( SHADER_SAMPLER8, info.m_nSpecTexture3 );						// Spec Map 3
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER8, TEXTURE_BLACK );
		}
		if ( bHasSpec4 == true )
		{
			pShader->BindTexture( SHADER_SAMPLER9, info.m_nSpecTexture4 );						// Spec Map 4
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER9, TEXTURE_BLACK );
		}

		pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_LIGHTMAP );

		bool bFlashlightShadows = false;

#if 1
		if( bHasFlashlight )
		{
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			
			pShader->BindTexture( SHADER_SAMPLER13, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame );

			bFlashlightShadows = state.m_bEnableShadows;

			SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR );

			if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER14, pFlashlightDepthTexture );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER15, TEXTURE_SHADOW_NOISE_2D );
			}

			float atten[4], pos[4], tweaks[4];

			atten[0] = state.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = state.m_fLinearAtten;
			atten[2] = state.m_fQuadraticAtten;
			atten[3] = state.m_FarZAtten;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 );

			pos[0] = state.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = state.m_vecLightOrigin[1];
			pos[2] = state.m_vecLightOrigin[2];
			pos[3] = state.m_FarZ;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 );	// steps on rim boost

			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, worldToTexture.Base(), 4 );

			// Tweaks associated with a given flashlight
			tweaks[0] = ShadowFilterFromState( state );
			tweaks[1] = ShadowAttenFromState( state );
			pShader->HashShadow2DJitter( state.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );

			int nTexWidth, nTexHeight;
			pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D );

			vScreenScale[0] = (float) nWidth  / nTexWidth;
			vScreenScale[1] = (float) nHeight / nTexHeight;

			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );

			if ( IsX360() )
			{
				pShaderAPI->SetBooleanPixelShaderConstant( 0, &state.m_nShadowQuality, 1 );
			}

			QAngle angles;
			QuaternionAngles( state.m_quatOrientation, angles );

#if 0
			// World to Light's View matrix
			matrix3x4_t viewMatrix, viewMatrixInverse;
			AngleMatrix( angles, state.m_vecLightOrigin, viewMatrixInverse );
			MatrixInvert( viewMatrixInverse, viewMatrix );
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, worldToTexture.Base(), 4 );
#endif
		}
#endif

		if ( bHasFoW )
		{
			pShader->BindTexture( SHADER_SAMPLER10, info.m_nFoW, -1 );

			float	vFoWSize[ 4 ];
			Vector	vMins = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MINS );
			Vector	vMaxs = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MAXS );
			vFoWSize[ 0 ] = vMins.x;
			vFoWSize[ 1 ] = vMins.y;
			vFoWSize[ 2 ] = vMaxs.x - vMins.x;
			vFoWSize[ 3 ] = vMaxs.y - vMins.y;
			pShaderAPI->SetVertexShaderConstant( 26, vFoWSize );
		}

		Vector4D	vRotations( DEG2RAD( params[ info.m_nRotation ]->GetFloatValue() ), DEG2RAD( params[ info.m_nRotation2 ]->GetFloatValue() ), 
								DEG2RAD( params[ info.m_nRotation3 ]->GetFloatValue() ), DEG2RAD( params[ info.m_nRotation4 ]->GetFloatValue() ) );
		pShaderAPI->SetVertexShaderConstant( 27, vRotations.Base() );

		Vector4D	vScales( params[ info.m_nScale ]->GetFloatValue() > 0.0f ? params[ info.m_nScale ]->GetFloatValue() : 1.0f, 
							 params[ info.m_nScale2 ]->GetFloatValue() > 0.0f ? params[ info.m_nScale2 ]->GetFloatValue() : 1.0f, 
							 params[ info.m_nScale3 ]->GetFloatValue() > 0.0f ? params[ info.m_nScale3 ]->GetFloatValue() : 1.0f, 
							 params[ info.m_nScale4 ]->GetFloatValue() > 0.0f ? params[ info.m_nScale4 ]->GetFloatValue() : 1.0f );
		pShaderAPI->SetVertexShaderConstant( 28, vScales.Base() );

		Vector4D vLightDir;
		vLightDir.AsVector3D() = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_LIGHT_DIRECTION );
		vLightDir.w = pShaderAPI->GetFloatRenderingParameter( FLOAT_RENDERPARM_SPECULAR_POWER );
		pShaderAPI->SetVertexShaderConstant( 29, vLightDir.Base() );


		LightState_t lightState;
		pShaderAPI->GetDX9LightState( &lightState );


#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( multiblend_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,      pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER( multiblend_vs20 );

			DECLARE_DYNAMIC_PIXEL_SHADER( multiblend_ps20b );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER( multiblend_ps20b );
		}
#ifndef _X360
		else
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( multiblend_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,      pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER( multiblend_vs30 );

			DECLARE_DYNAMIC_PIXEL_SHADER( multiblend_ps30 );
			SET_DYNAMIC_PIXEL_SHADER( multiblend_ps30 );
		}
#endif

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nBaseTextureTransform );

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		// Pack phong exponent in with the eye position
		float vEyePos_SpecExponent[4];
		float vSpecularTint[4] = {1, 1, 1, 1};
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );

//		if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() )
//			vEyePos_SpecExponent[3] = params[info.m_nPhongExponent]->GetFloatValue();		// This overrides the channel in the map
//		else
			vEyePos_SpecExponent[3] = 0;													// Use the alpha channel of the normal map for the exponent

		// If it's all zeros, there was no constant tint in the vmt
		if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) )
		{
			vSpecularTint[0] = 1.0f;
			vSpecularTint[1] = 1.0f;
			vSpecularTint[2] = 1.0f;
		}

		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

		// Set c0 and c1 to contain first two rows of ViewProj matrix
		VMatrix matView, matProj, matViewProj;
		pShaderAPI->GetMatrix( MATERIAL_VIEW, matView.m[0] );
		pShaderAPI->GetMatrix( MATERIAL_PROJECTION, matProj.m[0] );
		matViewProj = matView * matProj;
		pShaderAPI->SetPixelShaderConstant( 0, matViewProj.m[0], 2 );

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );
	}
	pShader->Draw();
}
示例#6
0
void Draw_Eyes_Refract_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
	IShaderShadow* pShaderShadow, bool bDrawFlashlightAdditivePass, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	bool bDiffuseWarp = IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture );
	bool bIntro = IS_PARAM_DEFINED( info.m_nIntro ) ? ( params[info.m_nIntro]->GetIntValue() ? true : false ) : false;

	SHADOW_STATE
	{
		SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT );

		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );	// Cornea normal
		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );	// Iris
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );	// Cube reflection
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );	// Ambient occlusion

		// Set stream format (note that this shader supports compression)
		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED;
		int nTexCoordCount = 1;
		int userDataSize = 0;
		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

		if ( bDiffuseWarp )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );	// Light warp
		}

#if !defined( PLATFORM_X360 )
		bool bWorldNormal = ( ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH == ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 )));
#endif

		int nShadowFilterMode = 0;
		if ( bDrawFlashlightAdditivePass == true )
		{
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
			}

			pShaderShadow->EnableDepthWrites( false );
			pShaderShadow->EnableAlphaWrites( false );
			pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Additive blending 
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );	// Flashlight cookie
		}
		else
		{
			pShaderShadow->EnableAlphaWrites( true );
		}

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) );
			SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, 0 );
			SET_STATIC_VERTEX_SHADER( eye_refract_vs20 );

			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false );
				bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false );

				DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
				SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 );
				SET_STATIC_PIXEL_SHADER( eye_refract_ps20b );

				if ( bDrawFlashlightAdditivePass == true )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Shadow depth map
					pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER6 );
					pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Noise map
				}
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 );
				SET_STATIC_PIXEL_SHADER( eye_refract_ps20 );
			}
		}
#ifndef _X360
		else
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );	// Screen space ambient occlusion

			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );
			SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION );

			DECLARE_STATIC_VERTEX_SHADER( eye_refract_vs30 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) );
			SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
			SET_STATIC_VERTEX_SHADER( eye_refract_vs30 );

			bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false );
			bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false );

			DECLARE_STATIC_PIXEL_SHADER( eye_refract_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
			SET_STATIC_PIXEL_SHADER( eye_refract_ps30 );

			if ( bDrawFlashlightAdditivePass == true )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Shadow depth map
				pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Noise map
			}
		}
#endif

		// On DX9, get the gamma read and write correct
		//pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false );		// Cornea normal
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );			// Iris
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );			// Cube map reflection
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true );			// Ambient occlusion
		pShaderShadow->EnableSRGBWrite( true );

		if ( bDiffuseWarp )
		{
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );		// Light Warp
		}

		if ( bDrawFlashlightAdditivePass == true )
		{
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true );		// Flashlight cookie
		}

		// Fog
		if ( bDrawFlashlightAdditivePass == true )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->FogToFogColor();
		}

		// Per-instance state
		pShader->PI_BeginCommandBuffer();
		if ( !bDrawFlashlightAdditivePass )
		{
			pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY );
		}
		pShader->PI_SetVertexShaderAmbientLightCube();
		pShader->PI_SetPixelShaderAmbientLightCubeLuminance( 10 );
		pShader->PI_EndCommandBuffer();
	}
	DYNAMIC_STATE
	{
		VMatrix worldToTexture;
		ITexture *pFlashlightDepthTexture = NULL;
		FlashlightState_t flashlightState;
		bool bFlashlightShadows = false;
		if ( bDrawFlashlightAdditivePass == true )
		{
			flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			bFlashlightShadows = flashlightState.m_bEnableShadows;
		}

		bool bSinglePassFlashlight = false;

		pShader->BindTexture( SHADER_SAMPLER0, info.m_nCorneaTexture );
		pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame );
		pShader->BindTexture( SHADER_SAMPLER2, info.m_nEnvmap );
		pShader->BindTexture( SHADER_SAMPLER3, info.m_nAmbientOcclTexture );
	
		if ( bDiffuseWarp )
		{
			if ( r_lightwarpidentity.GetBool() )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_IDENTITY_LIGHTWARP );
			}
			else
			{
				pShader->BindTexture( SHADER_SAMPLER4, info.m_nDiffuseWarpTexture );
			}
		}

		// On PC, we sample from ambient occlusion texture
		if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() )
		{
			ITexture *pAOTexture = pShaderAPI->GetTextureRenderingParameter( TEXTURE_RENDERPARM_AMBIENT_OCCLUSION );

			if ( pAOTexture )
			{
				pShader->BindTexture( SHADER_SAMPLER8, pAOTexture );
			}
			else
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER8, TEXTURE_WHITE );
			}
		}

		if ( bDrawFlashlightAdditivePass == true )
			pShader->BindTexture( SHADER_SAMPLER5, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );

		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV );

		if ( bDrawFlashlightAdditivePass == true )
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flashlightState.m_vecLightOrigin.Base(), 1 );

		LightState_t lightState = { 0, false, false };
		if ( bDrawFlashlightAdditivePass == false )
		{
			pShaderAPI->GetDX9LightState( &lightState );
		}

		int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 );
			SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs20 );
		}
#ifndef _X360
		else
		{
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 );

			if ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH )
			{
				float vEyeDir[4];
				pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir );

				float flFarZ = pShaderAPI->GetFarZ();
				vEyeDir[0] /= flFarZ;	// Divide by farZ for SSAO algorithm
				vEyeDir[1] /= flFarZ;
				vEyeDir[2] /= flFarZ;
				pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, vEyeDir );
			}

			TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode();
			if ( nTessellationMode != TESSELLATION_MODE_DISABLED )
			{
				pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES );

				bool bHasDisplacement = false; // TODO
				float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(), bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f, 0.0f };
				pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, vSubDDimensions );
			}

			DECLARE_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode );
			SET_DYNAMIC_VERTEX_SHADER( eye_refract_vs30 );
		}
#endif

		// Special constant for DX9 eyes: { Dilation, Glossiness, x, x };
		float vPSConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
		vPSConst[0] = IS_PARAM_DEFINED( info.m_nDilation ) ? params[info.m_nDilation]->GetFloatValue() : kDefaultDilation;
		vPSConst[1] = IS_PARAM_DEFINED( info.m_nGlossiness ) ? params[info.m_nGlossiness]->GetFloatValue() : kDefaultGlossiness;
		vPSConst[2] = 0.0f; // NOT USED
		vPSConst[3] = IS_PARAM_DEFINED( info.m_nCorneaBumpStrength ) ? params[info.m_nCorneaBumpStrength]->GetFloatValue() : kDefaultCorneaBumpStrength;
		pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 );

		pShaderAPI->SetPixelShaderConstant( 1, IS_PARAM_DEFINED( info.m_nEyeOrigin ) ? params[info.m_nEyeOrigin]->GetVecValue() : kDefaultEyeOrigin, 1 );
		pShaderAPI->SetPixelShaderConstant( 2, IS_PARAM_DEFINED( info.m_nIrisU ) ? params[info.m_nIrisU]->GetVecValue() : kDefaultIrisU, 1 );
		pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_nIrisV ) ? params[info.m_nIrisV]->GetVecValue() : kDefaultIrisV, 1 );

		float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos );
		pShaderAPI->SetPixelShaderConstant( 4, vEyePos, 1 );

		float vAmbientOcclusion[4] = { 0.33f, 0.33f, 0.33f, 0.0f };
		if ( IS_PARAM_DEFINED( info.m_nAmbientOcclColor ) )
		{
			params[info.m_nAmbientOcclColor]->GetVecValue( vAmbientOcclusion, 3 );
		}
		vAmbientOcclusion[3] = IS_PARAM_DEFINED( info.m_nAmbientOcclusion ) ? params[info.m_nAmbientOcclusion]->GetFloatValue() : 0.0f;

		float vPackedConst6[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
		//vPackedConst6[0] Unused
		vPackedConst6[1] = IS_PARAM_DEFINED( info.m_nEyeballRadius ) ? params[info.m_nEyeballRadius]->GetFloatValue() : kDefaultEyeballRadius;
		//vPackedConst6[2] = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? params[info.m_nRaytraceSphere]->GetFloatValue() : kDefaultRaytraceSphere;
		vPackedConst6[3] = IS_PARAM_DEFINED( info.m_nParallaxStrength ) ? params[info.m_nParallaxStrength]->GetFloatValue() : kDefaultParallaxStrength;
		pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 );

		if ( bDrawFlashlightAdditivePass == true )
		{
			SetFlashLightColorFromState( flashlightState, pShaderAPI, bSinglePassFlashlight );

			if ( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER6, pFlashlightDepthTexture, 0 );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_SHADOW_NOISE_2D );
			}
		}

		if ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH )
		{
			float vEyeDir[4];
			pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir );

			float flFarZ = pShaderAPI->GetFarZ();
			vEyeDir[0] /= flFarZ;	// Divide by farZ for SSAO algorithm
			vEyeDir[1] /= flFarZ;
			vEyeDir[2] /= flFarZ;
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, vEyeDir );
		}

		// Flashlight tax
#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
				SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20b );
			}
			else // ps.2.0
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps20 );
			}
		}
#ifndef _X360
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nFixedLightingMode ? 0 : lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, nFixedLightingMode ? false : bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight );
			SET_DYNAMIC_PIXEL_SHADER( eye_refract_ps30 );

			// Set constant to enable translation of VPOS to render target coordinates in ps_3_0
			pShaderAPI->SetScreenSizeForVPOS();

			SetupUberlightFromState( pShaderAPI, flashlightState );
		}
#endif

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		if ( bDrawFlashlightAdditivePass == true )
		{
			float atten[4], pos[4], tweaks[4];
			atten[0] = flashlightState.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZAtten;
			pShaderAPI->SetPixelShaderConstant( 7, atten, 1 );

			pos[0] = flashlightState.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			pShaderAPI->SetPixelShaderConstant( 8, pos, 1 );

			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 );

			// Tweaks associated with a given flashlight
			tweaks[0] = ShadowFilterFromState( flashlightState );
			tweaks[1] = ShadowAttenFromState( flashlightState );
			pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			pShaderAPI->SetPixelShaderConstant( 9, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );

			int nTexWidth, nTexHeight;
			pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D );

			vScreenScale[0] = (float) nWidth  / nTexWidth;
			vScreenScale[1] = (float) nHeight / nTexHeight;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );

			vAmbientOcclusion[3] *= flashlightState.m_flAmbientOcclusion;
		}

		vAmbientOcclusion[3] = MIN( MAX( vAmbientOcclusion[3], 0.0f ), 1.0f );
		pShaderAPI->SetPixelShaderConstant( 5, vAmbientOcclusion, 1 );

		// Intro tax
		if ( bIntro )
		{
			float curTime = params[info.m_nWarpParam]->GetFloatValue();
			float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime };
			if ( IS_PARAM_DEFINED( info.m_nEntityOrigin ) )
			{
				params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 );
			}
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, timeVec, 1 );
		}
	}
	pShader->Draw();
}
//-----------------------------------------------------------------------------
// Draws the shader
//-----------------------------------------------------------------------------
void DrawVortWarp_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
	IShaderShadow* pShaderShadow, bool bVertexLitGeneric, bool hasFlashlight, VortWarp_DX9_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture();
	bool hasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture();
	bool hasDetailTexture = !hasBump && params[info.m_nDetail]->IsTexture();
	bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );
	bool hasVertexColor = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
	bool hasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA );
	bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
	bool hasSelfIllumInEnvMapMask =
		( info.m_nSelfIllumEnvMapMask_Alpha != -1 ) &&
		( params[info.m_nSelfIllumEnvMapMask_Alpha]->GetFloatValue() != 0.0 ) ;
	bool bHasFlowMap = ( info.m_nFlowMap != -1 ) && params[info.m_nFlowMap]->IsTexture();
	bool bHasSelfIllumMap = ( info.m_nSelfIllumMap != -1 ) && params[info.m_nSelfIllumMap]->IsTexture();
	
	BlendType_t blendType;
	if ( params[info.m_nBaseTexture]->IsTexture() )
	{
		blendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
	}
	else
	{
		blendType = pShader->EvaluateBlendRequirements( info.m_nEnvmapMask, false );
	}

	
	if( pShader->IsSnapshotting() )
	{
		// look at color and alphamod stuff.
		// Unlit generic never uses the flashlight
		bool hasEnvmap = !hasFlashlight && params[info.m_nEnvmap]->IsTexture();
		bool hasEnvmapMask = (hasSelfIllumInEnvMapMask || !hasFlashlight) && 
			params[info.m_nEnvmapMask]->IsTexture();
		bool bHasNormal = bVertexLitGeneric || hasEnvmap;

		if( hasFlashlight )
		{
			hasEnvmapMask = false;
		}

		bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT );
		// Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState
		pShaderShadow->EnableAlphaTest( bIsAlphaTested );

		if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
		{
			pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
		}

		if( hasFlashlight )
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
			}
			else
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nEnvmapMask, false );
			}
			if( bIsAlphaTested )
			{
				// disable alpha test and use the zfunc zequals since alpha isn't guaranteed to 
				// be the same on both the regular pass and the flashlight pass.
				pShaderShadow->EnableAlphaTest( false );
				pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
			}
			pShaderShadow->EnableBlending( true );
			pShaderShadow->EnableDepthWrites( false );
		}
		else
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
			}
			else
			{
				pShader->SetDefaultBlendingShadowState( info.m_nEnvmapMask, false );
			}
		}
		
		unsigned int flags = VERTEX_POSITION;
		int nTexCoordCount = 1; // texcoord0 : base texcoord
		int userDataSize = 0;
		if( bHasNormal )
		{
			flags |= VERTEX_NORMAL;
		}

		if( hasBaseTexture )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );
		}
		if( hasEnvmap )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
			if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
			{
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );
			}
		}
		if( hasFlashlight )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
			userDataSize = 4; // tangent S
		}
		if( hasDetailTexture )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		}
		if( hasBump )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
			userDataSize = 4; // tangent S
			// Normalizing cube map
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
		}
		if( hasEnvmapMask )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
		}

		if( hasVertexColor || hasVertexAlpha )
		{
			flags |= VERTEX_COLOR;
		}

		pShaderShadow->EnableSRGBWrite( true );
		
		if( bHasSelfIllumMap )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
		}

		if( bHasFlowMap )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		}

		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

		Assert( hasBump );
	
#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_STATIC_VERTEX_SHADER( vortwarp_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
			SET_STATIC_VERTEX_SHADER( vortwarp_vs20 );
			
			if( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_STATIC_PIXEL_SHADER( vortwarp_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE,  hasBaseTexture );
				SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
				SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING,  !params[info.m_nUnlit]->GetIntValue() );
				SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
				SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
				SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, blendType == BT_BLEND );
				SET_STATIC_PIXEL_SHADER( vortwarp_ps20b );
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( vortwarp_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE,  hasBaseTexture );
				SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
				SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING,  !params[info.m_nUnlit]->GetIntValue() );
				SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
				SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
				SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, blendType == BT_BLEND );
				SET_STATIC_PIXEL_SHADER( vortwarp_ps20 );
			}
		}
#ifndef _X360
		else
		{
			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

			DECLARE_STATIC_VERTEX_SHADER( vortwarp_vs30 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
			SET_STATIC_VERTEX_SHADER( vortwarp_vs30 );

			DECLARE_STATIC_PIXEL_SHADER( vortwarp_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE,  hasBaseTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING,  !params[info.m_nUnlit]->GetIntValue() );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
			SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, blendType == BT_BLEND );
			SET_STATIC_PIXEL_SHADER( vortwarp_ps30 );
		}
#endif

		if( hasFlashlight )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->DefaultFog();
		}

		if( blendType == BT_BLEND )
		{
			pShaderShadow->EnableBlending( true );
			pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
			pShaderShadow->EnableAlphaWrites( false );
		}
		else
		{
			pShaderShadow->EnableAlphaWrites( true );
		}
	}
	else
	{
		bool hasEnvmap = !hasFlashlight && params[info.m_nEnvmap]->IsTexture();
		bool hasEnvmapMask = !hasFlashlight && params[info.m_nEnvmapMask]->IsTexture();

		if( hasBaseTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
		}
		if( hasEnvmap )
		{
			pShader->BindTexture( SHADER_SAMPLER1, info.m_nEnvmap, info.m_nEnvmapFrame );
		}
		if( hasDetailTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER2, info.m_nDetail, info.m_nDetailFrame );
		}
		if( !g_pConfig->m_bFastNoBump )
		{
			if( hasBump )
			{
				pShader->BindTexture( SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame );
			}
		}
		else
		{
			if( hasBump )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT );
			}
		}
		if( hasEnvmapMask )
		{
			pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame );
		}

		if( hasFlashlight )
		{
			Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 );
			pShader->BindTexture( SHADER_SAMPLER7, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame );
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			SetFlashLightColorFromState( state, pShaderAPI );
		}

		// Set up light combo state
		LightState_t lightState = {0, false, false};
		if ( bVertexLitGeneric && !hasFlashlight )
		{
			pShaderAPI->GetDX9LightState( &lightState );
		}

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
		int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;
		int numBones = pShaderAPI->GetCurrentNumBones();

		Assert( hasBump );

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( vortwarp_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,  fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,  numBones > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( vortwarp_vs20 );

			if( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( vortwarp_ps20b );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z &&
					blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				float warpParam = params[info.m_nWarpParam]->GetFloatValue();
		//		float selfIllumTint = params[info.m_nSelfIllumTint]->GetFloatValue();
		//		DevMsg( 1, "warpParam: %f %f\n", warpParam, selfIllumTint );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WARPINGIN, warpParam > 0.0f && warpParam < 1.0f );
				SET_DYNAMIC_PIXEL_SHADER( vortwarp_ps20b );
			}
			else
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( vortwarp_ps20 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z &&
					blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				float warpParam = params[info.m_nWarpParam]->GetFloatValue();
		//		float selfIllumTint = params[info.m_nSelfIllumTint]->GetFloatValue();
		//		DevMsg( 1, "warpParam: %f %f\n", warpParam, selfIllumTint );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WARPINGIN, warpParam > 0.0f && warpParam < 1.0f );
				SET_DYNAMIC_PIXEL_SHADER( vortwarp_ps20 );
			}
		}
#ifndef _X360
		else
		{
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );

			DECLARE_DYNAMIC_VERTEX_SHADER( vortwarp_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( vortwarp_vs30 );

			DECLARE_DYNAMIC_PIXEL_SHADER( vortwarp_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( AMBIENT_LIGHT, lightState.m_bAmbientLight ? 1 : 0 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z &&
				blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			float warpParam = params[info.m_nWarpParam]->GetFloatValue();
			//		float selfIllumTint = params[info.m_nSelfIllumTint]->GetFloatValue();
			//		DevMsg( 1, "warpParam: %f %f\n", warpParam, selfIllumTint );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WARPINGIN, warpParam > 0.0f && warpParam < 1.0f );
			SET_DYNAMIC_PIXEL_SHADER( vortwarp_ps30 );
		}
#endif

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );

		if( hasDetailTexture )
		{
			pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale );
			Assert( !hasBump );
		}
		if( hasBump )
		{
			pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
			Assert( !hasDetailTexture );
		}
		if( hasEnvmapMask )
		{
			pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform );
		}
		
		if( hasEnvmap )
		{
			pShader->SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint, -1, true );
		}
		if( ( info.m_nHDRColorScale != -1 ) && pShader->IsHDREnabled() )
		{
			pShader->SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() );
		}
		else
		{
			pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
		}

		pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast );
		pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation );

		pShader->SetPixelShaderConstant( 4, info.m_nSelfIllumTint );
		pShader->SetAmbientCubeDynamicStateVertexShader();
		if( hasBump )
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );
			pShaderAPI->SetPixelShaderStateAmbientLightCube( 5 );
            pShaderAPI->CommitPixelShaderLighting( 13 );
	
		}

		if( bHasSelfIllumMap )
		{
			pShader->BindTexture( SHADER_SAMPLER6, info.m_nSelfIllumMap, -1 );
		}

		if( bHasFlowMap )
		{
			pShader->BindTexture( SHADER_SAMPLER2, info.m_nFlowMap, -1 );
		}

		float eyePos[4];
		pShaderAPI->GetWorldSpaceCameraPosition( eyePos );
		pShaderAPI->SetPixelShaderConstant( 20, eyePos, 1 );
		pShaderAPI->SetPixelShaderFogParams( 21 );

		// dynamic drawing code that extends vertexlitgeneric
		float curTime = params[info.m_nWarpParam]->GetFloatValue();
		float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime };
		Assert( params[info.m_nEntityOrigin]->IsDefined() );
		params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 );
		pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, timeVec, 1 );

		curTime = pShaderAPI->CurrentTime();
		timeVec[0] = curTime;
		timeVec[1] = curTime;
		timeVec[2] = curTime;
		timeVec[3] = curTime;
		pShaderAPI->SetPixelShaderConstant( 22, timeVec, 1 );

		// flashlightfixme: put this in common code.
		if( hasFlashlight )
		{
			VMatrix worldToTexture;
			const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture );

			// Set the flashlight attenuation factors
			float atten[4];
			atten[0] = flashlightState.m_fConstantAtten;
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZ;
			pShaderAPI->SetPixelShaderConstant( 22, atten, 1 );

			// Set the flashlight origin
			float pos[4];
			pos[0] = flashlightState.m_vecLightOrigin[0];
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			pos[3] = 1.0f;
			pShaderAPI->SetPixelShaderConstant( 23, pos, 1 );

			pShaderAPI->SetPixelShaderConstant( 24, worldToTexture.Base(), 4 );
		}		
	}
	pShader->Draw();
}
void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar** params, bool hasFlashlight, 
								 IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, 
								 LightmappedGeneric_DX9_Vars_t &info,
								 CBasePerMaterialContextData **pContextDataPtr
								 )
{
	CLightmappedGeneric_DX9_Context *pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr );
	if ( pShaderShadow || ( ! pContextData ) || pContextData->m_bMaterialVarsChanged  || hasFlashlight )
	{
		bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture();
		int nAlphaChannelTextureVar = hasBaseTexture ? (int)info.m_nBaseTexture : (int)info.m_nEnvmapMask;
		BlendType_t nBlendType = pShader->EvaluateBlendRequirements( nAlphaChannelTextureVar, hasBaseTexture );
		bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
		bool bFullyOpaqueWithoutAlphaTest = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && (!hasFlashlight || IsX360()); //dest alpha is free for special use
		bool bFullyOpaque = bFullyOpaqueWithoutAlphaTest && !bIsAlphaTested;
		bool bNeedRegenStaticCmds = (! pContextData ) || pShaderShadow;

		if ( ! pContextData )								// make sure allocated
		{
			pContextData = new CLightmappedGeneric_DX9_Context;
			*pContextDataPtr = pContextData;
		}

		bool hasBump = ( params[info.m_nBumpmap]->IsTexture() ) && ( !g_pHardwareConfig->PreferReducedFillrate() );
		bool hasSSBump = hasBump && (info.m_nSelfShadowedBumpFlag != -1) &&	( params[info.m_nSelfShadowedBumpFlag]->GetIntValue() );
		bool hasBaseTexture2 = hasBaseTexture && params[info.m_nBaseTexture2]->IsTexture();
		bool hasLightWarpTexture = params[info.m_nLightWarpTexture]->IsTexture();
		bool hasBump2 = hasBump && params[info.m_nBumpmap2]->IsTexture();
		bool hasDetailTexture = params[info.m_nDetail]->IsTexture();
		bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM );
		bool hasBumpMask = hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum &&
			!hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0);
		bool bHasBlendModulateTexture = 
			(info.m_nBlendModulateTexture != -1) &&
			(params[info.m_nBlendModulateTexture]->IsTexture() );
		bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );

        // Parallax cubemaps
        bool hasParallaxCorrection = params[info.m_nEnvmapParallaxObb1]->IsDefined();

		if ( hasFlashlight && !IsX360() )				
		{
			// !!speed!! do this in the caller so we don't build struct every time
			CBaseVSShader::DrawFlashlight_dx90_Vars_t vars;
			vars.m_bBump = hasBump;
			vars.m_nBumpmapVar = info.m_nBumpmap;
			vars.m_nBumpmapFrame = info.m_nBumpFrame;
			vars.m_nBumpTransform = info.m_nBumpTransform;
			vars.m_nFlashlightTextureVar = info.m_nFlashlightTexture;
			vars.m_nFlashlightTextureFrameVar = info.m_nFlashlightTextureFrame;
			vars.m_bLightmappedGeneric = true;
			vars.m_bWorldVertexTransition = hasBaseTexture2;
			vars.m_nBaseTexture2Var = info.m_nBaseTexture2;
			vars.m_nBaseTexture2FrameVar = info.m_nBaseTexture2Frame;
			vars.m_nBumpmap2Var = info.m_nBumpmap2;
			vars.m_nBumpmap2Frame = info.m_nBumpFrame2;
			vars.m_nBump2Transform = info.m_nBumpTransform2;
			vars.m_nAlphaTestReference = info.m_nAlphaTestReference;
			vars.m_bSSBump = hasSSBump;
			vars.m_nDetailVar = info.m_nDetail;
			vars.m_nDetailScale = info.m_nDetailScale;
			vars.m_nDetailTextureCombineMode = info.m_nDetailTextureCombineMode;
			vars.m_nDetailTextureBlendFactor = info.m_nDetailTextureBlendFactor;
			vars.m_nDetailTint = info.m_nDetailTint;

			if ( ( info.m_nSeamlessMappingScale != -1 ) )
				vars.m_fSeamlessScale = params[info.m_nSeamlessMappingScale]->GetFloatValue();
			else
				vars.m_fSeamlessScale = 0.0;
			pShader->DrawFlashlight_dx90( params, pShaderAPI, pShaderShadow, vars );
			return;
		}

		pContextData->m_bFullyOpaque = bFullyOpaque;
		pContextData->m_bFullyOpaqueWithoutAlphaTest = bFullyOpaqueWithoutAlphaTest;

		NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE;
		if ( hasBump && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
			ITexture *pBumpTex = params[info.m_nBumpmap]->GetTextureValue();
			if ( pBumpTex )
			{
				nNormalDecodeMode = pBumpTex->GetNormalDecodeMode();

				if ( hasBump2 )			// Check encoding of secondary normal if there is oneg
				{
					ITexture *pBumpTex2 = params[info.m_nBumpmap]->GetTextureValue();
					if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) )
					{
						DevMsg("LightmappedGeneric: Primary and Secondary normal map compression formats don't match.  This is unsupported!\n");
						Assert(0);
					}
				}
			}
		}

		int nNormalMaskDecodeMode = 0;
		if ( hasBumpMask && g_pHardwareConfig->SupportsNormalMapCompression() && g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
			ITexture *pBumpMaskTex = params[info.m_nBumpMask]->GetTextureValue();
			if ( pBumpMaskTex )
			{
				nNormalMaskDecodeMode = pBumpMaskTex->GetNormalDecodeMode();
			}
		}

		bool bHasOutline = IsBoolSet( info.m_nOutline, params );
		pContextData->m_bPixelShaderForceFastPathBecauseOutline = bHasOutline;
		bool bHasSoftEdges = IsBoolSet( info.m_nSoftEdges, params );
		bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture();
		
		
		float fDetailBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 );

		if ( pShaderShadow || bNeedRegenStaticCmds )
		{
			bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
			bool hasDiffuseBumpmap = hasBump && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0);

			bool hasEnvmap = params[info.m_nEnvmap]->IsTexture();

			bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && 
									  ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) );
			
			if ( bNeedRegenStaticCmds )
			{
				pContextData->ResetStaticCmds();
				CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf;


				if( !hasBaseTexture )
				{
					if( hasEnvmap )
					{
						// if we only have an envmap (no basetexture), then we want the albedo to be black.
						staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK );
					}
					else
					{
						staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
					}
				}
				staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP );

				if ( bSeamlessMapping )
				{
					staticCmdsBuf.SetVertexShaderConstant4(
						VERTEX_SHADER_SHADER_SPECIFIC_CONST_0,
						params[info.m_nSeamlessMappingScale]->GetFloatValue(),0,0,0 );
				}
				staticCmdsBuf.StoreEyePosInPixelShaderConstant( 10 );
				staticCmdsBuf.SetPixelShaderFogParams( 11 );
				staticCmdsBuf.End();
				// now, copy buf
				pContextData->m_pStaticCmds = new uint8[staticCmdsBuf.Size()];
				memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() );
			}
			if ( pShaderShadow )
			{

				// Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState
				pShaderShadow->EnableAlphaTest( bIsAlphaTested );
				if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
				{
					pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
				}

				pShader->SetDefaultBlendingShadowState( nAlphaChannelTextureVar, hasBaseTexture );

				unsigned int flags = VERTEX_POSITION;

				// base texture
				pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );

				if ( hasLightWarpTexture )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false );
				}
				if ( bHasBlendModulateTexture )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false );
				}

				if ( hasBaseTexture2 )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, true );
				}
//		if( hasLightmap )
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );
				}
				else
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false );
				}

				if( hasEnvmap || ( IsX360() && hasFlashlight ) )
				{
					if( hasEnvmap )
					{
						pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
						if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
						{
							pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );
						}
					}
					flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL;
				}

				int nDetailBlendMode = 0;
				if ( hasDetailTexture )
				{
					nDetailBlendMode = GetIntParam( info.m_nDetailTextureCombineMode, params );
					ITexture *pDetailTexture = params[info.m_nDetail]->GetTextureValue();
					if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP )
					{
						if ( hasBump )
							nDetailBlendMode = 10;					// ssbump
						else
							nDetailBlendMode = 11;					// ssbump_nobump
					}
				}

				if( hasDetailTexture )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER12, true );
					bool bSRGBState = ( nDetailBlendMode == 1 );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, bSRGBState );
				}

				if( hasBump || hasNormalMapAlphaEnvmapMask )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
					if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
					{
						pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );	// Normal map alpha, in the compressed normal case
					}
				}
				if( hasBump2 )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
					if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
					{
						pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );	// Secondary normal alpha, in the compressed normal case
					}
				}
				if( hasBumpMask )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );
					if ( nNormalMaskDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
					{
						pShaderShadow->EnableTexture( SHADER_SAMPLER11, true );	// Normal mask alpha, in the compressed normal case
					}
				}
				if( hasEnvmapMask )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
				}

				if( hasFlashlight && IsX360() )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
					pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
					pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 );
					pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
				}

				if( hasVertexColor || hasBaseTexture2 || hasBump2 )
				{
					flags |= VERTEX_COLOR;
				}

				// texcoord0 : base texcoord
				// texcoord1 : lightmap texcoord
				// texcoord2 : lightmap texcoord offset
				int numTexCoords = 2;
				if( hasBump )
				{
					numTexCoords = 3;
				}
		
				pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 );

				// Pre-cache pixel shaders
				bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK );

				int bumpmap_variant=(hasSSBump) ? 2 : hasBump;
				bool bMaskedBlending=( (info.m_nMaskedBlending != -1) &&
									   (params[info.m_nMaskedBlending]->GetIntValue() != 0) );

				DECLARE_STATIC_VERTEX_SHADER( sdk_lightmappedgeneric_vs20 );
				SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK,  hasEnvmapMask );
				SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE,  params[info.m_nEnvmap]->IsTexture() );
				SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP,  hasBump );
				SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap );
				SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) );
				SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, hasBaseTexture2 || hasBump2 );
				SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, hasBumpMask );

				bool bReliefMapping = false; //( bumpmap_variant == 2 ) && ( ! bSeamlessMapping );
				SET_STATIC_VERTEX_SHADER_COMBO( RELIEF_MAPPING, false );//bReliefMapping );
				SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
#ifdef _X360
				SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight);
#endif
                SET_STATIC_VERTEX_SHADER(sdk_lightmappedgeneric_vs20);

				if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
				{
                    DECLARE_STATIC_PIXEL_SHADER(sdk_lightmappedgeneric_ps20b);
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  bumpmap_variant );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask );
					SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
					SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
					SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK,  hasEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK,  hasBaseAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP,  params[info.m_nBaseTextureNoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending);
					SET_STATIC_PIXEL_SHADER_COMBO( RELIEF_MAPPING, bReliefMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline );
					SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int)  nNormalDecodeMode );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMALMASK_DECODE_MODE, (int) nNormalMaskDecodeMode );
                    // Parallax cubemaps enabled for 2_0b and onwards
                    SET_STATIC_PIXEL_SHADER_COMBO( PARALLAXCORRECT, hasParallaxCorrection );
#ifdef _X360
					SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, hasFlashlight);
#endif
                    SET_STATIC_PIXEL_SHADER(sdk_lightmappedgeneric_ps20b);
				}
				else
				{
                    DECLARE_STATIC_PIXEL_SHADER(sdk_lightmappedgeneric_ps20);
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  bumpmap_variant );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask );
					SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
					SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
					SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK,  hasEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK,  hasBaseAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP,  params[info.m_nBaseTextureNoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending);
					SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline );
					SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, 0 );					// No normal compression with ps_2_0	(yikes!)
					SET_STATIC_PIXEL_SHADER_COMBO( NORMALMASK_DECODE_MODE, 0 );				// No normal compression with ps_2_0
                    // Parallax cubemaps
                    SET_STATIC_PIXEL_SHADER_COMBO(PARALLAXCORRECT, 0); // No parallax cubemaps with ps_2_0
                    SET_STATIC_PIXEL_SHADER(sdk_lightmappedgeneric_ps20);
				}
				// HACK HACK HACK - enable alpha writes all the time so that we have them for
				// underwater stuff and writing depth to dest alpha
				// But only do it if we're not using the alpha already for translucency
				pShaderShadow->EnableAlphaWrites( bFullyOpaque );

				pShaderShadow->EnableSRGBWrite( true );

				pShader->DefaultFog();


			} // end shadow state
		} // end shadow || regen display list
		if ( pShaderAPI && pContextData->m_bMaterialVarsChanged )
		{
			// need to regenerate the semistatic cmds
			pContextData->m_SemiStaticCmdsOut.Reset();
			pContextData->m_bMaterialVarsChanged = false;

			bool bHasBlendMaskTransform= (
				(info.m_nBlendMaskTransform != -1) &&
				(info.m_nMaskedBlending != -1) &&
				(params[info.m_nMaskedBlending]->GetIntValue() ) &&
				( ! (params[info.m_nBumpTransform]->MatrixIsIdentity() ) ) );
			
			// If we don't have a texture transform, we don't have
			// to set vertex shader constants or run vertex shader instructions
			// for the texture transform.
			bool bHasTextureTransform = 
				!( params[info.m_nBaseTextureTransform]->MatrixIsIdentity() &&
				   params[info.m_nBumpTransform]->MatrixIsIdentity() &&
				   params[info.m_nBumpTransform2]->MatrixIsIdentity() &&
				   params[info.m_nEnvmapMaskTransform]->MatrixIsIdentity() );
			
			bHasTextureTransform |= bHasBlendMaskTransform;
			
			pContextData->m_bVertexShaderFastPath = !bHasTextureTransform;

			if( params[info.m_nDetail]->IsTexture() )
			{
				pContextData->m_bVertexShaderFastPath = false;
			}
			if (bHasBlendMaskTransform)
			{
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( 
					VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, info.m_nBlendMaskTransform );
			}

			if ( ! pContextData->m_bVertexShaderFastPath )
			{
				bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && 
										  ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) );
				bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture();
				if (!bSeamlessMapping )
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
				// If we have a detail texture, then the bump texcoords are the same as the base texcoords.
				if( hasBump && !hasDetailTexture )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
				}
				if( hasEnvmapMask )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform );
				}
				else if ( hasBump2 )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform2 );
				}
			}
			pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint );
			// set up shader modulation color
			float color[4] = { 1.0, 1.0, 1.0, 1.0 };
			pShader->ComputeModulationColor( color );
			float flLScale = pShaderAPI->GetLightMapScaleFactor();
			color[0] *= flLScale;
			color[1] *= flLScale;
			color[2] *= flLScale;

			pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color );

			color[3] *= ( IS_PARAM_DEFINED( info.m_nAlpha2 ) && params[ info.m_nAlpha2 ]->GetFloatValue() > 0.0f ) ? params[ info.m_nAlpha2 ]->GetFloatValue() : 1.0f;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, color );
			
			if ( hasDetailTexture )
			{
				float detailTintAndBlend[4] = {1, 1, 1, 1};
				
				if ( info.m_nDetailTint != -1 )
				{
					params[info.m_nDetailTint]->GetVecValue( detailTintAndBlend, 3 );
				}
				
				detailTintAndBlend[3] = fDetailBlendFactor;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 8, detailTintAndBlend );
			}
			
			float envmapTintVal[4];
			float selfIllumTintVal[4];
			params[info.m_nEnvmapTint]->GetVecValue( envmapTintVal, 3 );
			params[info.m_nSelfIllumTint]->GetVecValue( selfIllumTintVal, 3 );
			float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue();
			float envmapSaturation = params[info.m_nEnvmapSaturation]->GetFloatValue();
			float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue();
			bool hasEnvmap = params[info.m_nEnvmap]->IsTexture();

			pContextData->m_bPixelShaderFastPath = true;
			bool bUsingContrast = hasEnvmap && ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) && (envmapSaturation != 1.0f);
			bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f);
			bool bUsingSelfIllumTint = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && (selfIllumTintVal[0] != 1.0f || selfIllumTintVal[1] != 1.0f || selfIllumTintVal[2] != 1.0f); 
			if ( bUsingContrast || bUsingFresnel || bUsingSelfIllumTint || !g_pConfig->bShowSpecular )
			{
				pContextData->m_bPixelShaderFastPath = false;
			}
			if( !pContextData->m_bPixelShaderFastPath )
			{
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstants( 2, 3 );
				pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapContrast]->GetVecValue() );
				pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapSaturation]->GetVecValue() );
				float flFresnel = params[info.m_nFresnelReflection]->GetFloatValue();
				// [ 0, 0, 1-R(0), R(0) ]
				pContextData->m_SemiStaticCmdsOut.OutputConstantData4( 0., 0., 1.0 - flFresnel, flFresnel );
				
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, params[info.m_nSelfIllumTint]->GetVecValue() );
			}
			else
			{
				if ( bHasOutline )
				{
					float flOutlineParms[8] = { GetFloatParam( info.m_nOutlineStart0, params ),
												GetFloatParam( info.m_nOutlineStart1, params ),
												GetFloatParam( info.m_nOutlineEnd0, params ),
												GetFloatParam( info.m_nOutlineEnd1, params ),
												0,0,0,
												GetFloatParam( info.m_nOutlineAlpha, params ) };
					if ( info.m_nOutlineColor != -1 )
					{
						params[info.m_nOutlineColor]->GetVecValue( flOutlineParms + 4, 3 );
					}
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, flOutlineParms, 2 );
				}
				
				if ( bHasSoftEdges )
				{
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 
						4, GetFloatParam( info.m_nEdgeSoftnessStart, params ),
						GetFloatParam( info.m_nEdgeSoftnessEnd, params ),
						0,0 );
				}
			}
			// texture binds
			if( hasBaseTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
			}
			// handle mat_fullbright 2
			bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
			if( bLightingOnly )
			{
				// BASE TEXTURE
				if( hasSelfIllum )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO );
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );
				}
				
				// BASE TEXTURE 2	
				if( hasBaseTexture2 )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_GREY );
				}

				// DETAIL TEXTURE
				if( hasDetailTexture )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER12, TEXTURE_GREY );
				}

				// disable color modulation
				float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color );

				// turn off environment mapping
				envmapTintVal[0] = 0.0f;
				envmapTintVal[1] = 0.0f;
				envmapTintVal[2] = 0.0f;
			}

			// always set the transform for detail textures since I'm assuming that you'll
			// always have a detailscale.
			if( hasDetailTexture )
			{
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale );
			}
			
			if( hasBaseTexture2 )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nBaseTexture2, info.m_nBaseTexture2Frame );
			}
			if( hasDetailTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetail, info.m_nDetailFrame );
			}

			if( hasBump || hasNormalMapAlphaEnvmapMask )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
					{
						pContextData->m_SemiStaticCmdsOut.BindMultiTexture( pShader, SHADER_SAMPLER4, SHADER_SAMPLER9, info.m_nBumpmap, info.m_nBumpFrame );
					}
					else
					{
						pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nBumpmap, info.m_nBumpFrame );
					}
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT );
				}
			}
			if( hasBump2 )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
					{
						pContextData->m_SemiStaticCmdsOut.BindMultiTexture( pShader, SHADER_SAMPLER5, SHADER_SAMPLER10, info.m_nBumpmap2, info.m_nBumpFrame2 );
					}
					else
					{
						pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nBumpmap2, info.m_nBumpFrame2 );
					}
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALMAP_FLAT );
				}
			}
			if( hasBumpMask )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					if ( nNormalMaskDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
					{
						Assert(0);
						//pContextData->m_SemiStaticCmdsOut.BindTexture( SHADER_SAMPLER8, SHADER_SAMPLER11, info.m_nBumpMask );
					}
					else
					{
						pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nBumpMask, -1 );
					}
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_NORMALMAP_FLAT );
				}
			}
			
			if( hasEnvmapMask )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame );
			}
			
			if ( hasLightWarpTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nLightWarpTexture, -1 );
			}
			
			if ( bHasBlendModulateTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBlendModulateTexture, -1 );
			}

            // Parallax cubemaps
            if (hasParallaxCorrection)
            {
                pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant(21, params[info.m_nEnvmapOrigin]->GetVecValue());

                float* vecs[3];
                vecs[0] = const_cast<float*>(params[info.m_nEnvmapParallaxObb1]->GetVecValue());
                vecs[1] = const_cast<float*>(params[info.m_nEnvmapParallaxObb2]->GetVecValue());
                vecs[2] = const_cast<float*>(params[info.m_nEnvmapParallaxObb3]->GetVecValue());
                float matrix[4][4];
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        matrix[i][j] = vecs[i][j];
                    }
                }
                matrix[3][0] = matrix[3][1] = matrix[3][2] = 0;
                matrix[3][3] = 1;
                pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant(22, &matrix[0][0], 4);
            }

			pContextData->m_SemiStaticCmdsOut.End();
		}
	}
	DYNAMIC_STATE
	{
		CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut;
		DynamicCmdsOut.Call( pContextData->m_pStaticCmds );
		DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() );

		bool hasEnvmap = params[info.m_nEnvmap]->IsTexture();

		if( hasEnvmap )
		{
			DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nEnvmap, info.m_nEnvmapFrame );
		}
		int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );

		bool bVertexShaderFastPath = pContextData->m_bVertexShaderFastPath;

		if( nFixedLightingMode != 0 )
		{
			if ( pContextData->m_bPixelShaderForceFastPathBecauseOutline )
				nFixedLightingMode = 0;
			else
				bVertexShaderFastPath = false;
		}

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
        DECLARE_DYNAMIC_VERTEX_SHADER(sdk_lightmappedgeneric_vs20);
		SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH,  bVertexShaderFastPath );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( 
			LIGHTING_PREVIEW, 
			(nFixedLightingMode)?1:0
			);
        SET_DYNAMIC_VERTEX_SHADER_CMD(DynamicCmdsOut, sdk_lightmappedgeneric_vs20);

		bool bPixelShaderFastPath = pContextData->m_bPixelShaderFastPath;
		if( nFixedLightingMode !=0 )
		{
			bPixelShaderFastPath = false;
		}
		bool bWriteDepthToAlpha;
		bool bWriteWaterFogToAlpha;
		if(  pContextData->m_bFullyOpaque ) 
		{
			bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
			bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
			AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
		}
		else
		{
			//can't write a special value to dest alpha if we're actually using as-intended alpha
			bWriteDepthToAlpha = false;
			bWriteWaterFogToAlpha = false;
		}

		float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue();
		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
            DECLARE_DYNAMIC_PIXEL_SHADER(sdk_lightmappedgeneric_ps20b);
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH,  bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline );
 			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST,  bPixelShaderFastPath && envmapContrast == 1.0f );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			
			// Don't write fog to alpha if we're using translucency
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nFixedLightingMode );
			
            SET_DYNAMIC_PIXEL_SHADER_CMD(DynamicCmdsOut, sdk_lightmappedgeneric_ps20b);
		}
		else
		{
            DECLARE_DYNAMIC_PIXEL_SHADER(sdk_lightmappedgeneric_ps20);
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH,  bPixelShaderFastPath );
 			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST,  bPixelShaderFastPath && envmapContrast == 1.0f );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			
			// Don't write fog to alpha if we're using translucency
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO(	LIGHTING_PREVIEW, nFixedLightingMode );
			
            SET_DYNAMIC_PIXEL_SHADER_CMD(DynamicCmdsOut, sdk_lightmappedgeneric_ps20);
		}

		if( hasFlashlight && IsX360() )
		{
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );

			DynamicCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture.Base(), 4 );

			SetFlashLightColorFromState( flashlightState, pShaderAPI );

			float atten[4], pos[4];
			atten[0] = flashlightState.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZ;
			DynamicCmdsOut.SetPixelShaderConstant( 13, atten, 1 );

			pos[0] = flashlightState.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			DynamicCmdsOut.SetPixelShaderConstant( 14, pos, 1 );

			pShader->BindTexture( SHADER_SAMPLER13, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );

			if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER14, pFlashlightDepthTexture, 0 );
				DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER15, TEXTURE_SHADOW_NOISE_2D );

				// Tweaks associated with a given flashlight
				float tweaks[4];
				tweaks[0] = ShadowFilterFromState( flashlightState );
				tweaks[1] = ShadowAttenFromState( flashlightState );
				pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
				DynamicCmdsOut.SetPixelShaderConstant( 19, tweaks, 1 );

				// Dimensions of screen, used for screen-space noise map sampling
				float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
				int nWidth, nHeight;
				pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );
				vScreenScale[0] = (float) nWidth  / 32.0f;
				vScreenScale[1] = (float) nHeight / 32.0f;
				DynamicCmdsOut.SetPixelShaderConstant( 31, vScreenScale, 1 );
			}
		}

		DynamicCmdsOut.End();
		pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() );
	}
	pShader->Draw();

	if( IsPC() && (IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0) && pContextData->m_bFullyOpaqueWithoutAlphaTest )
	{
		//Alpha testing makes it so we can't write to dest alpha
		//Writing to depth makes it so later polygons can't write to dest alpha either
		//This leads to situations with garbage in dest alpha.

		//Fix it now by converting depth to dest alpha for any pixels that just wrote.
		pShader->DrawEqualDepthToDestAlpha();
	}
}
static void DrawFlashlight( bool bDX9, CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, 
						   IShaderShadow* pShaderShadow, Eyes_DX8_DX9_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	if( pShaderShadow )
	{
		pShaderShadow->EnableDepthWrites( false );

		pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE );	// Write over the eyes that were already there 

		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );			// Spot
		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );			// Base
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );			// Normalizing cubemap
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );			// Iris

		// Set stream format (note that this shader supports compression)
		int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED;
		int nTexCoordCount = 1;
		int userDataSize = 0;
		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

		// Be sure not to write to dest alpha
		pShaderShadow->EnableAlphaWrites( false );

#ifdef STDSHADER_DX9_DLL_EXPORT
		if ( bDX9 )
		{
			int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
#ifndef _X360
			if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
			{
				DECLARE_STATIC_VERTEX_SHADER( sdk_eyes_flashlight_vs20 );
				SET_STATIC_VERTEX_SHADER( sdk_eyes_flashlight_vs20 );

				if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
				{
					DECLARE_STATIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20b );
					SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
					SET_STATIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20b );
				}
				else
				{
					DECLARE_STATIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20 );
					SET_STATIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20 );
				}
			}
#ifndef _X360
			else
			{
				// The vertex shader uses the vertex id stream
				SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

				DECLARE_STATIC_VERTEX_SHADER( sdk_eyes_flashlight_vs30 );
				SET_STATIC_VERTEX_SHADER( sdk_eyes_flashlight_vs30 );

				DECLARE_STATIC_PIXEL_SHADER( sdk_eyes_flashlight_ps30 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
				SET_STATIC_PIXEL_SHADER( sdk_eyes_flashlight_ps30 );
			}
#endif

			// On DX9, get the gamma read and write correct
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );			// Spot
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );			// Base
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true );			// Iris
			pShaderShadow->EnableSRGBWrite( true );

			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );			// Shadow depth map
				pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 );
				pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );			// Shadow noise rotation map
			}
		}
		else
#endif
		{
			// DX8 uses old asm shaders
			sdk_eyes_flashlight_vs11_Static_Index	vshIndex;
			pShaderShadow->SetVertexShader( "sdk_eyes_flashlight_vs11", vshIndex.GetIndex() );

			sdk_eyes_flashlight_ps11_Static_Index	pshIndex;
			pShaderShadow->SetPixelShader( "sdk_eyes_flashlight_ps11", pshIndex.GetIndex() );
		}
		
		pShader->FogToBlack();
	}
	else
	{
		// Specify that we have XYZ texcoords that need to be divided by W before the pixel shader.
		// NOTE Tried to divide XY by Z, but doesn't work.
		// The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders.
		if ( !bDX9 )
		{
			pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE0, 0, true );
		}
		
		VMatrix worldToTexture;
		ITexture *pFlashlightDepthTexture;
		FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );

		pShader->BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );
		pShader->BindTexture( SHADER_SAMPLER1, info.m_nBaseTexture, info.m_nFrame );
		pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP );
		pShader->BindTexture( SHADER_SAMPLER3, info.m_nIris, info.m_nIrisFrame );

#ifdef STDSHADER_DX9_DLL_EXPORT
		if ( bDX9 )
		{

#ifndef _X360
			if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
			{
				DECLARE_DYNAMIC_VERTEX_SHADER( sdk_eyes_flashlight_vs20 );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
				SET_DYNAMIC_VERTEX_SHADER( sdk_eyes_flashlight_vs20 );
			}
#ifndef _X360
			else
			{
				pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 );

				DECLARE_DYNAMIC_VERTEX_SHADER( sdk_eyes_flashlight_vs30 );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
				SET_DYNAMIC_VERTEX_SHADER( sdk_eyes_flashlight_vs30 );
			}
#endif

//			float vPSConst[4] = {params[info.m_nDilation]->GetFloatValue(), 0.0f, 0.0f, 0.0f};
//			pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 );

			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			SetFlashLightColorFromState( flashlightState, pShaderAPI );

			if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D );
			}

			pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

			float vEyePos_SpecExponent[4];
			pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );
			vEyePos_SpecExponent[3] = 0.0f;
			pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

#ifndef _X360
			if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
			{
				if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
				{
					DECLARE_DYNAMIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20b );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows );
					SET_DYNAMIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20b );

					SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState );
				}
				else
				{
					DECLARE_DYNAMIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20 );
					SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
					SET_DYNAMIC_PIXEL_SHADER( sdk_eyes_flashlight_ps20 );
				}
			}
#ifndef _X360
			else
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_eyes_flashlight_ps30 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows );
				SET_DYNAMIC_PIXEL_SHADER( sdk_eyes_flashlight_ps30 );

				SetDepthFlashlightParams( pShader, pShaderAPI, worldToTexture, flashlightState );
			}
#endif
		}
		else // older asm shaders for DX8
#endif
		{
			sdk_eyes_flashlight_vs11_Dynamic_Index vshIndex;
			vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
			vshIndex.SetSKINNING( pShaderAPI->GetCurrentNumBones() > 0 );
			pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );

			sdk_eyes_flashlight_ps11_Dynamic_Index pshIndex;
			pShaderAPI->SetPixelShaderIndex( pshIndex.GetIndex() );
		}

		// This uses from VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 to VERTEX_SHADER_SHADER_SPECIFIC_CONST_5
		pShader->SetFlashlightVertexShaderConstants( false, -1, false, -1, false );

		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, info.m_nEyeOrigin );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, info.m_nEyeUp );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, info.m_nIrisU );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, info.m_nIrisV );
	}
	pShader->Draw();
}
示例#10
0
void CBaseVSShader::DrawFlashlight_dx90( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, 
										IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars )
{
	// FLASHLIGHTFIXME: hack . . need to fix the vertex shader so that it can deal with and without bumps for vertexlitgeneric
	if( !vars.m_bLightmappedGeneric )
	{
		vars.m_bBump = false;
	}
	bool bBump2 = vars.m_bWorldVertexTransition && vars.m_bBump && vars.m_nBumpmap2Var != -1 && params[vars.m_nBumpmap2Var]->IsTexture();
	bool bSeamless = vars.m_fSeamlessScale != 0.0;
	bool bDetail = vars.m_bLightmappedGeneric && (vars.m_nDetailVar != -1) && params[vars.m_nDetailVar]->IsDefined() && (vars.m_nDetailScale != -1);

	int nDetailBlendMode = 0;
	if ( bDetail )
	{
		nDetailBlendMode = GetIntParam( vars.m_nDetailTextureCombineMode, params );
		ITexture *pDetailTexture = params[vars.m_nDetailVar]->GetTextureValue();
		if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP )
		{
			if ( vars.m_bBump )
				nDetailBlendMode = 10;					// ssbump
			else
				nDetailBlendMode = 11;					// ssbump_nobump
		}
	}
	
	if( pShaderShadow )
	{
		SetInitialShadowState();
		pShaderShadow->EnableDepthWrites( false );
		pShaderShadow->EnableAlphaWrites( false );

		// Alpha blend
		SetAdditiveBlendingShadowState( BASETEXTURE, true );

		// Alpha test
		pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) );
		if ( vars.m_nAlphaTestReference != -1 && params[vars.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
		{
			pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[vars.m_nAlphaTestReference]->GetFloatValue() );
		}

		// Spot sampler
		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );

		// Base sampler
		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );

		// Normalizing cubemap sampler
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );

		// Normalizing cubemap sampler2 or normal map sampler
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );

		// RandomRotation sampler
		pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );

		// Flashlight depth sampler
		pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
		pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 );

		if( vars.m_bWorldVertexTransition )
		{
			// $basetexture2
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );
		}
		if( bBump2 )
		{
			// Normalmap2 sampler
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
		}
		if( bDetail )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );				// detail sampler
			if ( nDetailBlendMode == 1 )
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true );
		}

		pShaderShadow->EnableSRGBWrite( true );

		if( vars.m_bLightmappedGeneric )
		{
#ifndef _X360
			if ( g_pHardwareConfig->HasFastVertexTextures() )
			{
				DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 );
				SET_STATIC_VERTEX_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition );
				SET_STATIC_VERTEX_SHADER_COMBO( NORMALMAP, vars.m_bBump );
				SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamless );
				SET_STATIC_VERTEX_SHADER_COMBO( DETAIL, bDetail );
				SET_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 );
			}
			else
#endif
			{
				DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 );
				SET_STATIC_VERTEX_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition );
				SET_STATIC_VERTEX_SHADER_COMBO( NORMALMAP, vars.m_bBump );
				SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamless );
				SET_STATIC_VERTEX_SHADER_COMBO( DETAIL, bDetail );
				SET_STATIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 );
			}

			unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
			if( vars.m_bBump )
			{
				flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T;
			}
			int numTexCoords = 1;
			if( vars.m_bWorldVertexTransition )
			{
				flags |= VERTEX_COLOR;
				numTexCoords = 2; // need lightmap texcoords to get alpha.
			}
			pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 );
		}
		else
		{

			// Need a 3.0 vs here?

			DECLARE_STATIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( TEETH, vars.m_bTeeth );
			SET_STATIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 );

			unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
			int numTexCoords = 1;
			pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, vars.m_bBump ? 4 : 0 );
		}

		int nBumpMapVariant = 0;
		if ( vars.m_bBump )
		{
			nBumpMapVariant = ( vars.m_bSSBump ) ? 2 : 1;
		}

#ifndef _X360
		if ( g_pHardwareConfig->HasFastVertexTextures() )
		{
			int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();

			DECLARE_STATIC_PIXEL_SHADER( flashlight_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP, nBumpMapVariant );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP2, bBump2 );
			SET_STATIC_PIXEL_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition );
			SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamless );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bDetail );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER( flashlight_ps30 );
		}
		else
#endif
		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
			int nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();

			DECLARE_STATIC_PIXEL_SHADER( flashlight_ps20b );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP, nBumpMapVariant );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP2, bBump2 );
			SET_STATIC_PIXEL_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition );
			SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamless );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bDetail );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER( flashlight_ps20b );
		}
		else
		{
			DECLARE_STATIC_PIXEL_SHADER( flashlight_ps20 );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP, nBumpMapVariant );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAP2, bBump2 );
			SET_STATIC_PIXEL_SHADER_COMBO( WORLDVERTEXTRANSITION, vars.m_bWorldVertexTransition );
			SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamless );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, bDetail );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER( flashlight_ps20 );
		}
		FogToBlack();

		PI_BeginCommandBuffer();
		PI_SetModulationPixelShaderDynamicState( PSREG_DIFFUSE_MODULATION );
		PI_EndCommandBuffer();
	}
	else
	{
		VMatrix worldToTexture;
		ITexture *pFlashlightDepthTexture;
		FlashlightState_t flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );

		SetFlashLightColorFromState( flashlightState, pShaderAPI, false );

		BindTexture( SHADER_SAMPLER0, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );

		pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D );
		if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows )
		{
			BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture, 0 );

			// Tweaks associated with a given flashlight
			float tweaks[4];
			tweaks[0] = ShadowFilterFromState( flashlightState );
			tweaks[1] = ShadowAttenFromState( flashlightState );
			HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );

			int nTexWidth, nTexHeight;
			pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D );

			vScreenScale[0] = (float) nWidth  / nTexWidth;
			vScreenScale[1] = (float) nHeight / nTexHeight;

			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE );
		}

		if( params[BASETEXTURE]->IsTexture() && mat_fullbright.GetInt() != 2 )
		{
			BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY );
		}
		if( vars.m_bWorldVertexTransition )
		{
			Assert( vars.m_nBaseTexture2Var >= 0 && vars.m_nBaseTexture2FrameVar >= 0 );
			BindTexture( SHADER_SAMPLER4, vars.m_nBaseTexture2Var, vars.m_nBaseTexture2FrameVar );
		}
		pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_NORMALIZATION_CUBEMAP );
		if( vars.m_bBump )
		{
			BindTexture( SHADER_SAMPLER3, vars.m_nBumpmapVar, vars.m_nBumpmapFrame );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP );
		}

		if( bDetail )
		{
			BindTexture( SHADER_SAMPLER8, vars.m_nDetailVar );
		}

		if( vars.m_bWorldVertexTransition )
		{
			if( bBump2 )
			{
				BindTexture( SHADER_SAMPLER6, vars.m_nBumpmap2Var, vars.m_nBumpmap2Frame );
			}
		}

		if( vars.m_bLightmappedGeneric )
		{
#ifndef _X360
			if ( g_pHardwareConfig->HasFastVertexTextures() )
			{
				DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 );
				SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs30 );
			}
			else
#endif
			{
				DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 );
				SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_flashlight_vs20 );
			}

			if ( bSeamless )
			{
				float const0[4]={ vars.m_fSeamlessScale,0,0,0};
				pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, const0 );
			}

			if ( bDetail )
			{
				float vDetailConstants[4] = {1,1,1,1};

				if ( vars.m_nDetailTint != -1 )
				{
					params[vars.m_nDetailTint]->GetVecValue( vDetailConstants, 3 );
				}

				if ( vars.m_nDetailTextureBlendFactor != -1 )
				{
					vDetailConstants[3] = params[vars.m_nDetailTextureBlendFactor]->GetFloatValue();
				}

				pShaderAPI->SetPixelShaderConstant( 0, vDetailConstants, 1 );
			}
		}
		else
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER( vertexlitgeneric_flashlight_vs20 );

			if( vars.m_bTeeth )
			{
				Assert( vars.m_nTeethForwardVar >= 0 );
				Assert( vars.m_nTeethIllumFactorVar >= 0 );
				Vector4D lighting;
				params[vars.m_nTeethForwardVar]->GetVecValue( lighting.Base(), 3 );
				lighting[3] = params[vars.m_nTeethIllumFactorVar]->GetFloatValue();
				pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lighting.Base() );
			}
		}

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		float vEyePos_SpecExponent[4];
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );
		vEyePos_SpecExponent[3] = 0.0f;
		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

#ifndef _X360
		if ( g_pHardwareConfig->HasFastVertexTextures() )
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, flashlightState.m_bUberlight );
			SET_DYNAMIC_PIXEL_SHADER( flashlight_ps30 );

			SetupUberlightFromState( pShaderAPI, flashlightState );
		}
		else
#endif
		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20b );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, flashlightState.m_bEnableShadows );
			SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20b );
		}
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( flashlight_ps20 );
			SET_DYNAMIC_PIXEL_SHADER( flashlight_ps20 );
		}

		float atten[4];										// Set the flashlight attenuation factors
		atten[0] = flashlightState.m_fConstantAtten;
		atten[1] = flashlightState.m_fLinearAtten;
		atten[2] = flashlightState.m_fQuadraticAtten;
		atten[3] = flashlightState.m_FarZAtten;
		s_pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 );

		float pos[4];										// Set the flashlight origin
		pos[0] = flashlightState.m_vecLightOrigin[0];
		pos[1] = flashlightState.m_vecLightOrigin[1];
		pos[2] = flashlightState.m_vecLightOrigin[2];
		pos[3] = flashlightState.m_FarZ;
		pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 );	// rim boost not really used here

		SetFlashlightVertexShaderConstants( vars.m_bBump, vars.m_nBumpTransform, bDetail, vars.m_nDetailScale,  bSeamless ? false : true );
	}
	Draw();
}
	inline void DrawReflectionRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow,
		IShaderDynamicAPI* pShaderAPI, bool bReflection, bool bRefraction ) 
	{
		BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true );
		bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use

		SHADOW_STATE
		{
			SetInitialShadowState( );
			if( bRefraction )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );
				}
			}
			if( bReflection )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
				pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );
				}
			}
			if( params[BASETEXTURE]->IsTexture() )
			{
				// BASETEXTURE
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
				// LIGHTMAP
				pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );

				if ( params[ENVMAPMASK]->IsTexture() )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
				}
			}

			// normal map
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );

			int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T;

			// texcoord0 : base texcoord
			// texcoord1 : lightmap texcoord
			// texcoord2 : lightmap texcoord offset
			int numTexCoords = 1;
			if( params[BASETEXTURE]->IsTexture() )
			{
				numTexCoords = 3;
			}
			pShaderShadow->VertexShaderVertexFormat( fmt, numTexCoords, 0, 0 );
			
			if ( IS_FLAG_SET(MATERIAL_VAR_TRANSLUCENT ) )
			{
				EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
			}

			DECLARE_STATIC_VERTEX_SHADER( sdk_lightmappedreflective_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() );
			SET_STATIC_VERTEX_SHADER( sdk_lightmappedreflective_vs20 );

			// "REFLECT" "0..1"
			// "REFRACT" "0..1"
			
			if( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_STATIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( REFLECT,  bReflection );
				SET_STATIC_PIXEL_SHADER_COMBO( REFRACT,  bRefraction );
				SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() );
				SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, params[ENVMAPMASK]->IsTexture() && params[BASETEXTURE]->IsTexture() );
				SET_STATIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20b );
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( REFLECT,  bReflection );
				SET_STATIC_PIXEL_SHADER_COMBO( REFRACT,  bRefraction );
				SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE, params[BASETEXTURE]->IsTexture() );
				SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, params[ENVMAPMASK]->IsTexture() && params[BASETEXTURE]->IsTexture() );
				SET_STATIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20 );
			}

			FogToFogColor();

			if( g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
			{
				// we are writing linear values from this shader.
				pShaderShadow->EnableSRGBWrite( true );
			}

			pShaderShadow->EnableAlphaWrites( bFullyOpaque );
		}
		DYNAMIC_STATE
		{
			if( bRefraction )
			{
				// HDRFIXME: add comment about binding.. Specify the number of MRTs in the enable
				BindTexture( SHADER_SAMPLER0, REFRACTTEXTURE, -1 );
			}
			if( bReflection )
			{
				BindTexture( SHADER_SAMPLER2, REFLECTTEXTURE, -1 );
			}
			BindTexture( SHADER_SAMPLER4, NORMALMAP, BUMPFRAME );
			if( params[BASETEXTURE]->IsTexture() )
			{
				BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP );
				SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, BASETEXTURETRANSFORM );

				if ( params[ENVMAPMASK]->IsTexture() )
				{
					BindTexture( SHADER_SAMPLER6, ENVMAPMASK, ENVMAPMASKFRAME );
				}
			}
			
			// Refraction tint
			if( bRefraction )
			{
				SetPixelShaderConstantGammaToLinear( 1, REFRACTTINT );
			}
			// Reflection tint
			if( bReflection )
			{
				SetPixelShaderConstantGammaToLinear( 4, REFLECTTINT );
			}

			SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM );
			
			float c0[4] = { 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 0.0f };
			pShaderAPI->SetPixelShaderConstant( 0, c0, 1 );
			
			float c2[4] = { 0.5f, 0.5f, 0.5f, 0.5f };
			pShaderAPI->SetPixelShaderConstant( 2, c2, 1 );
							  
			// fresnel constants
			float flFresnelFactor = params[MAXREFLECTIVITY]->GetFloatValue() - params[MINREFLECTIVITY]->GetFloatValue();
			float c3[4] = { flFresnelFactor, params[FRESNELPOWER]->GetFloatValue(), params[MINREFLECTIVITY]->GetFloatValue(), 0.0f };
			pShaderAPI->SetPixelShaderConstant( 3, c3, 1 );

			float c5[4] = { params[REFLECTAMOUNT]->GetFloatValue(), params[REFLECTAMOUNT]->GetFloatValue(), 
				params[REFRACTAMOUNT]->GetFloatValue(), params[REFRACTAMOUNT]->GetFloatValue() };
			pShaderAPI->SetPixelShaderConstant( 5, c5, 1 );

			pShaderAPI->SetPixelShaderFogParams( 8 );

			DECLARE_DYNAMIC_VERTEX_SHADER( sdk_lightmappedreflective_vs20 );
			SET_DYNAMIC_VERTEX_SHADER( sdk_lightmappedreflective_vs20 );
			
			if( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20b );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20b );
			}
			else
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER( sdk_lightmappedreflective_ps20 );
			}
		}
		Draw();
	}
示例#12
0
void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
					 IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL );
	bool bHasEnvmap = params[info.m_nEnvmap]->IsTexture();
	bool bRefractTintTexture = params[info.m_nRefractTintTexture]->IsTexture();
	bool bFadeOutOnSilhouette = params[info.m_nFadeOutOnSilhouette]->GetIntValue() != 0;
	int blurAmount = params[info.m_nBlurAmount]->GetIntValue();
	bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0);
	bool bSecondaryNormal = ( ( info.m_nNormalMap2 != -1 ) && ( params[info.m_nNormalMap2]->IsTexture() ) );
	bool bColorModulate = ( ( info.m_nVertexColorModulate != -1 ) && ( params[info.m_nVertexColorModulate]->GetIntValue() ) );
	bool bWriteZ = params[info.m_nNoWriteZ]->GetIntValue() == 0;
	bool bMirrorAboutViewportEdges = IsX360() && ( info.m_nMirrorAboutViewportEdges != -1 ) && ( params[info.m_nMirrorAboutViewportEdges]->GetIntValue() != 0 );
	bool bUseMagnification = params[info.m_nMagnifyEnable]->GetIntValue() != 0;
	
	if( blurAmount < 0 )
	{
		blurAmount = 0;
	}
	else if( blurAmount > MAXBLUR )
	{
		blurAmount = MAXBLUR;
	}

	BlendType_t nBlendType = pShader->EvaluateBlendRequirements( BASETEXTURE, true );
	bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use
	bFullyOpaque &= !bMasked;

	bool bTranslucentNormal = pShader->TextureIsTranslucent( info.m_nNormalMap, false );
	bFullyOpaque &= (! bTranslucentNormal );

	SHADOW_STATE
	{
		pShader->SetInitialShadowState( );

		pShaderShadow->EnableDepthWrites( bWriteZ );

		// Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState
		pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) );

		// If envmap is not specified, the alpha channel is the translucency
		// (If envmap *is* specified, alpha channel is the reflection amount)
		if ( params[info.m_nNormalMap]->IsTexture() && !bHasEnvmap )
		{
			pShader->SetDefaultBlendingShadowState( info.m_nNormalMap, false );
		}

		// source render target that contains the image that we are warping.
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, !IsX360() );

		// normal map
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );

		if ( bSecondaryNormal )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
		}

		if( bHasEnvmap )
		{
			// envmap
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );
		}
		if( bRefractTintTexture )
		{
			// refract tint texture
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true );
		}

		pShaderShadow->EnableSRGBWrite( true );

		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
		int userDataSize = 0;
		int nTexCoordCount = 1;
		if( bIsModel )
		{
			userDataSize = 4;
		}
		else
		{
			flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T;
		}

		if ( bColorModulate )
		{
			flags |= VERTEX_COLOR;
		}
		
		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );
		
		DECLARE_STATIC_VERTEX_SHADER( refract_vs20 );
		SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
		SET_STATIC_VERTEX_SHADER_COMBO( COLORMODULATE, bColorModulate );
		SET_STATIC_VERTEX_SHADER( refract_vs20 );

		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
			DECLARE_STATIC_PIXEL_SHADER( refract_ps20b );
			SET_STATIC_PIXEL_SHADER_COMBO( BLUR,  blurAmount );
			SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE,  bFadeOutOnSilhouette );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE,  bRefractTintTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked );
			SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate );
			SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal );
			SET_STATIC_PIXEL_SHADER_COMBO( MIRRORABOUTVIEWPORTEDGES, bMirrorAboutViewportEdges );
			SET_STATIC_PIXEL_SHADER_COMBO( MAGNIFY, bUseMagnification );
			SET_STATIC_PIXEL_SHADER( refract_ps20b );
		}
		else
		{
			DECLARE_STATIC_PIXEL_SHADER( refract_ps20 );
			SET_STATIC_PIXEL_SHADER_COMBO( BLUR,  blurAmount );
			SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE,  bFadeOutOnSilhouette );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE,  bRefractTintTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked );
			SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate );
			SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal );
			SET_STATIC_PIXEL_SHADER_COMBO( MIRRORABOUTVIEWPORTEDGES, bMirrorAboutViewportEdges );
			SET_STATIC_PIXEL_SHADER_COMBO( MAGNIFY, bUseMagnification );
			SET_STATIC_PIXEL_SHADER( refract_ps20 );
		}
		pShader->DefaultFog();
		if( bMasked )
		{
			pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA );
		}

		pShaderShadow->EnableAlphaWrites( bFullyOpaque );
	}
	DYNAMIC_STATE
	{
		pShaderAPI->SetDefaultState();

		if ( params[info.m_nBaseTexture]->IsTexture() )
		{
			pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture, info.m_nFrame );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 );
		}

		pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame );

		if ( bSecondaryNormal )
		{
			pShader->BindTexture( SHADER_SAMPLER1, info.m_nNormalMap2, info.m_nBumpFrame2 );
		}

		if( bHasEnvmap )
		{
			pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmap, info.m_nEnvmapFrame );
		}

		if( bRefractTintTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER5, info.m_nRefractTintTexture, info.m_nRefractTintTextureFrame );
		}

		DECLARE_DYNAMIC_VERTEX_SHADER( refract_vs20 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,  pShaderAPI->GetCurrentNumBones() > 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
		SET_DYNAMIC_VERTEX_SHADER( refract_vs20 );

		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20b );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
			SET_DYNAMIC_PIXEL_SHADER( refract_ps20b );
		}
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( refract_ps20 );
			SET_DYNAMIC_PIXEL_SHADER( refract_ps20 );
		}

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform );	// 1 & 2
		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nBumpTransform2 );	// 3 & 4

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		float vEyePos_SpecExponent[4];
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );
		vEyePos_SpecExponent[3] = 0.0f;
		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

		pShader->SetPixelShaderConstantGammaToLinear( 0, info.m_nEnvmapTint );
		pShader->SetPixelShaderConstantGammaToLinear( 1, info.m_nRefractTint );
		pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast );
		pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation );
		float c5[4] = { params[info.m_nRefractAmount]->GetFloatValue(), 
			params[info.m_nRefractAmount]->GetFloatValue(), 0.0f, 0.0f };

		// Time % 1000
		c5[3] = pShaderAPI->CurrentTime();
		c5[3] -= (float)( (int)( c5[3] / 1000.0f ) ) * 1000.0f;
		pShaderAPI->SetPixelShaderConstant( 5, c5, 1 );

		float c6[4];
		params[info.m_nMagnifyCenter]->GetVecValue( c6, 2 );
		c6[2] = params[info.m_nMagnifyScale]->GetFloatValue();
		if ( c6[2] != 0 )
		{
			c6[2] = 1.0f / c6[2]; // Shader uses the inverse scale value
		}
		pShaderAPI->SetPixelShaderConstant( 6, c6, 1 );

		float cVs3[4] = { c5[3], 0.0f, 0.0f, 0.0f };
		pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, cVs3, 1 );

		// Get viewport and render target dimensions and set shader constant to do a 2D mad and also deal with mirror on viewport edges.
		int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
		pShaderAPI->GetCurrentViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight );

		int nRtWidth, nRtHeight;
		pShaderAPI->GetCurrentRenderTargetDimensions( nRtWidth, nRtHeight );

		float vViewportMad[4] = { 1.0f, 1.0f, 0.0f, 0.0f };
		if ( params[ info.m_nNoViewportFixup ]->GetIntValue() == 0 )
		{
			vViewportMad[0] = ( float )nViewportWidth / ( float )nRtWidth;
			vViewportMad[1] = ( float )nViewportHeight / ( float )nRtHeight;
			vViewportMad[2] = ( float )nViewportX / ( float )nRtWidth;
			vViewportMad[3] = ( float )nViewportY / ( float )nRtHeight;
		}
		pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, vViewportMad, 1 );

		if ( bMirrorAboutViewportEdges )
		{
			// Need the extents that we are allowed to sample from the refract texture to clamp by for splitscreen, etc.
			float vNormalizedViewportMinXYMaxWZ[4];

			vNormalizedViewportMinXYMaxWZ[0] = ( float )( nViewportX + REFRACT_VIEWPORT_SHRINK_PIXELS ) / ( float )nRtWidth;
			vNormalizedViewportMinXYMaxWZ[1] = ( float )( nViewportY + REFRACT_VIEWPORT_SHRINK_PIXELS ) / ( float )nRtHeight;
			vNormalizedViewportMinXYMaxWZ[3] = ( float )( nViewportX + nViewportWidth - REFRACT_VIEWPORT_SHRINK_PIXELS - 1 ) / ( float )nRtWidth;
			vNormalizedViewportMinXYMaxWZ[2] = ( float )( nViewportY + nViewportHeight - REFRACT_VIEWPORT_SHRINK_PIXELS - 1 ) / ( float )nRtHeight;

			pShaderAPI->SetPixelShaderConstant( 4, vNormalizedViewportMinXYMaxWZ, 1 );
		}
	}
	pShader->Draw();
}
void DrawLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, 
								 LightmappedGeneric_DX9_Vars_t &info, CBasePerMaterialContextData **pContextDataPtr, bool bDeferredActive )
{
	//bool bDeferredActive = GetDeferredExt()->IsDeferredLightingEnabled();

	bool bSinglePassFlashlight = true;
	bool hasFlashlight = !bDeferredActive && pShader->UsingFlashlight( params );

	CLightmappedGeneric_DX9_Context *pContextData = reinterpret_cast< CLightmappedGeneric_DX9_Context *> ( *pContextDataPtr );
	bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && params[info.m_nShaderSrgbRead360]->GetIntValue() );

	const bool bHasFoW = true; //( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) );

	if ( pShaderShadow || ( ! pContextData )|| pContextData->m_bMaterialVarsChanged || pContextData->m_bNeedsCmdRegen || ( hasFlashlight && !IsX360() ) )
	{
		bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture();
		int nAlphaChannelTextureVar = hasBaseTexture ? (int)info.m_nBaseTexture : (int)info.m_nEnvmapMask;
		BlendType_t nBlendType = pShader->EvaluateBlendRequirements( nAlphaChannelTextureVar, hasBaseTexture );
		bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
		bool bFullyOpaqueWithoutAlphaTest = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && (!hasFlashlight || IsX360()); //dest alpha is free for special use
		bool bFullyOpaque = bFullyOpaqueWithoutAlphaTest && !bIsAlphaTested;
		bool bNeedRegenStaticCmds = (! pContextData ) || pShaderShadow || pContextData->m_bNeedsCmdRegen;

		if ( ! pContextData )								// make sure allocated
		{
			pContextData = new CLightmappedGeneric_DX9_Context;
			*pContextDataPtr = pContextData;
		}

		bool hasBump = ( params[info.m_nBumpmap]->IsTexture() ) && g_pConfig->UseBumpmapping();
		bool hasSSBump = hasBump && (info.m_nSelfShadowedBumpFlag != -1) &&	( params[info.m_nSelfShadowedBumpFlag]->GetIntValue() );
		bool hasBaseTexture2 = hasBaseTexture && params[info.m_nBaseTexture2]->IsTexture();
		bool hasLightWarpTexture = params[info.m_nLightWarpTexture]->IsTexture();
		bool hasBump2 = hasBump && params[info.m_nBumpmap2]->IsTexture();
		bool hasDetailTexture = params[info.m_nDetail]->IsTexture();
		bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM );
		bool hasBumpMask = hasBump && hasBump2 && params[info.m_nBumpMask]->IsTexture() && !hasSelfIllum &&
			!hasDetailTexture && !hasBaseTexture2 && (params[info.m_nBaseTextureNoEnvmap]->GetIntValue() == 0);
		bool bHasBlendModulateTexture = 
			(info.m_nBlendModulateTexture != -1) &&
			(params[info.m_nBlendModulateTexture]->IsTexture() );
		bool hasNormalMapAlphaEnvmapMask = g_pConfig->UseSpecular() && IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );

		if( g_pConfig->bEditMode )
		{
			hasBump = false;
			hasBump2 = false;
		}

		bool bParallaxMapping = false;
		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			bParallaxMapping = ( info.m_nParallaxMap != -1 ) && ( params[info.m_nParallaxMap]->GetIntValue() != 0 );

		if ( hasFlashlight && !IsX360() )				
		{
			// !!speed!! do this in the caller so we don't build struct every time
			CBaseVSShader::DrawFlashlight_dx90_Vars_t vars;
			vars.m_bBump = hasBump;
			vars.m_nBumpmapVar = info.m_nBumpmap;
			vars.m_nBumpmapFrame = info.m_nBumpFrame;
			vars.m_nBumpTransform = info.m_nBumpTransform;
			vars.m_nFlashlightTextureVar = info.m_nFlashlightTexture;
			vars.m_nFlashlightTextureFrameVar = info.m_nFlashlightTextureFrame;
			vars.m_bLightmappedGeneric = true;
			vars.m_bWorldVertexTransition = hasBaseTexture2;
			vars.m_nBaseTexture2Var = info.m_nBaseTexture2;
			vars.m_nBaseTexture2FrameVar = info.m_nBaseTexture2Frame;
			vars.m_nBumpmap2Var = info.m_nBumpmap2;
			vars.m_nBumpmap2Frame = info.m_nBumpFrame2;
			vars.m_nBump2Transform = info.m_nBumpTransform2;
			vars.m_nAlphaTestReference = info.m_nAlphaTestReference;
			vars.m_bSSBump = hasSSBump;
			vars.m_nDetailVar = info.m_nDetail;
			vars.m_nDetailScale = info.m_nDetailScale;
			vars.m_nDetailTextureCombineMode = info.m_nDetailTextureCombineMode;
			vars.m_nDetailTextureBlendFactor = info.m_nDetailTextureBlendFactor;
			vars.m_nDetailTint = info.m_nDetailTint;

			if ( ( info.m_nSeamlessMappingScale != -1 ) )
				vars.m_fSeamlessScale = params[info.m_nSeamlessMappingScale]->GetFloatValue();
			else
				vars.m_fSeamlessScale = 0.0;

			pShader->DrawFlashlight_dx90( params, pShaderAPI, pShaderShadow, vars );
			return;
		}

		pContextData->m_bFullyOpaque = bFullyOpaque;
		pContextData->m_bFullyOpaqueWithoutAlphaTest = bFullyOpaqueWithoutAlphaTest;

		bool bHasOutline = IsBoolSet( info.m_nOutline, params );
		pContextData->m_bPixelShaderForceFastPathBecauseOutline = bHasOutline;
		bool bHasSoftEdges = IsBoolSet( info.m_nSoftEdges, params );
		bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture() && !bHasFoW;
		
		
		float fDetailBlendFactor = GetFloatParam( info.m_nDetailTextureBlendFactor, params, 1.0 );

		if ( pShaderShadow || bNeedRegenStaticCmds )
		{
			bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
			bool hasDiffuseBumpmap = hasBump && (params[info.m_nNoDiffuseBumpLighting]->GetIntValue() == 0);

			bool hasEnvmap = params[info.m_nEnvmap]->IsTexture();
			int envmap_variant; //0 = no envmap, 1 = regular, 2 = darken in shadow mode
			if( hasEnvmap )
			{
				//only enabled darkened cubemap mode when the scale calls for it. And not supported in ps20 when also using a 2nd bumpmap
				envmap_variant = ((GetFloatParam( info.m_nEnvMapLightScale, params ) > 0.0f) && (g_pHardwareConfig->SupportsPixelShaders_2_b() || !hasBump2)) ? 2 : 1;
			}
			else
			{
				envmap_variant = 0; 
			}

			bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && 
									  ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) );
			
			if ( bNeedRegenStaticCmds )
			{
				pContextData->m_bNeedsCmdRegen = false;

				pContextData->ResetStaticCmds();
				CCommandBufferBuilder< CFixedCommandStorageBuffer< 5000 > > staticCmdsBuf;

				int nLightingPreviewMode = !bHasFoW ? IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ) : 0;
				if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() )
				{
					staticCmdsBuf.SetVertexShaderNearAndFarZ( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 );	// Needed for SSAO
				}

				if( !hasBaseTexture )
				{
					if( hasEnvmap )
					{
						// if we only have an envmap (no basetexture), then we want the albedo to be black.
						staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_BLACK );
					}
					else
					{
						staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
					}
				}
				staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP );

				if ( g_pConfig->m_bPaintInGame && !r_twopasspaint.GetBool() )
				{
					staticCmdsBuf.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_PAINT );
				}

				if ( bSeamlessMapping )
				{
					staticCmdsBuf.SetVertexShaderConstant4(
						VERTEX_SHADER_SHADER_SPECIFIC_CONST_0,
						params[info.m_nSeamlessMappingScale]->GetFloatValue(),0,0,0 );
				}

				staticCmdsBuf.StoreEyePosInPixelShaderConstant( 10 );
				staticCmdsBuf.SetPixelShaderFogParams( 11 );
				staticCmdsBuf.End();
				// now, copy buf
				pContextData->m_pStaticCmds = new uint8[staticCmdsBuf.Size()];
				memcpy( pContextData->m_pStaticCmds, staticCmdsBuf.Base(), staticCmdsBuf.Size() );
			}
			if ( pShaderShadow )
			{

				// Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState
				pShaderShadow->EnableAlphaTest( bIsAlphaTested );
				if ( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
				{
					pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
				}

				pShader->SetDefaultBlendingShadowState( nAlphaChannelTextureVar, hasBaseTexture );

				unsigned int flags = VERTEX_POSITION;

				// base texture
				pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead );

				if ( g_pConfig->m_bPaintInGame && !r_twopasspaint.GetBool() )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, !bShaderSrgbRead );
				}

				if ( hasLightWarpTexture )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false );
				}
				if ( bHasBlendModulateTexture )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false );
				}

				if ( hasBaseTexture2 )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, !bShaderSrgbRead );
				}
//		if( hasLightmap )
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );
				}
				else
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false );
				}

				if( hasEnvmap || ( IsX360() && hasFlashlight ) )
				{
					if( hasEnvmap )
					{
						pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
						if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
						{
							pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );
						}
					}
					flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL;
				}

#define TCOMBINE_NONE 12									// there is no detail texture

				int nDetailBlendMode = TCOMBINE_NONE;

				if ( hasDetailTexture )
				{
					nDetailBlendMode = GetIntParam( info.m_nDetailTextureCombineMode, params );
					ITexture *pDetailTexture = params[info.m_nDetail]->GetTextureValue();
					if ( pDetailTexture->GetFlags() & TEXTUREFLAGS_SSBUMP )
					{
						if ( hasBump )
							nDetailBlendMode = 10;					// ssbump
						else
							nDetailBlendMode = 11;					// ssbump_nobump
					}
					pShaderShadow->EnableTexture( SHADER_SAMPLER12, true );
					bool bSRGBState = ( nDetailBlendMode == 1 );
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, bSRGBState );
				}

				// Hijack detail blend mode 9 for paint (this blend mode was previously skipped/unused in lightmappedgeneric)
				if ( g_pConfig->m_bPaintInGame && !r_twopasspaint.GetBool() )
				{
					nDetailBlendMode = 9;
				}
				
				if( hasBump || hasNormalMapAlphaEnvmapMask )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
				}
				if( hasBump2 )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
				}
				if( hasBumpMask )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );
				}
				if( hasEnvmapMask )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
				}

				if( bHasFoW )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
				}

				if( bDeferredActive )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
					pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
				}

				if( hasFlashlight && IsX360() )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
					pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
					pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER14 );
					pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
				}

				if( hasVertexColor || hasBaseTexture2 || hasBump2 )
				{
					flags |= VERTEX_COLOR;
				}

				// texcoord0 : base texcoord
				// texcoord1 : lightmap texcoord
				// texcoord2 : lightmap texcoord offset
				int numTexCoords;
				
				// if ( pShaderAPI->InEditorMode() )
// 				if ( pShader->CanUseEditorMaterials() )
// 				{
// 					numTexCoords = 1;
// 				}
// 				else
				{
					numTexCoords = 2;
					if( hasBump )
					{
						numTexCoords = 3;
					}
				}
		
				int nLightingPreviewMode = !bHasFoW ? IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ) : 0;

				pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 );

				// Pre-cache pixel shaders
				bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK );

				int bumpmap_variant=(hasSSBump) ? 2 : hasBump;
				bool bMaskedBlending=( (info.m_nMaskedBlending != -1) &&
									   (params[info.m_nMaskedBlending]->GetIntValue() != 0) );

				if( bDeferredActive )
				{
					DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_deferred_vs30 );
					SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK,  hasEnvmapMask );
					SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE,  params[info.m_nEnvmap]->IsTexture() );
					SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP,  hasBump );
					SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap );
					SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) );
					SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, hasBaseTexture2 || hasBump2 );
					SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, hasBumpMask );
					SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode );
					SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping );
					SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
					SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture );
					SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture );
					SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
					SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW );
					SET_STATIC_VERTEX_SHADER( lightmappedgeneric_deferred_vs30 );

					DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_deferred_ps30 );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  bumpmap_variant );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask );
					SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
					SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  envmap_variant );
					SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK,  hasEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK,  hasBaseAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP,  params[info.m_nBaseTextureNoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending);
					SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline );
					SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
					SET_STATIC_PIXEL_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
					SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode );
					SET_STATIC_PIXEL_SHADER( lightmappedgeneric_deferred_ps30 );
				}
				else
				{
					DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs30 );
					SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK,  hasEnvmapMask );
					SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE,  params[info.m_nEnvmap]->IsTexture() );
					SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP,  hasBump );
					SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP, hasDiffuseBumpmap );
					SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR, IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) );
					SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, hasBaseTexture2 || hasBump2 );
					SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK, hasBumpMask );
					SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode );
					SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping );
					SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
					SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture );
					SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture );
					SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
					SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW );
					SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs30 );

					DECLARE_STATIC_PIXEL_SHADER( lightmappedgeneric_ps30 );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, hasBaseTexture2 );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  bumpmap_variant );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP2, hasBump2 );
					SET_STATIC_PIXEL_SHADER_COMBO( BUMPMASK, hasBumpMask );
					SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
					SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  envmap_variant );
					SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK,  hasEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK,  hasBaseAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
					SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURENOENVMAP,  params[info.m_nBaseTextureNoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2NOENVMAP, params[info.m_nBaseTexture2NoEnvmap]->GetIntValue() );
					SET_STATIC_PIXEL_SHADER_COMBO( WARPLIGHTING, hasLightWarpTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( FANCY_BLENDING, bHasBlendModulateTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( MASKEDBLENDING, bMaskedBlending);
					SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS, bSeamlessMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( OUTLINE, bHasOutline );
					SET_STATIC_PIXEL_SHADER_COMBO( SOFTEDGES, bHasSoftEdges );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, hasDetailTexture );
					SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
					SET_STATIC_PIXEL_SHADER_COMBO( PARALLAX_MAPPING, bParallaxMapping );
					SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
					SET_STATIC_PIXEL_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode );
					SET_STATIC_PIXEL_SHADER( lightmappedgeneric_ps30 );
				}

				// HACK HACK HACK - enable alpha writes all the time so that we have them for
				// underwater stuff and writing depth to dest alpha
				// But only do it if we're not using the alpha already for translucency
				pShaderShadow->EnableAlphaWrites( bFullyOpaque );

				pShaderShadow->EnableSRGBWrite( true );

				pShader->DefaultFog();

				// NOTE: This isn't optimal. If $color2 is ever changed by a material
				// proxy, this code won't get re-run, but too bad. No time to make this work
				// Also note that if the lightmap scale factor changes
				// all shadow state blocks will be re-run, so that's ok
				float flLScale = pShaderShadow->GetLightMapScaleFactor();
				pShader->PI_BeginCommandBuffer();
				pShader->PI_SetModulationPixelShaderDynamicState( 21 );

				// MAINTOL4DMERGEFIXME
				// Need to reflect this change which is from this rel changelist since this constant set was moved from the dynamic block to here:
				// Change 578692 by Alex@alexv_rel on 2008/06/04 18:07:31
				//
				// Fix for portalareawindows in ep2 being rendered black. The color variable was being multipurposed for both the vs and ps differently where the ps doesn't care about alpha, but the vs does. Only applying the alpha2 DoD hack to the pixel shader constant where the alpha was never used in the first place and leaving alpha as is for the vs.

  				// color[3] *= ( IS_PARAM_DEFINED( info.m_nAlpha2 ) && params[ info.m_nAlpha2 ]->GetFloatValue() > 0.0f ) ? params[ info.m_nAlpha2 ]->GetFloatValue() : 1.0f;
  	  	  		// pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, color );

				pShader->PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( 12, flLScale );
				pShader->PI_SetModulationVertexShaderDynamicState_LinearScale( flLScale );
				pShader->PI_EndCommandBuffer();
			} // end shadow state
		} // end shadow || regen display list

		if ( pShaderAPI && ( pContextData->m_bMaterialVarsChanged ) )
		{
			// need to regenerate the semistatic cmds
			pContextData->m_SemiStaticCmdsOut.Reset();
			pContextData->m_bMaterialVarsChanged = false;

			bool bHasBlendMaskTransform= (
				(info.m_nBlendMaskTransform != -1) &&
				(info.m_nMaskedBlending != -1) &&
				(params[info.m_nMaskedBlending]->GetIntValue() ) &&
				( ! (params[info.m_nBumpTransform]->MatrixIsIdentity() ) ) );
			
			// If we don't have a texture transform, we don't have
			// to set vertex shader constants or run vertex shader instructions
			// for the texture transform.
			bool bHasTextureTransform = 
				!( params[info.m_nBaseTextureTransform]->MatrixIsIdentity() &&
				   params[info.m_nBumpTransform]->MatrixIsIdentity() &&
				   params[info.m_nBumpTransform2]->MatrixIsIdentity() &&
				   params[info.m_nEnvmapMaskTransform]->MatrixIsIdentity() );
			
			bHasTextureTransform |= bHasBlendMaskTransform;
			
			pContextData->m_bVertexShaderFastPath = !bHasTextureTransform;

			if( params[info.m_nDetail]->IsTexture() )
			{
				pContextData->m_bVertexShaderFastPath = false;
			}
			int nTransformToLoad = info.m_nBlendMaskTransform;
			if( ( hasBump || hasSSBump ) && hasDetailTexture && !hasSelfIllum && !bHasBlendModulateTexture )
			{
				nTransformToLoad = info.m_nBumpTransform;
			}
			pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( 
				VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, nTransformToLoad );

			if ( ! pContextData->m_bVertexShaderFastPath )
			{
				bool bSeamlessMapping = ( ( info.m_nSeamlessMappingScale != -1 ) && 
										  ( params[info.m_nSeamlessMappingScale]->GetFloatValue() != 0.0 ) );
				bool hasEnvmapMask = params[info.m_nEnvmapMask]->IsTexture() && !bHasFoW;
				if (!bSeamlessMapping )
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
				// If we have a detail texture, then the bump texcoords are the same as the base texcoords.
				if( hasBump && !hasDetailTexture )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
				}
				if( hasEnvmapMask )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform );
				}
				else if ( hasBump2 )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform2 );
				}
			}
			pContextData->m_SemiStaticCmdsOut.SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint );
			
			if ( hasDetailTexture )
			{
				float detailTintAndBlend[4] = {1, 1, 1, 1};
				
				if ( info.m_nDetailTint != -1 )
				{
					params[info.m_nDetailTint]->GetVecValue( detailTintAndBlend, 3 );
				}
				
				detailTintAndBlend[3] = fDetailBlendFactor;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 8, detailTintAndBlend );
			}
			
			float envmapTintVal[4];
			float selfIllumTintVal[4];
			params[info.m_nEnvmapTint]->GetVecValue( envmapTintVal, 3 );
			params[info.m_nSelfIllumTint]->GetVecValue( selfIllumTintVal, 3 );
			float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue();
			float envmapSaturation = params[info.m_nEnvmapSaturation]->GetFloatValue();
			float fresnelReflection = params[info.m_nFresnelReflection]->GetFloatValue();
			bool hasEnvmap = params[info.m_nEnvmap]->IsTexture();
			int envmap_variant; //0 = no envmap, 1 = regular, 2 = darken in shadow mode
			if( hasEnvmap )
			{
				//only enabled darkened cubemap mode when the scale calls for it. And not supported in ps20 when also using a 2nd bumpmap
				envmap_variant = ((GetFloatParam( info.m_nEnvMapLightScale, params ) > 0.0f) && (g_pHardwareConfig->SupportsPixelShaders_2_b() || !hasBump2)) ? 2 : 1;
			}
			else
			{
				envmap_variant = 0; 
			}

			pContextData->m_bPixelShaderFastPath = true;
			bool bUsingContrastOrSaturation = hasEnvmap && ( ( (envmapContrast != 0.0f) && (envmapContrast != 1.0f) ) || (envmapSaturation != 1.0f) );
			bool bUsingFresnel = hasEnvmap && (fresnelReflection != 1.0f);
			bool bUsingSelfIllumTint = IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && (selfIllumTintVal[0] != 1.0f || selfIllumTintVal[1] != 1.0f || selfIllumTintVal[2] != 1.0f); 
			if ( bUsingContrastOrSaturation || bUsingFresnel || bUsingSelfIllumTint || !g_pConfig->bShowSpecular )
			{
				pContextData->m_bPixelShaderFastPath = false;
			}
			if( !pContextData->m_bPixelShaderFastPath )
			{
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstants( 2, 3 );
				pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapContrast]->GetVecValue() );
				pContextData->m_SemiStaticCmdsOut.OutputConstantData( params[info.m_nEnvmapSaturation]->GetVecValue() );
				float flFresnel = params[info.m_nFresnelReflection]->GetFloatValue();
				// [ 0, 0, 1-R(0), R(0) ]
				pContextData->m_SemiStaticCmdsOut.OutputConstantData4( 0., 0., 1.0 - flFresnel, flFresnel );
				
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 7, params[info.m_nSelfIllumTint]->GetVecValue() );
			}
			else
			{
				if ( bHasOutline )
				{
					float flOutlineParms[8] = { GetFloatParam( info.m_nOutlineStart0, params ),
												GetFloatParam( info.m_nOutlineStart1, params ),
												GetFloatParam( info.m_nOutlineEnd0, params ),
												GetFloatParam( info.m_nOutlineEnd1, params ),
												0,0,0,
												GetFloatParam( info.m_nOutlineAlpha, params ) };
					if ( info.m_nOutlineColor != -1 )
					{
						params[info.m_nOutlineColor]->GetVecValue( flOutlineParms + 4, 3 );
					}
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 2, flOutlineParms, 2 );
				}

				if ( bHasSoftEdges )
				{
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 
						4, GetFloatParam( info.m_nEdgeSoftnessStart, params ),
						GetFloatParam( info.m_nEdgeSoftnessEnd, params ),
						0,0 );
				}
			}

			// parallax and cubemap light scale mapping parms (c20)
			if ( bParallaxMapping || (envmap_variant == 2) )
			{
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 20, GetFloatParam( info.m_nHeightScale, params), GetFloatParam( info.m_nEnvMapLightScale, params), 0, 0 );
			}

			// texture binds
			if( hasBaseTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
			}
			// handle mat_fullbright 2
			bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
			if( bLightingOnly )
			{
				// BASE TEXTURE
				if( hasSelfIllum )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO );
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );
				}

				// BASE TEXTURE 2	
				if( hasBaseTexture2 )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_GREY );
				}

				// DETAIL TEXTURE
				if( hasDetailTexture )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER12, TEXTURE_GREY );
				}

				// disable color modulation
				float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_MODULATION_COLOR, color );

				// turn off environment mapping
				envmapTintVal[0] = 0.0f;
				envmapTintVal[1] = 0.0f;
				envmapTintVal[2] = 0.0f;
			}

			// always set the transform for detail textures since I'm assuming that you'll
			// always have a detailscale.
			if( hasDetailTexture )
			{
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale );
			}

			if( hasBaseTexture2 )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nBaseTexture2, info.m_nBaseTexture2Frame );
			}
			if( hasDetailTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetail, info.m_nDetailFrame );
			}

			if( hasBump || hasNormalMapAlphaEnvmapMask )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nBumpmap, info.m_nBumpFrame );
				}
				else
				{
					if( hasSSBump )
					{
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_SSBUMP_FLAT );
					}
					else
					{
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT );
					}
				}
			}
			if( hasBump2 )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nBumpmap2, info.m_nBumpFrame2 );
				}
				else
				{
					if( hasSSBump )
					{
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALMAP_FLAT );
					}
					else
					{
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SSBUMP_FLAT );
					}
				}
			}
			if( hasBumpMask )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nBumpMask, -1 );
				}
				else
				{
					// this doesn't make sense
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_NORMALMAP_FLAT );
				}
			}

			if( hasEnvmapMask )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame );
			}

			if ( hasLightWarpTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nLightWarpTexture, -1 );
			}

			if ( bHasBlendModulateTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBlendModulateTexture, -1 );
			}

			if ( hasFlashlight && IsX360() )
			{
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderFlashlightState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 );

				CBCmdSetPixelShaderFlashlightState_t state;
				state.m_LightSampler = SHADER_SAMPLER13;
				state.m_DepthSampler = SHADER_SAMPLER14;
				state.m_ShadowNoiseSampler = SHADER_SAMPLER15;
				state.m_nColorConstant = 28;
				state.m_nAttenConstant = 13;
				state.m_nOriginConstant = 14;
				state.m_nDepthTweakConstant = 19;
				state.m_nScreenScaleConstant = 31;
				state.m_nWorldToTextureConstant = -1;
				state.m_bFlashlightNoLambert = false;
				state.m_bSinglePassFlashlight = bSinglePassFlashlight;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state );
			}

			pContextData->m_SemiStaticCmdsOut.End();
		}
	}
	DYNAMIC_STATE
	{
		CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut;
		DynamicCmdsOut.Call( pContextData->m_pStaticCmds );
		DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() );

		bool hasEnvmap = params[info.m_nEnvmap]->IsTexture();

		if( hasEnvmap )
		{
			DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nEnvmap, info.m_nEnvmapFrame );
		}

		bool bVertexShaderFastPath = pContextData->m_bVertexShaderFastPath;

		int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );
		if( nFixedLightingMode != ENABLE_FIXED_LIGHTING_NONE )
		{
			if ( pContextData->m_bPixelShaderForceFastPathBecauseOutline )
			{
				nFixedLightingMode = ENABLE_FIXED_LIGHTING_NONE;
			}
			else
			{
				bVertexShaderFastPath = false;
			}
		}

		bool bWorldNormal = ( nFixedLightingMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH );
		if ( bWorldNormal && IsPC() )
		{
			float vEyeDir[4];
			pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir );

			float flFarZ = pShaderAPI->GetFarZ();
			vEyeDir[0] /= flFarZ;	// Divide by farZ for SSAO algorithm
			vEyeDir[1] /= flFarZ;
			vEyeDir[2] /= flFarZ;
			DynamicCmdsOut.SetVertexShaderConstant4( 12, vEyeDir[0], vEyeDir[1], vEyeDir[2], 1.0f );
		}

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();

		if( bDeferredActive )
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_deferred_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH,  bVertexShaderFastPath );
			SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_deferred_vs30 );
		}
		else
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH,  bVertexShaderFastPath );
			SET_DYNAMIC_VERTEX_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_vs30 );
		}

		bool bPixelShaderFastPath = pContextData->m_bPixelShaderFastPath;

		if ( nFixedLightingMode != ENABLE_FIXED_LIGHTING_NONE )
		{
			bPixelShaderFastPath = false;
		}
		bool bWriteDepthToAlpha;
		bool bWriteWaterFogToAlpha;
		if(  pContextData->m_bFullyOpaque ) 
		{
			bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
			bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
			AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
		}
		else
		{
			//can't write a special value to dest alpha if we're actually using as-intended alpha
			bWriteDepthToAlpha = false;
			bWriteWaterFogToAlpha = false;
		}

		if( bHasFoW )
		{
			if( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) )
				DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER13, info.m_nFoW, -1 );
			else
				DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER13, TEXTURE_WHITE );

			float	vFoWSize[ 4 ];
			Vector	vMins = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MINS );
			Vector	vMaxs = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MAXS );
			vFoWSize[ 0 ] = vMins.x;
			vFoWSize[ 1 ] = vMins.y;
			vFoWSize[ 2 ] = vMaxs.x - vMins.x;
			vFoWSize[ 3 ] = vMaxs.y - vMins.y;
			DynamicCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_12, vFoWSize );
		}

		if( bDeferredActive )
		{
			DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER14, GetDeferredExt()->GetTexture_LightAccum(), 0 );
			DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER15, GetDeferredExt()->GetTexture_LightAccum2(), 0 );
			//DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER14, TEXTURE_WHITE );
			int x, y, w, t;
			pShaderAPI->GetCurrentViewport( x, y, w, t );
			float fl1[4] = { 1.0f / w, 1.0f / t, 0, 0 };

			DynamicCmdsOut.SetPixelShaderConstant( PSREG_UBERLIGHT_SMOOTH_EDGE_0, fl1 );
		}

		bool bFlashlightShadows = false;
		bool bUberlight = false;
		if( hasFlashlight && IsX360() )
		{
			pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight );
		}
		else
		{
			// only do ambient light when not using flashlight
			static ConVarRef mat_ambient_light_r_forced( "mat_ambient_light_r_forced" );
			static ConVarRef mat_ambient_light_g_forced( "mat_ambient_light_g_forced" );
			static ConVarRef mat_ambient_light_b_forced( "mat_ambient_light_b_forced" );

			float vAmbientColor[4] = { mat_ambient_light_r_forced.GetFloat() != -1.0f ? mat_ambient_light_r_forced.GetFloat() : mat_ambient_light_r.GetFloat(), 
									   mat_ambient_light_g_forced.GetFloat() != -1.0f ? mat_ambient_light_g_forced.GetFloat() : mat_ambient_light_g.GetFloat(), 
									   mat_ambient_light_b_forced.GetFloat() != -1.0f ? mat_ambient_light_b_forced.GetFloat() : mat_ambient_light_b.GetFloat(), 
									   0.0f };
			if ( mat_fullbright.GetInt() == 1 )
			{
				vAmbientColor[0] = vAmbientColor[1] = vAmbientColor[2] = 0.0f;
			}
			DynamicCmdsOut.SetPixelShaderConstant( 31, vAmbientColor, 1 );
		}

		float envmapContrast = params[info.m_nEnvmapContrast]->GetFloatValue();

		if( bDeferredActive )
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_deferred_ps30);
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH,  bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST,  bPixelShaderFastPath && envmapContrast == 1.0f );

			// Don't write fog to alpha if we're using translucency
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, /*bFlashlightShadows*/ 0 );
			SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_deferred_ps30 );
		}
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( lightmappedgeneric_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATH,  bPixelShaderFastPath || pContextData->m_bPixelShaderForceFastPathBecauseOutline );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FASTPATHENVMAPCONTRAST,  bPixelShaderFastPath && envmapContrast == 1.0f );

			// Don't write fog to alpha if we're using translucency
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER_CMD( DynamicCmdsOut, lightmappedgeneric_ps30 );
		}

		DynamicCmdsOut.End();
		pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() );
	}
	pShader->Draw();

	if( !bDeferredActive && IsPC() && (IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0) && pContextData->m_bFullyOpaqueWithoutAlphaTest )
	{
		//Alpha testing makes it so we can't write to dest alpha
		//Writing to depth makes it so later polygons can't write to dest alpha either
		//This leads to situations with garbage in dest alpha.

		//Fix it now by converting depth to dest alpha for any pixels that just wrote.
		pShader->DrawEqualDepthToDestAlpha();
	}
}
void DrawPassLightPassVolum( const lightPassParms &info, CBaseVSShader *pShader, IMaterialVar **params,
	IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI,
	VertexCompressionType_t vertexCompression )
{
	const bool bWorldProjection = PARM_SET( info.iWorldProjection );
	const int iLightType = PARM_INT( info.iLightTypeVar );

	const bool bPoint = iLightType == DEFLIGHTTYPE_POINT;

	SHADOW_STATE
	{
		pShaderShadow->SetDefaultState();
		pShaderShadow->EnableDepthTest( false );
		pShaderShadow->EnableDepthWrites( false );
		pShaderShadow->EnableAlphaWrites( false );
		pShaderShadow->EnableCulling( true );

		pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE );

		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );

		for ( int i = 0; i < FREE_LIGHT_SAMPLERS; i++ )
		{
			pShaderShadow->EnableTexture( (Sampler_t)( FIRST_LIGHT_SAMPLER + i ), true );
		}

		pShaderShadow->VertexShaderVertexFormat( VERTEX_POSITION, 1, NULL, 0 );

		DECLARE_STATIC_VERTEX_SHADER( defconstruct_vs30 );
		SET_STATIC_VERTEX_SHADER_COMBO( USEWORLDTRANSFORM, bWorldProjection ? 1 : 0 );
		SET_STATIC_VERTEX_SHADER_COMBO( SENDWORLDPOS, bWorldProjection ? 1 : 0 );
		SET_STATIC_VERTEX_SHADER( defconstruct_vs30 );

		switch ( iLightType )
		{
		case DEFLIGHTTYPE_POINT:
			{
				DECLARE_STATIC_PIXEL_SHADER( volumpass_point_ps30 );
				SET_STATIC_PIXEL_SHADER_COMBO( USEWORLDTRANSFORM, bWorldProjection ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER( volumpass_point_ps30 );
			}
			break;
		case DEFLIGHTTYPE_SPOT:
			{
				DECLARE_STATIC_PIXEL_SHADER( volumpass_spot_ps30 );
				SET_STATIC_PIXEL_SHADER_COMBO( USEWORLDTRANSFORM, bWorldProjection ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER( volumpass_spot_ps30 );
			}
			break;
		}
	}
	DYNAMIC_STATE
	{
		pShaderAPI->SetDefaultState();

		CDeferredExtension *pExt = GetDeferredExt();

		const volumeData_t &vData = GetDeferredExt()->GetVolumeData();

		Assert( pExt->GetActiveLightData() != NULL );
		Assert( pExt->GetActiveLights_NumRows() != NULL );

		const int iNumShadowedCookied = vData.bHasCookie ? 1:0;
		const int iNumShadowed = vData.bHasCookie ? 0:1;

		Assert( (iNumShadowedCookied + iNumShadowed) == 1 );
		Assert( iNumShadowedCookied <= pExt->GetNumActiveLights_ShadowedCookied() );
		Assert( iNumShadowed <= pExt->GetNumActiveLights_Shadowed() );

		DECLARE_DYNAMIC_VERTEX_SHADER( defconstruct_vs30 );
		SET_DYNAMIC_VERTEX_SHADER( defconstruct_vs30 );

		switch ( iLightType )
		{
		case DEFLIGHTTYPE_POINT:
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( volumpass_point_ps30 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_SHADOWED_COOKIE, iNumShadowedCookied );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_SHADOWED, iNumShadowed );
				SET_DYNAMIC_PIXEL_SHADER( volumpass_point_ps30 );
			}
			break;
		case DEFLIGHTTYPE_SPOT:
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( volumpass_spot_ps30 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_SHADOWED_COOKIE, iNumShadowedCookied );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_SHADOWED, iNumShadowed );
				SET_DYNAMIC_PIXEL_SHADER( volumpass_spot_ps30 );
			}
			break;
		}

		pShader->BindTexture( SHADER_SAMPLER0, GetDeferredExt()->GetTexture_VolumePrePass() );
		pShader->BindTexture( SHADER_SAMPLER1, GetDeferredExt()->GetTexture_Depth() );

		int iSampler = 0;
		int iShadow = vData.iSamplerOffset;
		int iCookie = vData.iSamplerOffset;

		for ( ; iSampler < (iNumShadowedCookied*2);)
		{
			ITexture *pDepth = bPoint ? GetDeferredExt()->GetTexture_ShadowDepth_DP(iShadow) :
				GetDeferredExt()->GetTexture_ShadowDepth_Proj(iShadow);

			pShader->BindTexture( (Sampler_t)( FIRST_LIGHT_SAMPLER + iSampler ), pDepth );
			pShader->BindTexture( (Sampler_t)( FIRST_LIGHT_SAMPLER + iSampler + 1 ), GetDeferredExt()->GetTexture_Cookie(iCookie) );

			iSampler += 2;
			iShadow++;
			iCookie++;
		}

		for ( ; iSampler < (iNumShadowedCookied*2+iNumShadowed); )
		{
			ITexture *pDepth = bPoint ? GetDeferredExt()->GetTexture_ShadowDepth_DP(iShadow) :
				GetDeferredExt()->GetTexture_ShadowDepth_Proj(iShadow);

			pShader->BindTexture( (Sampler_t)( FIRST_LIGHT_SAMPLER + iSampler ), pDepth );

			iSampler++;
			iShadow++;
		}

		const int frustumReg = bWorldProjection ? 3 : VERTEX_SHADER_SHADER_SPECIFIC_CONST_0;
		CommitBaseDeferredConstants_Frustum( pShaderAPI, frustumReg, !bWorldProjection );
		CommitBaseDeferredConstants_Origin( pShaderAPI, 0 );

		pShaderAPI->SetPixelShaderConstant( FIRST_SHARED_LIGHTDATA_CONSTANT,
			pExt->GetActiveLightData() + vData.iDataOffset,
			vData.iNumRows );

		if ( bWorldProjection )
		{
			CommitHalfScreenTexel( pShaderAPI, 6 );
		}
	}

	pShader->Draw();
}
//-----------------------------------------------------------------------------
// Draws the shader
//-----------------------------------------------------------------------------
void DrawVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, 
	IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info )
{
	Assert( info.m_nPhong >= 0 );
	if( params[info.m_nPhong]->GetIntValue() )
	{
		DrawSkin_DX9( pShader, params, pShaderAPI, pShaderShadow, true, info );
		return;		
	}

	bool hasBaseTexture = params[info.m_nBaseTexture]->IsTexture();
	bool hasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture();
	bool hasDetailTexture = !hasBump && params[info.m_nDetail]->IsTexture();
	bool hasDiffuseLighting = bVertexLitGeneric;
	bool hasBaseAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_BASEALPHAENVMAPMASK );
	bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );
	bool hasVertexColor = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
	bool hasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA );
	bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
	bool hasSelfIllumInEnvMapMask =
		( info.m_nSelfIllumEnvMapMask_Alpha != -1 ) &&
		( params[info.m_nSelfIllumEnvMapMask_Alpha]->GetFloatValue() != 0.0 ) ;
	bool bAmbientOnly = (info.m_nAmbientOnly != -1) && (params[info.m_nAmbientOnly]->GetIntValue() == 1);

	BlendType_t blendType;
	if ( params[info.m_nBaseTexture]->IsTexture() )
	{
		blendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
	}
	else
	{
		blendType = pShader->EvaluateBlendRequirements( info.m_nEnvmapMask, false );
	}
	
	if( pShader->IsSnapshotting() )
	{
		// look at color and alphamod stuff.
		// Unlit generic never uses the flashlight
		bool hasFlashlight = hasDiffuseLighting && CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_FLASHLIGHT );
		bool hasEnvmap = !hasFlashlight && params[info.m_nEnvmap]->IsTexture();
		bool hasEnvmapMask = (hasSelfIllumInEnvMapMask || !hasFlashlight) && 
			params[info.m_nEnvmapMask]->IsTexture();
		bool bHasNormal = bVertexLitGeneric || hasEnvmap;
		bool hasSelfIllum = !hasFlashlight && IS_FLAG_SET( MATERIAL_VAR_SELFILLUM );

		if( hasFlashlight ) hasEnvmapMask = false;

		bool bHalfLambert = IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT );
		// Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState
		pShaderShadow->EnableAlphaTest( bIsAlphaTested );

		if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
		{
			pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
		}

		if( hasFlashlight )
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
			}
			else
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nEnvmapMask, false );
			}
			if( bIsAlphaTested )
			{
				// disable alpha test and use the zfunc zequals since alpha isn't guaranteed to 
				// be the same on both the regular pass and the flashlight pass.
				pShaderShadow->EnableAlphaTest( false );
				pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
			}
			pShaderShadow->EnableBlending( true );
			pShaderShadow->EnableDepthWrites( false );
		}
		else
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
			}
			else
			{
				pShader->SetDefaultBlendingShadowState( info.m_nEnvmapMask, false );
			}
		}
		
		unsigned int flags = VERTEX_POSITION;
		if( bHasNormal )
		{
			flags |= VERTEX_NORMAL;
		}

		int userDataSize = 0;
		if( hasBaseTexture )
		{
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE0, true );
			pShaderShadow->EnableSRGBRead( SHADER_TEXTURE_STAGE0, true );
		}
		if( hasEnvmap )
		{
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE1, true );
			if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
			{
				pShaderShadow->EnableSRGBRead( SHADER_TEXTURE_STAGE1, true );
			}
		}
		if( hasFlashlight )
		{
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE7, true );
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE4, true );
			userDataSize = 4; // tangent S
		}
		if( hasDetailTexture )
		{
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE2, true );
		}
		if( hasBump )
		{
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE3, true );
			userDataSize = 4; // tangent S
			// Normalizing cube map
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE5, true );
		}
		if( hasEnvmapMask )
		{
			pShaderShadow->EnableTexture( SHADER_TEXTURE_STAGE4, true );
		}

		if( hasVertexColor || hasVertexAlpha )
		{
			flags |= VERTEX_COLOR;
		}

		pShaderShadow->EnableSRGBWrite( true );
		
		// texcoord0 : base texcoord
		const int numTexCoords = 1;
		int numBoneWeights = 0;
		if( IS_FLAG_SET( MATERIAL_VAR_MODEL ) )
		{
			numBoneWeights = 3;
			flags |= VERTEX_BONE_INDEX;
		}
		
		pShaderShadow->VertexShaderVertexFormat( 
			flags, numTexCoords, NULL, numBoneWeights, userDataSize );

		if ( hasBump )
		{
			DECLARE_STATIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_bump_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
			SET_STATIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_bump_vs20 );
			
			DECLARE_STATIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_bump_ps20 );
			SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE,  hasBaseTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING,  hasDiffuseLighting );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMALMAPALPHAENVMAPMASK,  hasNormalMapAlphaEnvmapMask );
			SET_STATIC_PIXEL_SHADER_COMBO( HALFLAMBERT,  bHalfLambert);
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
			SET_STATIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_bump_ps20 );
		}
		else
		{
			DECLARE_STATIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor || hasVertexAlpha );
			SET_STATIC_VERTEX_SHADER_COMBO( CUBEMAP,  hasEnvmap );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT,  bHalfLambert );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
			SET_STATIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_vs20 );
			
			DECLARE_STATIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_ps20 );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAPMASK_ALPHA, 
										   ( hasSelfIllumInEnvMapMask && ( hasEnvmapMask ) ) );
			SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE,  hasBaseTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  hasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSELIGHTING,  hasDiffuseLighting );
			SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK,  hasEnvmapMask );
			SET_STATIC_PIXEL_SHADER_COMBO( BASEALPHAENVMAPMASK,  hasBaseAlphaEnvmapMask );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
			SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor );
			SET_STATIC_PIXEL_SHADER_COMBO( VERTEXALPHA,  hasVertexAlpha );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
			SET_STATIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_ps20 );
		}

		if( hasFlashlight )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->DefaultFog();
		}

		// HACK HACK HACK - enable alpha writes all the time so that we have them for
		// underwater stuff
		if( blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested )
		{
			pShaderShadow->EnableAlphaWrites( true );
		}
	}
	else
	{
		bool hasFlashlight = hasDiffuseLighting && pShaderAPI->InFlashlightMode();
		bool hasEnvmap = !hasFlashlight && params[info.m_nEnvmap]->IsTexture();
		bool hasEnvmapMask = !hasFlashlight && params[info.m_nEnvmapMask]->IsTexture();

		if( hasBaseTexture )
		{
			pShader->BindTexture( SHADER_TEXTURE_STAGE0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
		}
		if( hasEnvmap )
		{
			pShader->BindTexture( SHADER_TEXTURE_STAGE1, info.m_nEnvmap, info.m_nEnvmapFrame );
		}
		if( hasDetailTexture )
		{
			pShader->BindTexture( SHADER_TEXTURE_STAGE2, info.m_nDetail, info.m_nDetailFrame );
		}
		if( !g_pConfig->m_bFastNoBump )
		{
			if( hasBump )
			{
				pShader->BindTexture( SHADER_TEXTURE_STAGE3, info.m_nBumpmap, info.m_nBumpFrame );
			}
		}
		else
		{
			if( hasBump )
			{
				pShaderAPI->BindFlatNormalMap( SHADER_TEXTURE_STAGE3 );
			}
		}
		if( hasEnvmapMask )
		{
			pShader->BindTexture( SHADER_TEXTURE_STAGE4, info.m_nEnvmapMask, info.m_nEnvmapMaskFrame );
		}
		bool bHasFlashlightDepth = false;
		if( hasFlashlight )
		{
			Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 );
			pShader->BindTexture( SHADER_TEXTURE_STAGE7, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame );
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			SetFlashLightColorFromState( state, pShaderAPI );
			if( pFlashlightDepthTexture )
			{
				pShader->BindTexture( SHADER_TEXTURE_STAGE4, pFlashlightDepthTexture, 0 );
				bHasFlashlightDepth = true;
			}
		}

		int lightCombo = 0;
		if( bVertexLitGeneric && !hasFlashlight )
		{
			lightCombo = pShaderAPI->GetCurrentLightCombo();
		}
		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
		int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;
		int numBones	= pShaderAPI->GetCurrentNumBones();

		if ( hasBump )
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_bump_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHT_COMBO,  lightCombo );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,  fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_BONES,  numBones );
			SET_DYNAMIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_bump_vs20 );

			DECLARE_DYNAMIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_bump_ps20 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( LIGHT_COMBO,  lightCombo );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z &&
				blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FOGTYPE, pShaderAPI->GetSceneFogMode() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTH, bHasFlashlightDepth );
			SET_DYNAMIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_bump_ps20 );
		}
		else
		{
			if ( bAmbientOnly )	// Override selected light combo to be ambient only
				lightCombo = 2;

			DECLARE_DYNAMIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHT_COMBO,  lightCombo );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,  fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_BONES,  numBones );
			SET_DYNAMIC_VERTEX_SHADER_COMBO(
				LIGHTING_PREVIEW, hasDiffuseLighting && pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0);
			SET_DYNAMIC_VERTEX_SHADER( sdk_vertexlit_and_unlit_generic_vs20 );

			DECLARE_DYNAMIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_ps20 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z &&
				blendType != BT_BLENDADD && blendType != BT_BLEND && !bIsAlphaTested );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FOGTYPE, pShaderAPI->GetSceneFogMode() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO(
				LIGHTING_PREVIEW, hasDiffuseLighting && pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING));
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTH, bHasFlashlightDepth );
			SET_DYNAMIC_PIXEL_SHADER( sdk_vertexlit_and_unlit_generic_ps20 );
		}

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
		if( hasDetailTexture )
		{
			pShader->SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale );
			Assert( !hasBump );
		}
		if( hasBump )
		{
			pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
			Assert( !hasDetailTexture );
		}
		if( hasEnvmapMask )
		{
			pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform );
		}
		
		if( hasEnvmap )
		{
			pShader->SetEnvMapTintPixelShaderDynamicState( 0, info.m_nEnvmapTint, -1, true );
		}
		if( ( info.m_nHDRColorScale != -1 ) && pShader->IsHDREnabled() )
		{
			pShader->SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( 1, params[info.m_nHDRColorScale]->GetFloatValue() );
		}
		else
		{
			pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
		}

		pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast );
		pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation );

		pShader->SetPixelShaderConstant( 4, info.m_nSelfIllumTint );
		pShader->SetAmbientCubeDynamicStateVertexShader();
		if( hasBump )
		{
			pShaderAPI->BindSignedNormalizationCubeMap( SHADER_TEXTURE_STAGE5 );
			pShaderAPI->SetPixelShaderStateAmbientLightCube( 5 );
            pShaderAPI->CommitPixelShaderLighting( 13 );
	
		}

		if( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z )
		{
			pShader->SetWaterFogColorPixelShaderConstantLinear( 19 );
		}

		float eyePos[4];
		pShaderAPI->GetWorldSpaceCameraPosition( eyePos );
		pShaderAPI->SetPixelShaderConstant( 20, eyePos, 1 );
		pShaderAPI->SetPixelShaderFogParams( 21 );

		// flashlightfixme: put this in common code.
		if( hasFlashlight )
		{
			VMatrix worldToTexture;
			const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture );

			// Set the flashlight attenuation factors
			float atten[4];
			atten[0] = flashlightState.m_fConstantAtten;
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZ;
			pShaderAPI->SetPixelShaderConstant( 22, atten, 1 );

			// Set the flashlight origin
			float pos[4];
			pos[0] = flashlightState.m_vecLightOrigin[0];
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			pos[3] = 1.0f;
			pShaderAPI->SetPixelShaderConstant( 23, pos, 1 );

			pShaderAPI->SetPixelShaderConstant( 24, worldToTexture.Base(), 4 );
		}		
	}
}
//-----------------------------------------------------------------------------
// Draws the shader
//-----------------------------------------------------------------------------
void DrawExampleModel_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
	bool bHasFlashlight, ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression,
							CBasePerMaterialContextData **pContextDataPtr )
{
	bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture();
	bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;

	BlendType_t nBlendType= pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
	bool bFullyOpaque = ( nBlendType != BT_BLENDADD ) && ( nBlendType != BT_BLEND ) && !bIsAlphaTested && !bHasFlashlight;

	CExampleModel_DX9_Context *pContextData = reinterpret_cast< CExampleModel_DX9_Context *> ( *pContextDataPtr );
	if ( !pContextData )
	{
		pContextData = new CExampleModel_DX9_Context;
		*pContextDataPtr = pContextData;
	}

	if( pShader->IsSnapshotting() )
	{
		pShaderShadow->EnableAlphaTest( bIsAlphaTested );

		if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
		{
			pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
		}

		int nShadowFilterMode = 0;
		if( bHasFlashlight )
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
			}

			if( bIsAlphaTested )
			{
				// disable alpha test and use the zfunc zequals since alpha isn't guaranteed to 
				// be the same on both the regular pass and the flashlight pass.
				pShaderShadow->EnableAlphaTest( false );
				pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
			}
			pShaderShadow->EnableBlending( true );
			pShaderShadow->EnableDepthWrites( false );

			// Be sure not to write to dest alpha
			pShaderShadow->EnableAlphaWrites( false );

			nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
		}
		else // not flashlight pass
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
			}
		}
		
		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
		int userDataSize = 0;

		// Always enable...will bind white if nothing specified...
		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );		// Base (albedo) map
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );

		if( bHasFlashlight )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );	// Shadow depth map
			pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );	// Noise map
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Flashlight cookie
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true );
			userDataSize = 4; // tangent S
		}

		// Always enable, since flat normal will be bound
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );		// Normal map
		userDataSize = 4; // tangent S
		pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );		// Normalizing cube map
		pShaderShadow->EnableSRGBWrite( true );
		
		// texcoord0 : base texcoord, texcoord2 : decal hw morph delta
		int pTexCoordDim[3] = { 2, 0, 3 };
		int nTexCoordCount = 1;

		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize );

		DECLARE_STATIC_VERTEX_SHADER( example_model_vs20 );
		SET_STATIC_VERTEX_SHADER( example_model_vs20 );

		// Assume we're only going to get in here if we support 2b
		DECLARE_STATIC_PIXEL_SHADER( example_model_ps20b );
		SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
		SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
		SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 );
		SET_STATIC_PIXEL_SHADER( example_model_ps20b );

		if( bHasFlashlight )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->DefaultFog();
		}

		// HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff
		pShaderShadow->EnableAlphaWrites( bFullyOpaque );
	}
	else // not snapshotting -- begin dynamic state
	{
		bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE );

		if( bHasBaseTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
		}

		LightState_t lightState = { 0, false, false };
		bool bFlashlightShadows = false;
		if( bHasFlashlight )
		{
			Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 );
			pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame );
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			bFlashlightShadows = state.m_bEnableShadows && ( pFlashlightDepthTexture != NULL );

			SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR );

			if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D );
			}
		}
		else // no flashlight
		{
			pShaderAPI->GetDX9LightState( &lightState );
		}

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
		int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;
		int numBones = pShaderAPI->GetCurrentNumBones();

		bool bWriteDepthToAlpha = false;
		bool bWriteWaterFogToAlpha = false;
		if( bFullyOpaque ) 
		{
			bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
			bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
			AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
		}

		DECLARE_DYNAMIC_VERTEX_SHADER( example_model_vs20 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, fogIndex );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING)!=0);
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
		SET_DYNAMIC_VERTEX_SHADER( example_model_vs20 );

		DECLARE_DYNAMIC_PIXEL_SHADER( example_model_ps20b );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
		SET_DYNAMIC_PIXEL_SHADER( example_model_ps20b );

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
		pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
		pShader->SetAmbientCubeDynamicStateVertexShader();

		if( !bHasFlashlight )
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );
		}

		pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight );	// Force to black if not bAmbientLight
		pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY );

		// handle mat_fullbright 2 (diffuse lighting only)
		if( bLightingOnly )
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );
		}

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		if( bHasFlashlight )
		{
			VMatrix worldToTexture;
			float atten[4], pos[4], tweaks[4];

			const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture );
			SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR );

			pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );

			atten[0] = flashlightState.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZ;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 );

			pos[0] = flashlightState.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 );

			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 );

			// Tweaks associated with a given flashlight
			tweaks[0] = ShadowFilterFromState( flashlightState );
			tweaks[1] = ShadowAttenFromState( flashlightState );
			pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );
			vScreenScale[0] = (float) nWidth  / 32.0f;
			vScreenScale[1] = (float) nHeight / 32.0f;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );
		}
	}
	pShader->Draw();
}
void DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
					 IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL );
	bool bHasEnvmap = params[info.m_nEnvmap]->IsTexture();
	bool bRefractTintTexture = params[info.m_nRefractTintTexture]->IsTexture();
	bool bFadeOutOnSilhouette = params[info.m_nFadeOutOnSilhouette]->GetIntValue() != 0;
	int blurAmount = params[info.m_nBlurAmount]->GetIntValue();
	bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0);
	bool bSecondaryNormal = ( ( info.m_nNormalMap2 != -1 ) && ( params[info.m_nNormalMap2]->IsTexture() ) );
	bool bColorModulate = ( ( info.m_nVertexColorModulate != -1 ) && ( params[info.m_nVertexColorModulate]->GetIntValue() ) );
	bool bWriteZ = params[info.m_nNoWriteZ]->GetIntValue() == 0;

	if( blurAmount < 0 )
	{
		blurAmount = 0;
	}
	else if( blurAmount > MAXBLUR )
	{
		blurAmount = MAXBLUR;
	}

	BlendType_t nBlendType = pShader->EvaluateBlendRequirements( BASETEXTURE, true );
	bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use
	bFullyOpaque &= !bMasked;

	bool bTranslucentNormal = pShader->TextureIsTranslucent( info.m_nNormalMap, false );
	bFullyOpaque &= (! bTranslucentNormal );

	NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE;
	if ( g_pHardwareConfig->SupportsNormalMapCompression() )
	{
		ITexture *pBumpTex = params[info.m_nNormalMap]->GetTextureValue();
		if ( pBumpTex )
		{
			nNormalDecodeMode = pBumpTex->GetNormalDecodeMode();

			if ( bSecondaryNormal )			// Check encoding of secondary normal if there is one
			{
				ITexture *pBumpTex2 = params[info.m_nNormalMap2]->GetTextureValue();
				if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) )
				{
					DevMsg("Refract: Primary and Secondary normal map compression formats don't match.  This is unsupported!\n");
					Assert(0);
				}
			}
		}
	}

	SHADOW_STATE
	{
		pShader->SetInitialShadowState( );

		pShaderShadow->EnableDepthWrites( bWriteZ );

		// Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState
		pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) );

		// If envmap is not specified, the alpha channel is the translucency
		// (If envmap *is* specified, alpha channel is the reflection amount)
		if ( params[info.m_nNormalMap]->IsTexture() && !bHasEnvmap )
		{
			pShader->SetDefaultBlendingShadowState( info.m_nNormalMap, false );
		}

		// source render target that contains the image that we are warping.
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );

		// normal map
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
		if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Normal map alpha, in the compressed normal case
		}

		if ( bSecondaryNormal )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );

			if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Secondary normal map alpha, in the compressed normal case
			}
		}

		if( bHasEnvmap )
		{
			// envmap
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );
		}
		if( bRefractTintTexture )
		{
			// refract tint texture
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true );
		}

		pShaderShadow->EnableSRGBWrite( true );

		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
		int userDataSize = 0;
		int nTexCoordCount = 1;
		if( bIsModel )
		{
			userDataSize = 4;
		}
		else
		{
			flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T;
		}

		if ( bColorModulate )
		{
			flags |= VERTEX_COLOR;
		}
		
		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );
		
		DECLARE_STATIC_VERTEX_SHADER( jl_refract_vs20 );
		SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
		SET_STATIC_VERTEX_SHADER_COMBO( COLORMODULATE, bColorModulate );
		SET_STATIC_VERTEX_SHADER( jl_refract_vs20 );

		// We have to do this in the shader on R500 or Leopard
		bool bShaderSRGBConvert = IsOSX() && ( g_pHardwareConfig->FakeSRGBWrite() || !g_pHardwareConfig->CanDoSRGBReadFromRTs() );
		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send OpenGL down the ps2b path
		{
			DECLARE_STATIC_PIXEL_SHADER( jl_refract_ps20b );
			SET_STATIC_PIXEL_SHADER_COMBO( BLUR,  blurAmount );
			SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE,  bFadeOutOnSilhouette );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE,  bRefractTintTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked );
			SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate );
			SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode );
			SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSRGBConvert );
			SET_STATIC_PIXEL_SHADER( jl_refract_ps20b );
		}
		else
		{
			DECLARE_STATIC_PIXEL_SHADER( jl_refract_ps20 );
			SET_STATIC_PIXEL_SHADER_COMBO( BLUR,  blurAmount );
			SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE,  bFadeOutOnSilhouette );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP,  bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE,  bRefractTintTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked );
			SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate );
			SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal );
			SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode );
			SET_STATIC_PIXEL_SHADER( jl_refract_ps20 );
		}
		pShader->DefaultFog();
		if( bMasked )
		{
			pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA );
		}

		bool bAlphaWrites = bFullyOpaque || ( params[ info.m_nForceAlphaWrite ]->GetIntValue() != 0 );
		pShaderShadow->EnableAlphaWrites( bAlphaWrites );
	}
	DYNAMIC_STATE
	{
		pShaderAPI->SetDefaultState();

		if ( params[info.m_nBaseTexture]->IsTexture() )
		{
			pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture, info.m_nFrame );
		}
		else
		{
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 );
		}

		if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
		{
			pShader->BindTexture( SHADER_SAMPLER3, SHADER_SAMPLER6, info.m_nNormalMap, info.m_nBumpFrame );
		}
		else
		{
			pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame );
		}

		if ( bSecondaryNormal )
		{
			if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA )
			{
				pShader->BindTexture( SHADER_SAMPLER1, SHADER_SAMPLER7, info.m_nNormalMap2, info.m_nBumpFrame2 );
			}
			else
			{
				pShader->BindTexture( SHADER_SAMPLER1, info.m_nNormalMap2, info.m_nBumpFrame2 );
			}
		}

		if( bHasEnvmap )
		{
			pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmap, info.m_nEnvmapFrame );
		}

		if( bRefractTintTexture )
		{
			pShader->BindTexture( SHADER_SAMPLER5, info.m_nRefractTintTexture, info.m_nRefractTintTextureFrame );
		}

		DECLARE_DYNAMIC_VERTEX_SHADER( jl_refract_vs20 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,  pShaderAPI->GetCurrentNumBones() > 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
		SET_DYNAMIC_VERTEX_SHADER( jl_refract_vs20 );

		if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send Posix down the ps2b path
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( jl_refract_ps20b );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
			SET_DYNAMIC_PIXEL_SHADER( jl_refract_ps20b );
		}
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( jl_refract_ps20 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER( jl_refract_ps20 );
		}

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform );	// 1 & 2
		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nBumpTransform2 );	// 3 & 4

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		float vEyePos_SpecExponent[4];
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );
		vEyePos_SpecExponent[3] = 0.0f;
		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );

		pShader->SetPixelShaderConstantGammaToLinear( 0, info.m_nEnvmapTint );
		pShader->SetPixelShaderConstantGammaToLinear( 1, info.m_nRefractTint );
		pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast );
		pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation );
		float c5[4] = { params[info.m_nRefractAmount]->GetFloatValue(), 
			params[info.m_nRefractAmount]->GetFloatValue(), 0.0f, 0.0f };

		// Time % 1000
		c5[3] = pShaderAPI->CurrentTime();
		c5[3] -= (float)( (int)( c5[3] / 1000.0f ) ) * 1000.0f;
		pShaderAPI->SetPixelShaderConstant( 5, c5, 1 );

		float cVs3[4] = { c5[3], 0.0f, 0.0f, 0.0f };
		pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, cVs3, 1 );
	}
	pShader->Draw();
}
示例#18
0
void DrawPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
	                         VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr, bool bDeferredActive )
{
	CPhong_DX9_Context *pContextData = reinterpret_cast< CPhong_DX9_Context *> ( *pContextDataPtr );

	bool bHasFlashlight = !bDeferredActive && pShader->UsingFlashlight( params );
	bool bHasFlashlightOnly = bHasFlashlight && !IsX360();
#ifndef _X360
	bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL );
#endif
	bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
	BlendType_t nBlendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
	bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlightOnly; //dest alpha is free for special use
	bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture();
#if !defined( PLATFORM_X360 )
	bool bHasDisplacementWrinkles = (info.m_nDisplacementWrinkleMap != -1) && params[info.m_nDisplacementWrinkleMap]->GetIntValue();
#endif

	bool bHasTeamColorTexture = ( info.m_nTeamColorTexture != -1 ) && params[info.m_nTeamColorTexture]->IsTexture();

	bool bHasFoW = ( ( info.m_nFoW != -1 ) && ( params[ info.m_nFoW ]->IsTexture() != 0 ) );
	bool bFOWValidTexture = true;
	if ( bHasFoW == true )
	{
		ITexture *pTexture = params[ info.m_nFoW ]->GetTextureValue();
		if ( ( pTexture->GetFlags() & TEXTUREFLAGS_RENDERTARGET ) == 0 )
		{
			bHasFoW = true;
			bFOWValidTexture = false;
		}
	}
	else
	{
		bHasFoW = true;
		bFOWValidTexture = false;
	}

	if( pShader->IsSnapshotting() )
	{
		PhongShaderInfo_t phongInfo;
		ComputePhongShaderInfo( pShader, params, info, bHasFlashlightOnly, &phongInfo );

		bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && params[info.m_nShaderSrgbRead360]->GetIntValue() );
		int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue();
		bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
		bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA );

		// look at color and alphamod stuff.
		// Unlit generic never uses the flashlight
		bool bHasEnvmap = !bHasFlashlightOnly && params[info.m_nEnvmap]->IsTexture();

		// Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState
		pShaderShadow->EnableAlphaTest( bIsAlphaTested );

		if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
		{
			pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
		}

		// Based upon vendor and device dependent formats
		int nShadowFilterMode = bHasFlashlight ? g_pHardwareConfig->GetShadowFilterMode() : 0;
		if( bHasFlashlightOnly )
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
			}

			if( bIsAlphaTested )
			{
				// disable alpha test and use the zfunc zequals since alpha isn't guaranteed to 
				// be the same on both the regular pass and the flashlight pass.
				pShaderShadow->EnableAlphaTest( false );
				pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
			}
			pShaderShadow->EnableBlending( true );
			pShaderShadow->EnableDepthWrites( false );

			// Be sure not to write to dest alpha
			pShaderShadow->EnableAlphaWrites( false );
		}

		if ( !bHasFlashlightOnly ) // not flashlight pass
		{
			if (params[info.m_nBaseTexture]->IsTexture())
			{
				pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
			}

			if ( bHasEnvmap )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );	// Cubic environment map
				if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
				{
					pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, true );
				}
			}
		}
		
		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
		int userDataSize = 0;

		// Always enable...will bind white if nothing specified...
		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );		// Base (albedo) map
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead );

		if ( !bHasFoW && !bDeferredActive && (phongInfo.m_bHasBaseTextureWrinkle) )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );	// Base (albedo) compression map
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, !bShaderSrgbRead );

			pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );	// Base (albedo) stretch map
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, !bShaderSrgbRead );
		}

		if( phongInfo.m_bHasDiffuseWarp )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );	// Diffuse warp texture
		}

		if( phongInfo.m_bHasPhongWarp )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );	// Specular warp texture
		}

		// Specular exponent map or dummy
		pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Specular exponent map

		if( bHasFlashlight )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );	// Shadow depth map
			pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );	// Noise map
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Flashlight cookie
		}

		// Always enable, since flat normal will be bound
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );		// Normal map
		userDataSize = 4; // tangent S
		pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );		// Normalizing cube map

		if ( !bHasFoW && !bDeferredActive && (phongInfo.m_bHasBumpWrinkle || phongInfo.m_bHasBaseTextureWrinkle) )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER11, true );	// Normal compression map
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER11, false );

			pShaderShadow->EnableTexture( SHADER_SAMPLER12, true );	// Normal stretch map
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, false );
		}

		if( bHasFoW )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );
		}

		if( bDeferredActive )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );
			pShaderShadow->EnableTexture( SHADER_SAMPLER11, true );
		}

		if ( phongInfo.m_bHasDetailTexture )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
			if ( nDetailBlendMode != 0 ) //Not Mod2X
			{
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER13, true );
			}
		}

		if ( phongInfo.m_bHasSelfIllum )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
		}

		if( bHasVertexColor || bHasVertexAlpha )
		{
			flags |= VERTEX_COLOR;
		}

		// Always enable ambient occlusion sampler on PC on DX10 parts
		if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
		}

		if( bHasTeamColorTexture )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER12, true );
		}

		if ( bHasDisplacement && IsPC() && g_pHardwareConfig->HasFastVertexTextures() )
		{
			pShaderShadow->EnableVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, true );
		}

		pShaderShadow->EnableSRGBWrite( true );
		
		// texcoord0 : base texcoord, texcoord2 : decal hw morph delta
		int pTexCoordDim[3] = { 2, 0, 3 };
		int nTexCoordCount = 1;

#ifndef _X360
		// Special morphed decal information 
		if ( bIsDecal && g_pHardwareConfig->HasFastVertexTextures() )
		{
			nTexCoordCount = 3;
		}
#endif

		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize );

#if !defined( PLATFORM_X360 )
		bool bWorldNormal = ( ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH == ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 )));
#endif

		// This is to allow phong materials to disable half lambert. Half lambert has always been forced on in phong,
		// so the only safe way to allow artists to disable half lambert is to create this param that disables the
		// default behavior of forcing half lambert on.
		bool bPhongHalfLambert = IS_PARAM_DEFINED( info.m_nPhongDisableHalfLambert ) ? ( params[ info.m_nPhongDisableHalfLambert ]->GetIntValue() == 0 ) : true;

		if ( g_pHardwareConfig->HasFastVertexTextures() )
		{
			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );
			SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION );
		}

		DECLARE_STATIC_VERTEX_SHADER( phong_vs30 );
		SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
		SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal );
		SET_STATIC_VERTEX_SHADER_COMBO( FOW, bHasFoW );
		SET_STATIC_VERTEX_SHADER( phong_vs30 );

		if( bDeferredActive ) 
		{
			DECLARE_STATIC_PIXEL_SHADER( phong_deferred_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL,  phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong );
			SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, phongInfo.m_bHasPhongWarp && phongInfo.m_bHasPhong );
			//SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, !bHasFoW && phongInfo.m_bHasBaseTextureWrinkle );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, phongInfo.m_bHasDetailTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, phongInfo.m_bHasRimLight );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
			SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
			SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert );
			SET_STATIC_PIXEL_SHADER_COMBO( TEAMCOLORTEXTURE,  bHasTeamColorTexture );
			//SET_STATIC_PIXEL_SHADER_COMBO( FOW, /*bHasFoW*/ 1 );
			SET_STATIC_PIXEL_SHADER( phong_deferred_ps30 );
		}
		else
		{
			DECLARE_STATIC_PIXEL_SHADER( phong_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly );
			SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL,  phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong );
			SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, phongInfo.m_bHasPhongWarp && phongInfo.m_bHasPhong );
			//SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, !bHasFoW && phongInfo.m_bHasBaseTextureWrinkle );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, phongInfo.m_bHasDetailTexture );
			SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
			SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, phongInfo.m_bHasRimLight );
			SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
			SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
			SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert );
			SET_STATIC_PIXEL_SHADER_COMBO( TEAMCOLORTEXTURE,  bHasTeamColorTexture );
			//SET_STATIC_PIXEL_SHADER_COMBO( FOW, /*bHasFoW*/ 1 );
			SET_STATIC_PIXEL_SHADER( phong_ps30 );
		}

		if( bHasFlashlightOnly )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->DefaultFog();
		}

		// HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff
		pShaderShadow->EnableAlphaWrites( bFullyOpaque );

		pShader->PI_BeginCommandBuffer();
		pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE );
		pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY );
		pShader->PI_SetVertexShaderAmbientLightCube();
		// material can opt out of per-instance modulation via $nodiffusemodulation
		bool bAllowDiffuseModulation = ( info.m_nAllowDiffuseModulation == -1 ) ? true : ( params[info.m_nAllowDiffuseModulation]->GetIntValue() != 0 );
		if ( bAllowDiffuseModulation )
		{
			pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
		}
		else
		{
			pShader->PI_SetModulationPixelShaderDynamicState_Identity( 1 );
		}
		pShader->PI_EndCommandBuffer();
	}
	else // not snapshotting -- begin dynamic state
	{
		// Deal with semisatic
		if ( ( !pContextData ) || ( pContextData->m_bMaterialVarsChanged ) )
		{
			if ( !pContextData )								// make sure allocated
			{
				pContextData = new CPhong_DX9_Context;
				*pContextDataPtr = pContextData;
			}

			pContextData->m_SemiStaticCmdsOut.Reset();
			pContextData->m_bMaterialVarsChanged = false;

			PhongShaderInfo_t phongInfo;
			ComputePhongShaderInfo( pShader, params, info, bHasFlashlightOnly, &phongInfo );

			bool bHasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture();
			bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
			bool bHasSelfIllumMask = ( phongInfo.m_bHasSelfIllum ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsTexture();
			float fBlendFactor = ( info.m_nDetailTextureBlendFactor == -1 )? 1 : params[info.m_nDetailTextureBlendFactor]->GetFloatValue();
			bool bHasSpecularExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture();
			bool bHasPhongTintMap = bHasSpecularExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 );
			bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );
			bool bHasRimMaskMap = bHasSpecularExponentTexture && phongInfo.m_bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 );
			bool bHasSinglePassFlashlight = IsX360(); // NOTE: If you change this, fix state.m_nDepthTweakConstant below! And, deal with SINGLE_PASS_FLASHLIGHT in phong_ps20b.fxc

			if( phongInfo.m_bHasBaseTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
			}
			else
			{
				pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
			}

			if ( !bHasFoW && !bDeferredActive && phongInfo.m_bHasBaseTextureWrinkle )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, info.m_nWrinkle, info.m_nBaseTextureFrame );
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER10, info.m_nStretch, info.m_nBaseTextureFrame );
			}

			if( phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong )
			{
				if ( r_lightwarpidentity.GetBool() )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_IDENTITY_LIGHTWARP );
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, info.m_nDiffuseWarpTexture );
				}
			}

			if( phongInfo.m_bHasPhongWarp )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nPhongWarpTexture );
			}

			if( bHasSpecularExponentTexture && phongInfo.m_bHasPhong )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, info.m_nPhongExponentTexture );
			}
			else
			{
				pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE );
			}

			if( !g_pConfig->m_bFastNoBump )
			{
				if( bHasBump )
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nBumpmap, info.m_nBumpFrame );
				else
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT );

				if ( !bHasFoW && !bDeferredActive && phongInfo.m_bHasBumpWrinkle )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nNormalWrinkle, info.m_nBumpFrame );
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nNormalStretch, info.m_nBumpFrame );
				}
				else if ( !bHasFoW && !bDeferredActive && phongInfo.m_bHasBaseTextureWrinkle )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nBumpmap, info.m_nBumpFrame );
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nBumpmap, info.m_nBumpFrame );
				}
			}
			else // Just flat bump maps
			{
				if ( bHasBump )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALMAP_FLAT );
				}

				if ( !bHasFoW && !bDeferredActive && phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, TEXTURE_NORMALMAP_FLAT );
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, TEXTURE_NORMALMAP_FLAT );
				}
			}

			if ( phongInfo.m_bHasDetailTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER13, info.m_nDetail, info.m_nDetailFrame );
			}

			if ( phongInfo.m_bHasSelfIllum )
			{
				if ( bHasSelfIllumMask )												// Separate texture for self illum?
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER14, info.m_nSelfIllumMask );	// Bind it
				}
				else																	// else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER14, TEXTURE_BLACK );	// Bind dummy
				}
			}

			if( !bHasFlashlightOnly )
			{
				if ( phongInfo.m_bHasEnvmap )
				{
					pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER8, info.m_nEnvmap, info.m_nEnvmapFrame );
				}
			}
			
			pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );

			if( bHasBump )
			{
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
			}

			if ( phongInfo.m_bHasDetailTexture )
			{
				if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) )
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4,
						info.m_nDetailTextureTransform, 
						info.m_nDetailScale );
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4,
						info.m_nBaseTextureTransform, 
						info.m_nDetailScale );
				}
			}

			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, fBlendFactor );
			bool bInvertPhongMask = ( info.m_nInvertPhongMask != -1 ) && ( params[info.m_nInvertPhongMask]->GetIntValue() != 0 );
			float fInvertPhongMask = bInvertPhongMask ? 1 : 0;

			bool bHasBaseAlphaPhongMask = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 );
			float fHasBaseAlphaPhongMask = bHasBaseAlphaPhongMask ? 1 : 0;
			bool bBlendTintByBaseAlpha = (info.m_nBlendTintByBaseAlpha != -1) && ( params[info.m_nBlendTintByBaseAlpha]->GetIntValue() != 0 );
			float fBlendTintByBaseAlpha = bBlendTintByBaseAlpha ? 1 : 0;
			
			// Controls for lerp-style paths through shader code
			float vShaderControls[4] = { fHasBaseAlphaPhongMask, 0.0f, 1.0f-fBlendTintByBaseAlpha, fInvertPhongMask };
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SHADER_CONTROLS, vShaderControls, 1 );

			if ( phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly )
			{
				float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f };
				float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f;
				float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f;
				float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f;

				vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias
				vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale
				vConstScaleBiasExp[2] = flExp; // Exp
				vConstScaleBiasExp[3] = flMax; // Brightness

				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SELFILLUM_SCALE_BIAS_EXP, vConstScaleBiasExp, 1 );
			}

			if( !bHasFlashlightOnly )
			{
				pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );

				if( phongInfo.m_bHasEnvmap )
				{
					float vEnvMapTint_MaskControl[4] = {1.0f, 1.0f, 1.0f, 0.0f};

					// If we have a tint, grab it
					if ( (info.m_nEnvmapTint != -1) && params[info.m_nEnvmapTint]->IsDefined() )
						params[info.m_nEnvmapTint]->GetVecValue(vEnvMapTint_MaskControl, 3);

					// Set control for source of env map mask (normal alpha or base alpha)
					vEnvMapTint_MaskControl[3] = bHasNormalMapAlphaEnvmapMask ? 1.0f : 0.0f;

					// Handle mat_fullbright 2 (diffuse lighting only with 50% gamma space basetexture)
					if( bLightingOnly )
					{
						vEnvMapTint_MaskControl[0] = vEnvMapTint_MaskControl[1] = vEnvMapTint_MaskControl[2] = 0.0f;
					}

					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, vEnvMapTint_MaskControl, 1 );
				}
			}

			// Pack Phong exponent in with the eye position
			float vSpecularTint[4] = {1, 1, 1, 4};
			float vFresnelRanges_SpecBoost[4] = {0, 0.5, 1, 1}, vRimBoost[4] = {1, 1, 1, 1};

			// Get the tint parameter
			if ( (info.m_nPhongTint != -1) && params[info.m_nPhongTint]->IsDefined() )
			{
				params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 3);
			}

			// Get the rim light power (goes in w of Phong tint)
			if ( phongInfo.m_bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() )
			{
				vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue();
				vSpecularTint[3] = MAX(vSpecularTint[3], 1.0f);	// Make sure this is at least 1
			}

			// Get the rim boost (goes in w of flashlight position)
			if ( phongInfo.m_bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() )
			{
				vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue();
			}

			// Single pass flashlight has to use a separate constant for this stuff since a flashlight constant is repurposed for rimlighting when doing multi-pass flashlight.
			if ( phongInfo.m_bHasRimLight )
			{
				if ( bHasSinglePassFlashlight )
				{
					float vRimParams[4] = {0, 0, 0, 0};
					vRimParams[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f;
					vRimParams[1] = params[info.m_nRimLightBoost]->GetFloatValue();

					// Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_RIMPARAMS, vRimParams, 1 );
				}
				else if ( !bHasFlashlight )
				{
					float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code
					vRimMaskControl[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f;

					// Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 );
				}
			}

			// If it's all zeros, there was no constant tint in the vmt
			if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) )
			{
				if ( bHasPhongTintMap )				// If we have a map to use, tell the shader
				{
					vSpecularTint[0] = -1;
				}
				else								// Otherwise, just tint with white
				{
					vSpecularTint[0] = 1.0f;
					vSpecularTint[1] = 1.0f;
					vSpecularTint[2] = 1.0f;
				}
			}

			// handle mat_fullbright 2 (diffuse lighting only)
			if( bLightingOnly )
			{
				// BASETEXTURE
				if( phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY_ALPHA_ZERO );

					if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle )
					{
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_GREY_ALPHA_ZERO );	// Compressed wrinklemap
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_GREY_ALPHA_ZERO );	// Stretched wrinklemap
					}
				}
				else
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );

					if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle )
					{
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_GREY );		// Compressed wrinklemap
						pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_GREY );	// Stretched wrinklemap
					}
				}

				// DETAILTEXTURE
				if ( phongInfo.m_bHasDetailTexture )
				{
					pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER13, TEXTURE_GREY );
				}

				// turn off specularity
				vSpecularTint[0] = vSpecularTint[1] = vSpecularTint[2] = 0.0f;
			}

			if ( (info.m_nPhongFresnelRanges != -1) && params[info.m_nPhongFresnelRanges]->IsDefined() )
			{
				params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 );	// Grab optional Fresnel range parameters
			}

			if ( (info.m_nPhongBoost != -1 ) && params[info.m_nPhongBoost]->IsDefined())		// Grab optional Phong boost param
			{
				vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue();
			}
			else
			{
				vFresnelRanges_SpecBoost[3] = 1.0f;
			}

			bool bHasBaseLuminancePhongMask = (info.m_nBaseMapLuminancePhongMask != -1) && ( params[info.m_nBaseMapLuminancePhongMask]->GetIntValue() != 0 );
			float fHasBaseLuminancePhongMask = bHasBaseLuminancePhongMask ? 1 : 0;
			float vShaderControls2[4] = {0.0f, fHasBaseLuminancePhongMask, 0.0f, 0.0f};
			if ( !bHasFlashlightOnly )
			{
				if ( phongInfo.m_bHasEnvmap ) 
				{
					if ( (info.m_nEnvmapFresnel != -1) && params[info.m_nEnvmapFresnel]->IsDefined() )
					{
						vShaderControls2[0] = params[info.m_nEnvmapFresnel]->GetFloatValue();
					}
				}
			}
			if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() )
			{
				vShaderControls2[2] = params[info.m_nPhongExponent]->GetFloatValue();		// This overrides the channel in the map
			}
			else
			{
				vShaderControls2[2] = 0;													// Use the alpha channel of the normal map for the exponent
			}

			vShaderControls2[3] = bHasSelfIllumMask ? 1.0f : 0.0f;

			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 );
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 );	// Rim boost in w on non-flashlight pass
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 );
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SHADER_CONTROLS_2, vShaderControls2, 1 );

			pContextData->m_SemiStaticCmdsOut.SetPixelShaderFogParams( PSREG_FOG_PARAMS );

			if ( bHasFlashlight )
			{
				CBCmdSetPixelShaderFlashlightState_t state;
				state.m_LightSampler = SHADER_SAMPLER6;
				state.m_DepthSampler = SHADER_SAMPLER4;
				state.m_ShadowNoiseSampler = SHADER_SAMPLER5;
				state.m_nColorConstant = PSREG_FLASHLIGHT_COLOR;
				state.m_nAttenConstant = PSREG_FLASHLIGHT_ATTENUATION;
				state.m_nOriginConstant = PSREG_FLASHLIGHT_POSITION_RIM_BOOST;
				state.m_nDepthTweakConstant = bHasSinglePassFlashlight ? 43 : PSREG_ENVMAP_TINT__SHADOW_TWEAKS; // NOTE: Reg 43 not available on < ps3.0!
				state.m_nScreenScaleConstant = PSREG_FLASHLIGHT_SCREEN_SCALE;
				state.m_nWorldToTextureConstant = PSREG_FLASHLIGHT_TO_WORLD_TEXTURE;
				state.m_bFlashlightNoLambert = false;
				state.m_bSinglePassFlashlight = bHasSinglePassFlashlight;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state );

				if ( !IsX360() && ( g_pHardwareConfig->GetDXSupportLevel() > 92 ) )
				{
					pContextData->m_SemiStaticCmdsOut.SetPixelShaderUberLightState( 
						PSREG_UBERLIGHT_SMOOTH_EDGE_0,		PSREG_UBERLIGHT_SMOOTH_EDGE_1,
						PSREG_UBERLIGHT_SMOOTH_EDGE_OOW,	PSREG_UBERLIGHT_SHEAR_ROUND, 
						PSREG_UBERLIGHT_AABB,				PSREG_UBERLIGHT_WORLD_TO_LIGHT );
				}
			}

			// Team color constant + sampler
			if( bHasTeamColorTexture )
			{
				static const float kDefaultTeamColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
				const float *vecTeamColor = IS_PARAM_DEFINED( info.m_nTeamColor ) ? params[info.m_nTeamColor]->GetVecValue() : kDefaultTeamColor;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_RIMPARAMS, vecTeamColor, 1 );
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nTeamColorTexture, -1 );
			}

			pContextData->m_SemiStaticCmdsOut.End();
		}

		CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut;
		DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() );

		// On PC, we sample from ambient occlusion texture
		if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() )
		{
			ITexture *pAOTexture = pShaderAPI->GetTextureRenderingParameter( TEXTURE_RENDERPARM_AMBIENT_OCCLUSION );

			if ( pAOTexture )
			{
				DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER15, pAOTexture, 0 );
			}
			else
			{
				DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER15, TEXTURE_WHITE );
			}
		}

		bool bFlashlightShadows = false;
		bool bUberlight = false;
		float flAmbientOcclusionStrength = ( info.m_nAmbientOcclusion == -1 ) ? 0.0f : params[info.m_nAmbientOcclusion]->GetFloatValue();
		if ( bHasFlashlight )
		{
			pShaderAPI->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight );
			flAmbientOcclusionStrength *= pShaderAPI->GetFlashlightAmbientOcclusion();
		}

		float vEyePos_AmbientOcclusion[4];
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_AmbientOcclusion );
		vEyePos_AmbientOcclusion[3] = clamp( flAmbientOcclusionStrength, 0.0f, 1.0f );
		DynamicCmdsOut.SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_AmbientOcclusion, 1 );

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
		int numBones = pShaderAPI->GetCurrentNumBones();

		bool bWriteDepthToAlpha = false;
		bool bWriteWaterFogToAlpha = false;

		if( bFullyOpaque ) 
		{
			bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
			bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
			AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
		}

		LightState_t lightState = { 0, false, false };
		if( !bHasFlashlightOnly )
		{
			pShaderAPI->GetDX9LightState( &lightState );
		}

		if ( bHasFoW )
		{
			if( bFOWValidTexture )
				pShader->BindTexture( SHADER_SAMPLER9, info.m_nFoW, -1 );
			else
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER9, TEXTURE_WHITE );

			float	vFoWSize[ 4 ];
			Vector	vMins = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MINS );
			Vector	vMaxs = pShaderAPI->GetVectorRenderingParameter( VECTOR_RENDERPARM_GLOBAL_FOW_MAXS );
			vFoWSize[ 0 ] = vMins.x;
			vFoWSize[ 1 ] = vMins.y;
			vFoWSize[ 2 ] = vMaxs.x - vMins.x;
			vFoWSize[ 3 ] = vMaxs.y - vMins.y;
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, vFoWSize );
		}

		if( bDeferredActive )
		{
			pShader->BindTexture( SHADER_SAMPLER10, GetDeferredExt()->GetTexture_LightAccum() );
			pShader->BindTexture( SHADER_SAMPLER11, GetDeferredExt()->GetTexture_LightAccum2() );

			int x, y, w, t;
			pShaderAPI->GetCurrentViewport( x, y, w, t );
			float fl1[4] = { 1.0f / w, 1.0f / t, 0, 0 };

			pShaderAPI->SetPixelShaderConstant( PSREG_UBERLIGHT_SMOOTH_EDGE_0, fl1 );
		}

		pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );

		int nLightingPreviewMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );
		if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() )
		{
			float vEyeDir[4];
			pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir );

			float flFarZ = pShaderAPI->GetFarZ();
			vEyeDir[0] /= flFarZ;	// Divide by farZ for SSAO algorithm
			vEyeDir[1] /= flFarZ;
			vEyeDir[2] /= flFarZ;
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vEyeDir );
		}

		TessellationMode_t nTessellationMode = pShaderAPI->GetTessellationMode();
		if ( nTessellationMode != TESSELLATION_MODE_DISABLED && g_pHardwareConfig->HasFastVertexTextures() )
		{
			pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES );

			float vSubDDimensions[4] = { 1.0f/pShaderAPI->GetSubDHeight(),
											bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f,
											bHasDisplacementWrinkles && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f };

			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, vSubDDimensions );
			if( bHasDisplacement )
			{
				pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap );
			}
			else
			{
				pShaderAPI->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, TEXTURE_BLACK );
			}

			// Currently, tessellation is mutually exclusive with any kind of GPU-side skinning, morphing or vertex compression
			Assert( !pShaderAPI->IsHWMorphingEnabled() );
			Assert( numBones == 0 );
			Assert( vertexCompression == 0);
		}
		else
		{
			nTessellationMode = TESSELLATION_MODE_DISABLED;
		}

		DECLARE_DYNAMIC_VERTEX_SHADER( phong_vs30 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0) && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode );
		SET_DYNAMIC_VERTEX_SHADER( phong_vs30 );

		if( bDeferredActive ) 
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( phong_deferred_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nLightingPreviewMode ? 0 : lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, nLightingPreviewMode ? false : bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, nLightingPreviewMode ? false : bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight );
			SET_DYNAMIC_PIXEL_SHADER( phong_deferred_ps30 );
		}
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( phong_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nLightingPreviewMode ? 0 : lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, nLightingPreviewMode ? false : bWriteWaterFogToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, nLightingPreviewMode ? false : bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight );
			SET_DYNAMIC_PIXEL_SHADER( phong_ps30 );
		}

		bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal };
		pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords );

		// Set constant to enable translation of VPOS to render target coordinates in ps_3_0
		pShaderAPI->SetScreenSizeForVPOS();

		DynamicCmdsOut.End();
		pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() );
	}
	pShader->Draw();
}
示例#19
0
void DrawPassShadowPass( const defParms_shadow &info, CBaseVSShader *pShader, IMaterialVar **params,
	IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI,
	VertexCompressionType_t vertexCompression, CDeferredPerMaterialContextData *pDeferredContext )
{
	const bool bModel = info.bModel;
	const bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL );
	const bool bFastVTex = g_pHardwareConfig->HasFastVertexTextures();
	const bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL );

	const bool bAlbedo = PARM_TEX( info.iAlbedo );
	const bool bAlbedo2 = PARM_TEX( info.iAlbedo2 );
	const bool bAlbedo3 = PARM_TEX( info.iAlbedo3 );
	const bool bAlbedo4 = PARM_TEX( info.iAlbedo4 );
	const bool bAlphatest = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) && bAlbedo;

	const bool bMultiBlend = PARM_SET( info.iMultiblend ) && bAlbedo && bAlbedo2 && bAlbedo3;
	const bool bBaseTexture2 = !bMultiBlend && bAlbedo2;

	SHADOW_STATE
	{
		pShaderShadow->SetDefaultState();

		pShaderShadow->EnableSRGBWrite( false );

		if ( bNoCull )
		{
			pShaderShadow->EnableCulling( false );
		}

		int iVFmtFlags = VERTEX_POSITION | VERTEX_NORMAL;
		int iUserDataSize = 0;

		int *pTexCoordDim;
		int iTexCoordNum;
		GetTexcoordSettings( ( bModel && bIsDecal && bFastVTex ), bMultiBlend,
			iTexCoordNum, &pTexCoordDim );

		if ( bModel )
		{
			iVFmtFlags |= VERTEX_FORMAT_COMPRESSED;
		}

#ifndef DEFCFG_ENABLE_RADIOSITY
		if ( bAlphatest )
#endif
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );

			if ( bBaseTexture2 || bMultiBlend )
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );

			if ( bMultiBlend )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
				pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
			}
		}

		pShaderShadow->VertexShaderVertexFormat( iVFmtFlags, iTexCoordNum, pTexCoordDim, iUserDataSize );

		DECLARE_STATIC_VERTEX_SHADER( shadowpass_vs30 );
		SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bModel );
		SET_STATIC_VERTEX_SHADER_COMBO( MORPHING_VTEX, bModel && bFastVTex );
		SET_STATIC_VERTEX_SHADER_COMBO( MULTITEXTURE, bMultiBlend ? 2 : bBaseTexture2 ? 1 : 0 );
		SET_STATIC_VERTEX_SHADER( shadowpass_vs30 );

		DECLARE_STATIC_PIXEL_SHADER( shadowpass_ps30 );
		SET_STATIC_PIXEL_SHADER_COMBO( ALPHATEST, bAlphatest );
		SET_STATIC_PIXEL_SHADER_COMBO( MULTITEXTURE, bMultiBlend ? 2 : bBaseTexture2 ? 1 : 0 );
		SET_STATIC_PIXEL_SHADER( shadowpass_ps30 );
	}
	DYNAMIC_STATE
	{
		Assert( pDeferredContext != NULL );
		const int shadowMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_DEFERRED_SHADOW_MODE );
		const int radiosityOutput = DEFCFG_ENABLE_RADIOSITY != 0
			&& pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_DEFERRED_SHADOW_RADIOSITY );

		if ( pDeferredContext->m_bMaterialVarsChanged || !pDeferredContext->HasCommands( CDeferredPerMaterialContextData::DEFSTAGE_SHADOW ) )
		{
			tmpBuf.Reset();

			if ( bAlphatest )
			{
				PARM_VALIDATE( info.iAlphatestRef );

				tmpBuf.SetPixelShaderConstant1( 0, PARM_FLOAT( info.iAlphatestRef ) );
#ifndef DEFCFG_ENABLE_RADIOSITY
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER0, info.iAlbedo );
#endif
			}

#if DEFCFG_ENABLE_RADIOSITY
			if ( bAlbedo )
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER0, info.iAlbedo );
			else
				tmpBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );

			if ( bBaseTexture2 || bMultiBlend )
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER1, info.iAlbedo2 );

			if ( bMultiBlend )
			{
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER2, info.iAlbedo3 );

				if ( bAlbedo4 )
					tmpBuf.BindTexture( pShader, SHADER_SAMPLER3, info.iAlbedo4 );
				else
					tmpBuf.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_WHITE );
			}
#endif

			tmpBuf.End();

			pDeferredContext->SetCommands( CDeferredPerMaterialContextData::DEFSTAGE_SHADOW, tmpBuf.Copy() );
		}

		pShaderAPI->SetDefaultState();

		if ( bModel && bFastVTex )
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 );

		DECLARE_DYNAMIC_VERTEX_SHADER( shadowpass_vs30 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (bModel && (int)vertexCompression) ? 1 : 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, (bModel && pShaderAPI->GetCurrentNumBones() > 0) ? 1 : 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, (bModel && pShaderAPI->IsHWMorphingEnabled()) ? 1 : 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SHADOW_MODE, shadowMode );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( RADIOSITY, radiosityOutput );
		SET_DYNAMIC_VERTEX_SHADER( shadowpass_vs30 );

		DECLARE_DYNAMIC_PIXEL_SHADER( shadowpass_ps30 );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( SHADOW_MODE, shadowMode );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( RADIOSITY, radiosityOutput );
		SET_DYNAMIC_PIXEL_SHADER( shadowpass_ps30 );

		if ( bModel && bFastVTex )
		{
			bool bUnusedTexCoords[3] = { false, true, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal };
			pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords );
		}

		pShaderAPI->ExecuteCommandBuffer( pDeferredContext->GetCommands( CDeferredPerMaterialContextData::DEFSTAGE_SHADOW ) );

		switch ( shadowMode )
		{
		case DEFERRED_SHADOW_MODE_ORTHO:
			{
				CommitShadowcastingConstants_Ortho( pShaderAPI,
					pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_DEFERRED_SHADOW_INDEX ),
					VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, VERTEX_SHADER_SHADER_SPECIFIC_CONST_1,
					VERTEX_SHADER_SHADER_SPECIFIC_CONST_2
					);
			}
			break;
		case DEFERRED_SHADOW_MODE_PROJECTED:
			{
				CommitShadowcastingConstants_Proj( pShaderAPI,
					pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_DEFERRED_SHADOW_INDEX ),
					VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, VERTEX_SHADER_SHADER_SPECIFIC_CONST_1,
					VERTEX_SHADER_SHADER_SPECIFIC_CONST_2
					);
			}
			break;
		}

#ifdef SHADOWMAPPING_USE_COLOR
		CommitViewVertexShader( pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7 );
#endif
	}

	pShader->Draw();
}
void Draw_Eyes_Refract_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
	IShaderShadow* pShaderShadow, bool bDrawFlashlightAdditivePass, Eye_Refract_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	bool bDiffuseWarp = IS_PARAM_DEFINED( info.m_nDiffuseWarpTexture );
	bool bIntro = IS_PARAM_DEFINED( info.m_nIntro ) ? ( params[info.m_nIntro]->GetIntValue() ? true : false ) : false;

	SHADOW_STATE
	{
		SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT );

		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );	// Cornea normal
		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );	// Iris
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );	// Cube reflection
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );	// Ambient occlusion

		// Set stream format (note that this shader supports compression)
		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED;
		int nTexCoordCount = 1;
		int userDataSize = 0;
		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

		if ( bDiffuseWarp )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );	// Light warp
		}

		int nShadowFilterMode = 0;
		if ( bDrawFlashlightAdditivePass == true )
		{
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
			}

			pShaderShadow->EnableDepthWrites( false );
			pShader->EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE ); // Write over the eyes that were already there 
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );	// Flashlight cookie
		}

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_STATIC_VERTEX_SHADER( sdk_eye_refract_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) );
			SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER( sdk_eye_refract_vs20 );

			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false );
				bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false );

				DECLARE_STATIC_PIXEL_SHADER( sdk_eye_refract_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
				SET_STATIC_PIXEL_SHADER( sdk_eye_refract_ps20b );

				if ( bDrawFlashlightAdditivePass == true )
				{
					pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Shadow depth map
					pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER6 );
					pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Noise map
				}
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( sdk_eye_refract_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
				SET_STATIC_PIXEL_SHADER( sdk_eye_refract_ps20 );
			}
		}
#ifndef _X360
		else
		{
			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

			DECLARE_STATIC_VERTEX_SHADER( sdk_eye_refract_vs30 );
			SET_STATIC_VERTEX_SHADER_COMBO( HALFLAMBERT, IS_FLAG_SET( MATERIAL_VAR_HALFLAMBERT ) );
			SET_STATIC_VERTEX_SHADER_COMBO( INTRO, bIntro ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
			SET_STATIC_VERTEX_SHADER( sdk_eye_refract_vs30 );

			bool bSphereTexKillCombo = IS_PARAM_DEFINED( info.m_nSphereTexKillCombo ) ? ( params[info.m_nSphereTexKillCombo]->GetIntValue() ? true : false ) : ( kDefaultSphereTexKillCombo ? true : false );
			bool bRayTraceSphere = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? ( params[info.m_nRaytraceSphere]->GetIntValue() ? true : false ) : ( kDefaultRaytraceSphere ? true : false );

			DECLARE_STATIC_PIXEL_SHADER( sdk_eye_refract_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( SPHERETEXKILLCOMBO, bSphereTexKillCombo ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( RAYTRACESPHERE, bRayTraceSphere ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bDrawFlashlightAdditivePass ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, bDiffuseWarp ? 1 : 0 );
			SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
			SET_STATIC_PIXEL_SHADER( sdk_eye_refract_ps30 );

			if ( bDrawFlashlightAdditivePass == true )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );	// Shadow depth map
				pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	// Noise map
			}
		}
#endif

		// On DX9, get the gamma read and write correct
		//pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, false );		// Cornea normal
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );			// Iris
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );			// Cube map reflection
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true );			// Ambient occlusion
		pShaderShadow->EnableSRGBWrite( true );

		if ( bDiffuseWarp )
		{
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );		// Light Warp
		}

		if ( bDrawFlashlightAdditivePass == true )
		{
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true );		// Flashlight cookie
		}

		// Fog
		if ( bDrawFlashlightAdditivePass == true )
		{
			pShader->FogToBlack();
		}
		else
		{
			pShader->FogToFogColor();
		}
	}
	DYNAMIC_STATE
	{
		VMatrix worldToTexture;
		ITexture *pFlashlightDepthTexture = NULL;
		FlashlightState_t flashlightState;
		bool bFlashlightShadows = false;
		if ( bDrawFlashlightAdditivePass == true )
		{
			flashlightState = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			bFlashlightShadows = flashlightState.m_bEnableShadows;
		}

		pShader->BindTexture( SHADER_SAMPLER0, info.m_nCorneaTexture );
		pShader->BindTexture( SHADER_SAMPLER1, info.m_nIris, info.m_nIrisFrame );
		pShader->BindTexture( SHADER_SAMPLER2, info.m_nEnvmap );
		pShader->BindTexture( SHADER_SAMPLER3, info.m_nAmbientOcclTexture );
	
		if ( bDiffuseWarp )
		{
			if ( r_lightwarpidentity.GetBool() )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_IDENTITY_LIGHTWARP );
			}
			else
			{
				pShader->BindTexture( SHADER_SAMPLER4, info.m_nDiffuseWarpTexture );
			}
		}

		if ( bDrawFlashlightAdditivePass == true )
			pShader->BindTexture( SHADER_SAMPLER5, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );

		pShader->SetAmbientCubeDynamicStateVertexShader();

		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nEyeOrigin );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nIrisU );
		pShader->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nIrisV );

		if ( bDrawFlashlightAdditivePass == true )
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, flashlightState.m_vecLightOrigin.Base(), 1 );

		LightState_t lightState = { 0, false, false };
		if ( bDrawFlashlightAdditivePass == false )
		{
			pShaderAPI->GetDX9LightState( &lightState );
		}

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( sdk_eye_refract_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( sdk_eye_refract_vs20 );
		}
#ifndef _X360
		else
		{
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 );

			DECLARE_DYNAMIC_VERTEX_SHADER( sdk_eye_refract_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DYNAMIC_LIGHT, lightState.HasDynamicLight() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( STATIC_LIGHT, lightState.m_bStaticLight ? 1 : 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, pShaderAPI->IsHWMorphingEnabled() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( sdk_eye_refract_vs30 );
		}
#endif

		// Get luminance of ambient cube and saturate it
		float fAverageAmbient = max(0.0f, min( pShaderAPI->GetAmbientLightCubeLuminance(), 1.0f ) );

		// Special constant for DX9 eyes: { Dilation, Glossiness, x, x };
		float vPSConst[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
		vPSConst[0] = IS_PARAM_DEFINED( info.m_nDilation ) ? params[info.m_nDilation]->GetFloatValue() : kDefaultDilation;
		vPSConst[1] = IS_PARAM_DEFINED( info.m_nGlossiness ) ? params[info.m_nGlossiness]->GetFloatValue() : kDefaultGlossiness;
		vPSConst[2] = fAverageAmbient;
		vPSConst[3] = IS_PARAM_DEFINED( info.m_nCorneaBumpStrength ) ? params[info.m_nCorneaBumpStrength]->GetFloatValue() : kDefaultCorneaBumpStrength;
		pShaderAPI->SetPixelShaderConstant( 0, vPSConst, 1 );

		pShaderAPI->SetPixelShaderConstant( 1, IS_PARAM_DEFINED( info.m_nEyeOrigin ) ? params[info.m_nEyeOrigin]->GetVecValue() : kDefaultEyeOrigin, 1 );
		pShaderAPI->SetPixelShaderConstant( 2, IS_PARAM_DEFINED( info.m_nIrisU ) ? params[info.m_nIrisU]->GetVecValue() : kDefaultIrisU, 1 );
		pShaderAPI->SetPixelShaderConstant( 3, IS_PARAM_DEFINED( info.m_nIrisV ) ? params[info.m_nIrisV]->GetVecValue() : kDefaultIrisV, 1 );

		float vEyePos[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos );
		pShaderAPI->SetPixelShaderConstant( 4, vEyePos, 1 );
		pShaderAPI->SetPixelShaderConstant( 5, IS_PARAM_DEFINED( info.m_nAmbientOcclColor ) ? params[info.m_nAmbientOcclColor]->GetVecValue() : kDefaultAmbientOcclColor, 1 );

		float vPackedConst6[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
		//vPackedConst6[0] Unused
		vPackedConst6[1] = IS_PARAM_DEFINED( info.m_nEyeballRadius ) ? params[info.m_nEyeballRadius]->GetFloatValue() : kDefaultEyeballRadius;
		//vPackedConst6[2] = IS_PARAM_DEFINED( info.m_nRaytraceSphere ) ? params[info.m_nRaytraceSphere]->GetFloatValue() : kDefaultRaytraceSphere;
		vPackedConst6[3] = IS_PARAM_DEFINED( info.m_nParallaxStrength ) ? params[info.m_nParallaxStrength]->GetFloatValue() : kDefaultParallaxStrength;
		pShaderAPI->SetPixelShaderConstant( 6, vPackedConst6, 1 );

		float fPixelFogType = pShaderAPI->GetPixelFogCombo() == 1 ? 1 : 0;

		// Controls for lerp-style paths through shader code
		float vShaderControls[4] = { fPixelFogType, 0, 0, 0 };
		pShaderAPI->SetPixelShaderConstant( 10, vShaderControls, 1 );

		if ( bDrawFlashlightAdditivePass == true )
		{
			SetFlashLightColorFromState( flashlightState, pShaderAPI );

			if ( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && flashlightState.m_bEnableShadows )
			{
				pShader->BindTexture( SHADER_SAMPLER6, pFlashlightDepthTexture, 0 );
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER7, TEXTURE_SHADOW_NOISE_2D );
			}
		}

		// Flashlight tax
#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_eye_refract_ps20b );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
				SET_DYNAMIC_PIXEL_SHADER( sdk_eye_refract_ps20b );
			}
			else // ps.2.0
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( sdk_eye_refract_ps20 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER( sdk_eye_refract_ps20 );
			}
		}
#ifndef _X360
		else
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( sdk_eye_refract_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER( sdk_eye_refract_ps30 );
		}
#endif

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		if ( bDrawFlashlightAdditivePass == true )
		{
			float atten[4], pos[4], tweaks[4];
			atten[0] = flashlightState.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = flashlightState.m_fLinearAtten;
			atten[2] = flashlightState.m_fQuadraticAtten;
			atten[3] = flashlightState.m_FarZ;
			pShaderAPI->SetPixelShaderConstant( 7, atten, 1 );

			pos[0] = flashlightState.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = flashlightState.m_vecLightOrigin[1];
			pos[2] = flashlightState.m_vecLightOrigin[2];
			pShaderAPI->SetPixelShaderConstant( 8, pos, 1 );

			//pShaderAPI->SetPixelShaderConstant( 9, worldToTexture.Base(), 4 );
			//10
			//11
			//12

			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, worldToTexture[0], 1 );
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, worldToTexture[1], 1 );
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, worldToTexture[2], 1 );
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, worldToTexture[3], 1 );

			// Tweaks associated with a given flashlight
			tweaks[0] = flashlightState.m_flShadowFilterSize / flashlightState.m_flShadowMapResolution;
			tweaks[1] = ShadowAttenFromState( flashlightState );
			pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			pShaderAPI->SetPixelShaderConstant( 9, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );
			vScreenScale[0] = (float) nWidth  / 32.0f;
			vScreenScale[1] = (float) nHeight / 32.0f;
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );
		}
		else // Lighting constants when not drawing flashlight
		{
			pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY );
		}

		// Intro tax
		if ( bIntro )
		{
			float curTime = params[info.m_nWarpParam]->GetFloatValue();
			float timeVec[4] = { 0.0f, 0.0f, 0.0f, curTime };
			if ( IS_PARAM_DEFINED( info.m_nEntityOrigin ) )
			{
				params[info.m_nEntityOrigin]->GetVecValue( timeVec, 3 );
			}
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, timeVec, 1 );
		}
	}
	pShader->Draw();
}
void DrawCloak_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
				    IShaderShadow* pShaderShadow, Cloak_DX9_Vars_t &info, VertexCompressionType_t vertexCompression )
{
	bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL );
	bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0);
	bool hasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture();
	bool hasPhongExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture();
	bool hasPhongTintMap = hasPhongExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 );
	bool bHasRimLight = (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 );
	bool bHasRimMaskMap = hasPhongExponentTexture && bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 );

	SHADOW_STATE
	{
		SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT );

		pShader->SetInitialShadowState( );

		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );	// Always SRGB read on base map
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );	// Refraction map sampler...

		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
		pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );

		pShaderShadow->EnableSRGBWrite( true );

		unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
		int nTexCoordCount = 1;
		int userDataSize = 0;
		if( bIsModel )
		{
			userDataSize = 4;
		}
		else
		{
			flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T;
		}

		// This shader supports compressed vertices, so OR in that flag:
		flags |= VERTEX_FORMAT_COMPRESSED;

		pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize );

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_STATIC_VERTEX_SHADER( cloak_vs20 );
			SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
			SET_STATIC_VERTEX_SHADER( cloak_vs20 );

			// Bind ps_2_b shader so we can get Phong terms
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_STATIC_PIXEL_SHADER( cloak_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, hasDiffuseWarp );
				SET_STATIC_PIXEL_SHADER( cloak_ps20b );
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( cloak_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, hasDiffuseWarp );
				SET_STATIC_PIXEL_SHADER( cloak_ps20 );
			}
		}
#ifndef _X360
		else
		{
			// The vertex shader uses the vertex id stream
			SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );

			DECLARE_STATIC_VERTEX_SHADER( cloak_vs30 );
			SET_STATIC_VERTEX_SHADER_COMBO( MODEL,  bIsModel );
			SET_STATIC_VERTEX_SHADER( cloak_vs30 );

			// Bind ps_2_b shader so we can get Phong terms
			DECLARE_STATIC_PIXEL_SHADER( cloak_ps30 );
			SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, hasDiffuseWarp );
			SET_STATIC_PIXEL_SHADER( cloak_ps30 );
		}
#endif

		pShader->DefaultFog();

		if( bMasked )
		{
			pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA );
		}
	}
	DYNAMIC_STATE
	{
		pShaderAPI->SetDefaultState();

		// Bind textures
		pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, 0 );							// Base Map
		pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 );	// Refraction Map
		pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame );				// Normal Map
		pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );	// Normalization cube map

		if ( hasDiffuseWarp )
		{
			if ( r_lightwarpidentity.GetBool() )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_IDENTITY_LIGHTWARP );
			}
			else
			{
				pShader->BindTexture( SHADER_SAMPLER1, info.m_nDiffuseWarpTexture );					// Light warp texture
			}
		}

		MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
		int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;

		LightState_t lightState;
		pShaderAPI->GetDX9LightState( &lightState );

#ifndef _X360
		if ( !g_pHardwareConfig->HasFastVertexTextures() )
#endif
		{
			DECLARE_DYNAMIC_VERTEX_SHADER( cloak_vs20 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,    fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,      pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( cloak_vs20 );

			// Bind ps_2_b shader so we can get Phong, rim and a cloudier refraction
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( cloak_ps20b );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER( cloak_ps20b );
			}
			else
			{
				// JasonM Hack
				//
				// In general, cloaking on ps_2_0 needs re-working for multipass...yuck...
				//
				int nPS20NumLights = max( lightState.m_nNumLights, 1 );
				DECLARE_DYNAMIC_PIXEL_SHADER( cloak_ps20 );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nPS20NumLights );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
				SET_DYNAMIC_PIXEL_SHADER( cloak_ps20 );
			}
		}
#ifndef _X360
		else
		{
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );

			DECLARE_DYNAMIC_VERTEX_SHADER( cloak_vs30 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( DOWATERFOG,    fogIndex );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING,      pShaderAPI->GetCurrentNumBones() > 0 );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING,		pShaderAPI->IsHWMorphingEnabled() );
			SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
			SET_DYNAMIC_VERTEX_SHADER( cloak_vs30 );

			DECLARE_DYNAMIC_PIXEL_SHADER( cloak_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA,  fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
			SET_DYNAMIC_PIXEL_SHADER( cloak_ps30 );
		}
#endif

		pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform );

		if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
		{
			pShader->SetPixelShaderConstant( 27, info.m_nRefractTint );
		}
		else
		{
			pShader->SetPixelShaderConstantGammaToLinear( 27, info.m_nRefractTint );
		}

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		// Pack phong exponent in with the eye position
		float vEyePos_SpecExponent[4], vFresnelRanges_SpecBoost[4] = {0, 0.5, 1, 1};
		float vSpecularTint[4] = {1, 1, 1, 1}, vRimBoost[4] = {1, 1, 1, 1};
		pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent );

		if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() )
			vEyePos_SpecExponent[3] = params[info.m_nPhongExponent]->GetFloatValue();		// This overrides the channel in the map
		else
			vEyePos_SpecExponent[3] = 0;													// Use the alpha channel of the normal map for the exponent

		if ( (info.m_nPhongTint != -1 ) && params[info.m_nPhongTint]->IsDefined() )			// Get the tint parameter
			params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 4);

		// Get the rim light power (goes in w of Phong tint)
		if ( bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() )
		{
			vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue();
			vSpecularTint[3] = max(vSpecularTint[3], 1.0f);	// Make sure this is at least 1
		}

		// Get the rim boost power (goes in w of flashlight position)
		if ( bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() )
		{
			vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue();
		}

		// Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term
		if ( bHasRimMaskMap )
		{
			float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code
			vRimMaskControl[0] = params[info.m_nRimMask]->GetFloatValue();
			pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 );
		}

		// If it's all zeros, there was no constant tint in the vmt
		if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) )
		{
			if ( hasPhongTintMap )				// If we have a map to use, tell the shader
			{
				vSpecularTint[0] = -1;
			}
			else								// Otherwise, just tint with white
			{
				vSpecularTint[0] = 1.0f;
				vSpecularTint[1] = 1.0f;
				vSpecularTint[2] = 1.0f;
			}
		}

		if ( (info.m_nPhongFresnelRanges != -1 ) && params[info.m_nPhongFresnelRanges]->IsDefined() )
			params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 );	// Grab optional fresnel range parameters

		if ( ( info.m_nPhongBoost != -1 ) &&params[info.m_nPhongBoost]->IsDefined() )		// Grab optional phong boost param
			vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue();
		else
			vFresnelRanges_SpecBoost[3] = 1.0f;

		pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 );
		pShaderAPI->SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 );

		pShaderAPI->SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 );
		pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 );	// Rim boost in w on non-flashlight pass

		pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );

		// Lighting constants
		
		pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight );
		pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY );

		// Set c0 and c1 to contain first two rows of ViewProj matrix
		VMatrix matView, matProj, matViewProj;
		pShaderAPI->GetMatrix( MATERIAL_VIEW, matView.m[0] );
		pShaderAPI->GetMatrix( MATERIAL_PROJECTION, matProj.m[0] );
		matViewProj = matView * matProj;
		pShaderAPI->SetPixelShaderConstant( 0, matViewProj.m[0], 2 );

		// Cloaking control constants
		float vCloakControls[4] = { params[info.m_nRefractAmount]->GetFloatValue(), params[info.m_nCloakFactor]->GetFloatValue(), 0.0f, 0.0f };
		pShaderAPI->SetPixelShaderConstant( 3, vCloakControls, 1 );
	}
	pShader->Draw();
}
void DrawPassComposite( const defParms_composite &info, CBaseVSShader *pShader, IMaterialVar **params,
	IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI,
	VertexCompressionType_t vertexCompression, CDeferredPerMaterialContextData *pDeferredContext )
{
	const bool bModel = info.bModel;
	const bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL );
	const bool bFastVTex = g_pHardwareConfig->HasFastVertexTextures();

	const bool bAlbedo = PARM_TEX( info.iAlbedo );
	const bool bAlbedo2 = !bModel && bAlbedo && PARM_TEX( info.iAlbedo2 );
	const bool bAlbedo3 = !bModel && bAlbedo && PARM_TEX( info.iAlbedo3 );
	const bool bAlbedo4 = !bModel && bAlbedo && PARM_TEX( info.iAlbedo4 );

	const bool bAlphatest = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) && bAlbedo;
	const bool bTranslucent = IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) && bAlbedo && !bAlphatest;

	const bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL );

	const bool bUseSRGB = DEFCFG_USE_SRGB_CONVERSION != 0;
	const bool bPhongFresnel = PARM_SET( info.iPhongFresnel );

	const bool bEnvmap = PARM_TEX( info.iEnvmap );
	const bool bEnvmapMask = bEnvmap && PARM_TEX( info.iEnvmapMask );
	const bool bEnvmapMask2 = bEnvmapMask && PARM_TEX( info.iEnvmapMask2 );
	const bool bEnvmapFresnel = bEnvmap && PARM_SET( info.iEnvmapFresnel );

	const bool bRimLight = PARM_SET( info.iRimlightEnable );
	const bool bRimLightModLight = bRimLight && PARM_SET( info.iRimlightModLight );
	const bool bBlendmodulate = bAlbedo2 && PARM_TEX( info.iBlendmodulate );
	const bool bBlendmodulate2 = bBlendmodulate && PARM_TEX( info.iBlendmodulate2 );
	const bool bBlendmodulate3 = bBlendmodulate && PARM_TEX( info.iBlendmodulate3 );

	const bool bSelfIllum = !bAlbedo2 && IS_FLAG_SET( MATERIAL_VAR_SELFILLUM );
	const bool bSelfIllumMaskInEnvmapMask = bSelfIllum && bEnvmapMask && PARM_SET( info.iSelfIllumMaskInEnvmapAlpha );
	const bool bSelfIllumMask = bSelfIllum && !bSelfIllumMaskInEnvmapMask && !bEnvmapMask && PARM_TEX( info.iSelfIllumMask );

	const bool bMultiBlend = PARM_SET( info.iMultiblend )
		&& bAlbedo && bAlbedo2 && bAlbedo3 && !bEnvmapMask && !bSelfIllumMask;

	const bool bNeedsFresnel = bPhongFresnel || bEnvmapFresnel;
	const bool bGBufferNormal = bEnvmap || bRimLight || bNeedsFresnel;
	const bool bWorldEyeVec = bGBufferNormal;


	AssertMsgOnce( !(bTranslucent || bAlphatest) || !bAlbedo2,
		"blended albedo not supported by gbuffer pass!" );

	AssertMsgOnce( IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) == false,
		"Normal map sampling should stay out of composition pass." );

	AssertMsgOnce( !PARM_TEX( info.iSelfIllumMask ) || !bEnvmapMask,
		"Can't use separate selfillum mask with envmap mask - use SELFILLUM_ENVMAPMASK_ALPHA instead." );

	AssertMsgOnce( PARM_SET( info.iMultiblend ) == bMultiBlend,
		"Multiblend forced off due to invalid usage! May cause vertexformat mis-matches between passes." );


	SHADOW_STATE
	{
		pShaderShadow->SetDefaultState();
		pShaderShadow->EnableSRGBWrite( bUseSRGB );

		if ( bNoCull )
		{
			pShaderShadow->EnableCulling( false );
		}

		int iVFmtFlags = VERTEX_POSITION;
		int iUserDataSize = 0;

		int *pTexCoordDim;
		int iTexCoordNum;
		GetTexcoordSettings( ( bModel && bIsDecal && bFastVTex ), bMultiBlend,
			iTexCoordNum, &pTexCoordDim );

		if ( bModel )
		{
			iVFmtFlags |= VERTEX_NORMAL;
			iVFmtFlags |= VERTEX_FORMAT_COMPRESSED;
		}
		else
		{
			if ( bAlbedo2 )
				iVFmtFlags |= VERTEX_COLOR;
		}

		pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bUseSRGB );

		if ( bGBufferNormal )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false );
		}

		if ( bTranslucent )
		{
			pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
		}

		pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
		pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false );

		if ( bEnvmap )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );

			if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true );

			if ( bEnvmapMask )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );

				if ( bAlbedo2 )
					pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
			}
		}
		else if ( bSelfIllumMask )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
		}

		if ( bAlbedo2 )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, bUseSRGB );

			if ( bBlendmodulate )
				pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );
		}

		if ( bMultiBlend )
		{
			pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, bUseSRGB );

			if ( bAlbedo4 )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, bUseSRGB );
			}

			if ( bBlendmodulate )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );
				pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );
			}
		}

		pShaderShadow->EnableAlphaWrites( false );
		pShaderShadow->EnableDepthWrites( !bTranslucent );

		pShader->DefaultFog();

		pShaderShadow->VertexShaderVertexFormat( iVFmtFlags, iTexCoordNum, pTexCoordDim, iUserDataSize );

		DECLARE_STATIC_VERTEX_SHADER( composite_vs30 );
		SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bModel );
		SET_STATIC_VERTEX_SHADER_COMBO( MORPHING_VTEX, bModel && bFastVTex );
		SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bModel && bIsDecal );
		SET_STATIC_VERTEX_SHADER_COMBO( EYEVEC, bWorldEyeVec );
		SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE2, bAlbedo2 && !bMultiBlend );
		SET_STATIC_VERTEX_SHADER_COMBO( BLENDMODULATE, bBlendmodulate );
		SET_STATIC_VERTEX_SHADER_COMBO( MULTIBLEND, bMultiBlend );
		SET_STATIC_VERTEX_SHADER( composite_vs30 );

		DECLARE_STATIC_PIXEL_SHADER( composite_ps30 );
		SET_STATIC_PIXEL_SHADER_COMBO( ALPHATEST, bAlphatest );
		SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, bTranslucent );
		SET_STATIC_PIXEL_SHADER_COMBO( READNORMAL, bGBufferNormal );
		SET_STATIC_PIXEL_SHADER_COMBO( NOCULL, bNoCull );
		SET_STATIC_PIXEL_SHADER_COMBO( ENVMAP, bEnvmap );
		SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bEnvmapMask );
		SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPFRESNEL, bEnvmapFresnel );
		SET_STATIC_PIXEL_SHADER_COMBO( PHONGFRESNEL, bPhongFresnel );
		SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bRimLight );
		SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHTMODULATELIGHT, bRimLightModLight );
		SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, bAlbedo2 && !bMultiBlend );
		SET_STATIC_PIXEL_SHADER_COMBO( BLENDMODULATE, bBlendmodulate );
		SET_STATIC_PIXEL_SHADER_COMBO( MULTIBLEND, bMultiBlend );
		SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bSelfIllum );
		SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_MASK, bSelfIllumMask );
		SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAP_ALPHA, bSelfIllumMaskInEnvmapMask );
		SET_STATIC_PIXEL_SHADER( composite_ps30 );
	}
	DYNAMIC_STATE
	{
		Assert( pDeferredContext != NULL );

		if ( pDeferredContext->m_bMaterialVarsChanged || !pDeferredContext->HasCommands( CDeferredPerMaterialContextData::DEFSTAGE_COMPOSITE )
			|| building_cubemaps.GetBool() )
		{
			tmpBuf.Reset();

			if ( bAlphatest )
			{
				PARM_VALIDATE( info.iAlphatestRef );
				tmpBuf.SetPixelShaderConstant1( 0, PARM_FLOAT( info.iAlphatestRef ) );
			}

			if ( bAlbedo )
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER0, info.iAlbedo );
			else
				tmpBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );

			if ( bEnvmap )
			{
				if ( building_cubemaps.GetBool() )
					tmpBuf.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_BLACK );
				else
				{
					if ( PARM_TEX( info.iEnvmap ) && !bModel )
						tmpBuf.BindTexture( pShader, SHADER_SAMPLER3, info.iEnvmap );
					else
						tmpBuf.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LOCAL_ENV_CUBEMAP );
				}

				if ( bEnvmapMask )
					tmpBuf.BindTexture( pShader, SHADER_SAMPLER4, info.iEnvmapMask );

				if ( bAlbedo2 )
				{
					if ( bEnvmapMask2 )
						tmpBuf.BindTexture( pShader, SHADER_SAMPLER7, info.iEnvmapMask2 );
					else
						tmpBuf.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE );
				}

				tmpBuf.SetPixelShaderConstant( 5, info.iEnvmapTint );

				float fl6[4] = { 0 };
				fl6[0] = PARM_FLOAT( info.iEnvmapSaturation );
				fl6[1] = PARM_FLOAT( info.iEnvmapContrast );
				tmpBuf.SetPixelShaderConstant( 6, fl6 );
			}

			if ( bNeedsFresnel )
			{
				tmpBuf.SetPixelShaderConstant( 7, info.iFresnelRanges );
			}

			if ( bRimLight )
			{
				float fl9[4] = { 0 };
				fl9[0] = PARM_FLOAT( info.iRimlightExponent );
				fl9[1] = PARM_FLOAT( info.iRimlightAlbedoScale );
				tmpBuf.SetPixelShaderConstant( 9, fl9 );
			}

			if ( bAlbedo2 )
			{
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER5, info.iAlbedo2 );

				if ( bBlendmodulate )
				{
					tmpBuf.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.iBlendmodulateTransform );
					tmpBuf.BindTexture( pShader, SHADER_SAMPLER6, info.iBlendmodulate );
				}
			}

			if ( bMultiBlend )
			{
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER7, info.iAlbedo3 );

				if ( bAlbedo4 )
					tmpBuf.BindTexture( pShader, SHADER_SAMPLER8, info.iAlbedo4 );
				else
					tmpBuf.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_WHITE );

				if ( bBlendmodulate )
				{
					tmpBuf.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.iBlendmodulateTransform2 );
					tmpBuf.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, info.iBlendmodulateTransform3 );

					if ( bBlendmodulate2 )
						tmpBuf.BindTexture( pShader, SHADER_SAMPLER9, info.iBlendmodulate2 );
					else
						tmpBuf.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_BLACK );

					if ( bBlendmodulate3 )
						tmpBuf.BindTexture( pShader, SHADER_SAMPLER10, info.iBlendmodulate3 );
					else
						tmpBuf.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_BLACK );
				}
			}

			if ( bSelfIllum && bSelfIllumMask )
			{
				tmpBuf.BindTexture( pShader, SHADER_SAMPLER4, info.iSelfIllumMask );
			}

			int x, y, w, t;
			pShaderAPI->GetCurrentViewport( x, y, w, t );
			float fl1[4] = { 1.0f / w, 1.0f / t, 0, 0 };

			tmpBuf.SetPixelShaderConstant( 1, fl1 );

			tmpBuf.SetPixelShaderFogParams( 2 );

			float fl4 = { PARM_FLOAT( info.iPhongScale ) };
			tmpBuf.SetPixelShaderConstant1( 4, fl4 );

			tmpBuf.End();

			pDeferredContext->SetCommands( CDeferredPerMaterialContextData::DEFSTAGE_COMPOSITE, tmpBuf.Copy() );
		}

		pShaderAPI->SetDefaultState();

		if ( bModel && bFastVTex )
			pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 );
		
		DECLARE_DYNAMIC_VERTEX_SHADER( composite_vs30 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (bModel && (int)vertexCompression) ? 1 : 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, (bModel && pShaderAPI->GetCurrentNumBones() > 0) ? 1 : 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, (bModel && pShaderAPI->IsHWMorphingEnabled()) ? 1 : 0 );
		SET_DYNAMIC_VERTEX_SHADER( composite_vs30 );

		DECLARE_DYNAMIC_PIXEL_SHADER( composite_ps30 );
		SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
		SET_DYNAMIC_PIXEL_SHADER( composite_ps30 );

		if ( bModel && bFastVTex )
		{
			bool bUnusedTexCoords[3] = { false, true, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal };
			pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords );
		}

		pShaderAPI->ExecuteCommandBuffer( pDeferredContext->GetCommands( CDeferredPerMaterialContextData::DEFSTAGE_COMPOSITE ) );

		if ( bGBufferNormal )
			pShader->BindTexture( SHADER_SAMPLER1, GetDeferredExt()->GetTexture_Normals() );

		pShader->BindTexture( SHADER_SAMPLER2, GetDeferredExt()->GetTexture_LightAccum() );

		CommitBaseDeferredConstants_Origin( pShaderAPI, 3 );

		if ( bWorldEyeVec )
		{
			float vEyepos[4] = {0,0,0,0};
			pShaderAPI->GetWorldSpaceCameraPosition( vEyepos );
			pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vEyepos );
		}

		if ( bRimLight )
		{
			pShaderAPI->SetPixelShaderConstant( 8, params[ info.iRimlightTint ]->GetVecValue() );
		}

		if ( bSelfIllum )
		{
			pShaderAPI->SetPixelShaderConstant( 10, params[ info.iSelfIllumTint ]->GetVecValue() );
		}
	}

	pShader->Draw();
}
示例#23
0
	void DrawPass( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
		IShaderShadow* pShaderShadow, bool hasFlashlight, VertexCompressionType_t vertexCompression )
	{
		bool bSinglePassFlashlight = false;
		bool hasBump = params[BUMPMAP]->IsTexture();
		bool hasDiffuseBumpmap = hasBump && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0);
		bool hasBaseTexture = params[BASETEXTURE]->IsTexture();
		bool hasDetailTexture = /*!hasBump && */params[DETAIL]->IsTexture();
		bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) != 0;
		bool bHasDetailAlpha = params[DETAIL_ALPHA_MASK_BASE_TEXTURE]->GetIntValue() != 0;
		bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;

		BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true );
		bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use

		bool bSeamlessMapping = params[SEAMLESS_SCALE]->GetFloatValue() != 0.0;

		bool bShaderSrgbRead = ( IsX360() && IS_PARAM_DEFINED( SHADERSRGBREAD360 ) && params[SHADERSRGBREAD360]->GetIntValue() );

		SHADOW_STATE
		{
			int nShadowFilterMode = 0;

			// Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState
			pShaderShadow->EnableAlphaTest( bIsAlphaTested );
			if( hasFlashlight )
			{
				if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
				{
					nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
				}

				SetAdditiveBlendingShadowState( BASETEXTURE, true );
				pShaderShadow->EnableDepthWrites( false );

				// Be sure not to write to dest alpha
				pShaderShadow->EnableAlphaWrites( false );
			}
			else
			{
				SetDefaultBlendingShadowState( BASETEXTURE, true );
			}

			unsigned int flags = VERTEX_POSITION;
			if( hasBaseTexture )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead );
			}
			//			if( hasLightmap )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, true );
			}
			if( hasFlashlight )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
				pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );
				pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 );
				flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T | VERTEX_NORMAL;
			}
			if( hasDetailTexture )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
			}
			if( hasBump )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
			}
			if( hasVertexColor )
			{
				flags |= VERTEX_COLOR;
			}

			// Normalizing cube map
			pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );

			// texcoord0 : base texcoord
			// texcoord1 : lightmap texcoord
			// texcoord2 : lightmap texcoord offset
			int numTexCoords = 2;
			if( hasBump )
			{
				numTexCoords = 3;
			}

			pShaderShadow->VertexShaderVertexFormat( flags, numTexCoords, 0, 0 );

			// Pre-cache pixel shaders
			bool hasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM );

			pShaderShadow->EnableSRGBWrite( true );

			int nLightingPreviewMode = IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 );

#ifndef _X360
			if ( g_pHardwareConfig->HasFastVertexTextures() )
			{
				DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs30 );
				SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK,  false );
				SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK,  false );
				SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE,  hasFlashlight );
				SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP,  hasBump );
				SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
				SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor );
				SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, false );
				SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, 0 ); //( bumpmap_variant == 2 )?1:0);
				SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); //( bumpmap_variant == 2 )?1:0);
				SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
				SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
				SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING,  false );
				SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode != 0 );
				SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs30 );
			}
			else
#endif
			{
				DECLARE_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 );
				SET_STATIC_VERTEX_SHADER_COMBO( ENVMAP_MASK,  false );
				SET_STATIC_VERTEX_SHADER_COMBO( BUMPMASK,  false );
				SET_STATIC_VERTEX_SHADER_COMBO( TANGENTSPACE,  hasFlashlight );
				SET_STATIC_VERTEX_SHADER_COMBO( BUMPMAP,  hasBump );
				SET_STATIC_VERTEX_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
				SET_STATIC_VERTEX_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor );
				SET_STATIC_VERTEX_SHADER_COMBO( VERTEXALPHATEXBLENDFACTOR, false );
				SET_STATIC_VERTEX_SHADER_COMBO( PARALLAX_MAPPING, 0 ); //( bumpmap_variant == 2 )?1:0);
				SET_STATIC_VERTEX_SHADER_COMBO( SEAMLESS, bSeamlessMapping ); //( bumpmap_variant == 2 )?1:0);
				SET_STATIC_VERTEX_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
				SET_STATIC_VERTEX_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
				SET_STATIC_VERTEX_SHADER_COMBO( FANCY_BLENDING,  false );
				SET_STATIC_VERTEX_SHADER_COMBO( LIGHTING_PREVIEW, nLightingPreviewMode != 0 );
	#ifdef _X360
				SET_STATIC_VERTEX_SHADER_COMBO( FLASHLIGHT, hasFlashlight );
	#endif
				SET_STATIC_VERTEX_SHADER( lightmappedgeneric_vs20 );
			}

#ifndef _X360
			if ( g_pHardwareConfig->HasFastVertexTextures() )
			{
				DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps30 );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
				SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  hasBump );
				SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
				SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor );
				SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE,  bHasDetailAlpha );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
				SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS,  bSeamlessMapping );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
				SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
				SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps30 );
			}
			else
#endif
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
				SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  hasBump );
				SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
				SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor );
				SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE,  bHasDetailAlpha );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
				SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS,  bSeamlessMapping );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
				SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
				SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20b );
			}
			else
			{
				DECLARE_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE,  hasDetailTexture );
				SET_STATIC_PIXEL_SHADER_COMBO( BUMPMAP,  hasBump );
				SET_STATIC_PIXEL_SHADER_COMBO( DIFFUSEBUMPMAP,  hasDiffuseBumpmap );
				SET_STATIC_PIXEL_SHADER_COMBO( VERTEXCOLOR,  hasVertexColor );
				SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM,  hasSelfIllum );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_ALPHA_MASK_BASE_TEXTURE,  bHasDetailAlpha );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT,  hasFlashlight );
				SET_STATIC_PIXEL_SHADER_COMBO( SEAMLESS,  bSeamlessMapping );
				SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
				SET_STATIC_PIXEL_SHADER( worldtwotextureblend_ps20 );
			}

			// HACK HACK HACK - enable alpha writes all the time so that we have them for
			// underwater stuff. 
			// But only do it if we're not using the alpha already for translucency
			pShaderShadow->EnableAlphaWrites( bFullyOpaque );

			if( hasFlashlight )
			{
				FogToBlack();
			}
			else
			{
				DefaultFog();
			}

			PI_BeginCommandBuffer();
			PI_SetModulationVertexShaderDynamicState( );
			PI_EndCommandBuffer();
		}
		DYNAMIC_STATE
		{
			if( hasBaseTexture )
			{
				BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME );
			}
			else
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
			}

			//			if( hasLightmap )
			{
				pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP );
			}

			bool bFlashlightShadows = false;
			bool bUberlight = false;
			if( hasFlashlight )
			{
				VMatrix worldToTexture;
				ITexture *pFlashlightDepthTexture;
				FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
				bFlashlightShadows = state.m_bEnableShadows;
				bUberlight = state.m_bUberlight;

				SetFlashLightColorFromState( state, pShaderAPI, bSinglePassFlashlight );

				BindTexture( SHADER_SAMPLER2, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame );

				if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() )
				{
					BindTexture( SHADER_SAMPLER7, pFlashlightDepthTexture );
				}
			}
			if( hasDetailTexture )
			{
				BindTexture( SHADER_SAMPLER3, DETAIL, DETAILFRAME );
			}
			if( hasBump )
			{
				if( !g_pConfig->m_bFastNoBump )
				{
					BindTexture( SHADER_SAMPLER4, BUMPMAP, BUMPFRAME );
				}
				else
				{
					pShaderAPI->BindStandardTexture( SHADER_SAMPLER4, TEXTURE_NORMALMAP_FLAT );
				}
			}
			pShaderAPI->BindStandardTexture( SHADER_SAMPLER6, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );

			// If we don't have a texture transform, we don't have
			// to set vertex shader constants or run vertex shader instructions
			// for the texture transform.
			bool bHasTextureTransform = 
				!( params[BASETEXTURETRANSFORM]->MatrixIsIdentity() &&
				params[BUMPTRANSFORM]->MatrixIsIdentity() );

			bool bVertexShaderFastPath = !bHasTextureTransform;
			if( params[DETAIL]->IsTexture() )
			{
				bVertexShaderFastPath = false;
			}
			if( pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) != 0 )
			{
				bVertexShaderFastPath = false;
			}

			if( !bVertexShaderFastPath )
			{
				if ( !bSeamlessMapping )
				{
					SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM );
				}
				if( hasBump && !bHasDetailAlpha )
				{
					SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BUMPTRANSFORM );
					Assert( !hasDetailTexture );
				}
			}

			MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();

			if ( IsPC() )
			{
				bool bWorldNormal = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING ) == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH;
				if ( bWorldNormal )
				{
					float vEyeDir[4];
					pShaderAPI->GetWorldSpaceCameraDirection( vEyeDir );

					float flFarZ = pShaderAPI->GetFarZ();
					vEyeDir[0] /= flFarZ;	// Divide by farZ for SSAO algorithm
					vEyeDir[1] /= flFarZ;
					vEyeDir[2] /= flFarZ;
					pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_12, vEyeDir );
				}
			}

#ifndef _X360
			if (g_pHardwareConfig->HasFastVertexTextures() )
			{
				DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs30 );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH,  bVertexShaderFastPath );
				SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs30 );
			}
			else
#endif
			{
				DECLARE_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 );
				SET_DYNAMIC_VERTEX_SHADER_COMBO( FASTPATH,  bVertexShaderFastPath );
				SET_DYNAMIC_VERTEX_SHADER( lightmappedgeneric_vs20 );
			}

			bool bWriteDepthToAlpha;
			bool bWriteWaterFogToAlpha;
			if( bFullyOpaque ) 
			{
				bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
				bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
				AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
			}
			else
			{
				//can't write a special value to dest alpha if we're actually using as-intended alpha
				bWriteDepthToAlpha = false;
				bWriteWaterFogToAlpha = false;
			}

#ifndef _X360
			if ( g_pHardwareConfig->HasFastVertexTextures() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps30 );

				// Don't write fog to alpha if we're using translucency
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight );
				SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps30 );
			}
			else
#endif
			if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b );

				// Don't write fog to alpha if we're using translucency
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
				SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
				SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20b );
			}
			else
			{
				DECLARE_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 );

				// Don't write fog to alpha if we're using translucency
				SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z) && 
												(nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested );
				SET_DYNAMIC_PIXEL_SHADER( worldtwotextureblend_ps20 );
			}


			// always set the transform for detail textures since I'm assuming that you'll
			// always have a detailscale.
			if( hasDetailTexture )
			{
				SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, DETAILSCALE );
				Assert( !( hasBump && !bHasDetailAlpha ) );
			}

			SetPixelShaderConstantGammaToLinear( 7, SELFILLUMTINT );

			float eyePos[4];
			pShaderAPI->GetWorldSpaceCameraPosition( eyePos );
			pShaderAPI->SetPixelShaderConstant( 10, eyePos, 1 );
			pShaderAPI->SetPixelShaderFogParams( 11 );

			if ( bSeamlessMapping )
			{
				float map_scale[4]={ params[SEAMLESS_SCALE]->GetFloatValue(),0,0,0};
				pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale );
			}


			if( hasFlashlight )
			{
				VMatrix worldToTexture;
				const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture );

				// Set the flashlight attenuation factors
				float atten[4];
				atten[0] = flashlightState.m_fConstantAtten;
				atten[1] = flashlightState.m_fLinearAtten;
				atten[2] = flashlightState.m_fQuadraticAtten;
				atten[3] = flashlightState.m_FarZAtten;
				pShaderAPI->SetPixelShaderConstant( 20, atten, 1 );

				// Set the flashlight origin
				float pos[4];
				pos[0] = flashlightState.m_vecLightOrigin[0];
				pos[1] = flashlightState.m_vecLightOrigin[1];
				pos[2] = flashlightState.m_vecLightOrigin[2];
				pos[3] = flashlightState.m_FarZ; // didn't have this in main. . probably need this?
				pShaderAPI->SetPixelShaderConstant( 15, pos, 1 );

				pShaderAPI->SetPixelShaderConstant( 16, worldToTexture.Base(), 4 );

				if ( IsPC() && g_pHardwareConfig->HasFastVertexTextures() )
				{
					SetupUberlightFromState( pShaderAPI, flashlightState );
				}
			}
		}
		Draw();
	}
示例#24
0
void DrawFlesh(  CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
				IShaderShadow* pShaderShadow, FleshVars_t &info, VertexCompressionType_t vertexCompression,
				CBasePerMaterialContextData **pContextDataPtr )
{
	CFlesh_DX9_Context *pContextData = reinterpret_cast< CFlesh_DX9_Context *> ( *pContextDataPtr );

	bool bHasFlashlight = pShader->UsingFlashlight( params );
	bool bAlphaBlend = IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT );
	bool bDetail = ( info.m_nDetailTexture != -1 ) && ( params[info.m_nDetailTexture]->IsTexture() );

	if ( pShader->IsSnapshotting() || (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) )
	{
		bool bTransMatMasks = (info.m_nTransMatMasksTexture != -1) && params[info.m_nTransMatMasksTexture]->IsTexture();
		bool bEffectMasks = (info.m_nEffectMasksTexture != -1) && params[info.m_nEffectMasksTexture]->IsTexture();
		bool bIridescentWarp = (info.m_nIridescentWarpTexture != -1) && params[info.m_nIridescentWarpTexture]->IsTexture();
		bool bFresnelColorWarp = (info.m_nFresnelColorWarpTexture != -1) && params[info.m_nFresnelColorWarpTexture]->IsTexture();
		bool bColorWarp = (info.m_nColorWarpTexture != -1) && params[info.m_nColorWarpTexture]->IsTexture();
		bool bOpacityTexture = (info.m_nOpacityTexture != -1) && params[info.m_nOpacityTexture]->IsTexture();
		bool bInteriorLayer = (info.m_nInteriorEnable != -1) && ( params[info.m_nInteriorEnable]->GetIntValue() > 0 );
		bool bBackScatter = ( info.m_nBackScatter != -1 ) && ( params[info.m_nBackScatter]->GetFloatValue() > 0 );
		bool bForwardScatter = ( info.m_nForwardScatter != -1) && ( params[info.m_nForwardScatter]->GetFloatValue() > 0 );
		bool bNormal2 = ( info.m_nNormal2Softness != -1 ) && ( params[info.m_nNormal2Softness]->GetFloatValue() > 0 );

		if ( pShader->IsSnapshotting() )
		{
			// Set stream format (note that this shader supports compression)
			unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED;
			int nTexCoordCount = 1;
			int userDataSize = 4;
			int texCoordDims[4] = { 2, 2, 2, 2 };
			pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, texCoordDims, userDataSize );

			int nShadowFilterMode = 0;
			if ( bHasFlashlight )
			{
				nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode();	// Based upon vendor and device dependent formats
			}

			DECLARE_STATIC_VERTEX_SHADER( flesh_vs30 );
			SET_STATIC_VERTEX_SHADER( flesh_vs30 );

			// Pixel Shader
			if( /* g_pHardwareConfig->SupportsPixelShaders_3_0() */ true )
			{
				DECLARE_STATIC_PIXEL_SHADER( flesh_ps30 );
				SET_STATIC_PIXEL_SHADER_COMBO( ALPHABLEND, bAlphaBlend );
				SET_STATIC_PIXEL_SHADER_COMBO( TRANSMAT, bTransMatMasks );
				SET_STATIC_PIXEL_SHADER_COMBO( FRESNEL_WARP, bFresnelColorWarp );
				SET_STATIC_PIXEL_SHADER_COMBO( EFFECTS, bEffectMasks );
				SET_STATIC_PIXEL_SHADER_COMBO( TINTING, bColorWarp );
				SET_STATIC_PIXEL_SHADER_COMBO( IRIDESCENCE, bIridescentWarp );
				SET_STATIC_PIXEL_SHADER_COMBO( OPACITY_TEXTURE, bOpacityTexture );
				SET_STATIC_PIXEL_SHADER_COMBO( DETAIL, bDetail );
				SET_STATIC_PIXEL_SHADER_COMBO( NORMAL2SOFT, bNormal2 );
				SET_STATIC_PIXEL_SHADER_COMBO( INTERIOR_LAYER, bInteriorLayer );
				SET_STATIC_PIXEL_SHADER_COMBO( BACK_SCATTER, bBackScatter );
				SET_STATIC_PIXEL_SHADER_COMBO( FORWARD_SCATTER, bForwardScatter );
				SET_STATIC_PIXEL_SHADER_COMBO( HIGH_PRECISION_DEPTH, (g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT) ? true : false );
				SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
				SET_STATIC_PIXEL_SHADER( flesh_ps30 );
			}
			else
			{
				Assert( !"No ps_3_0" );
			}

			// Textures
			pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );		// [sRGB] Base
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );
			pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );		//		 Bump
			pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false );
			if( bInteriorLayer )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );		// [sRGB] Backbuffer
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true );
			}
			if( bTransMatMasks )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );		//       Trans mat masks
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false );
			}
			if( bColorWarp )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );		// [sRGB] Color Warp
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true );
			}
			if( bFresnelColorWarp )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );		// [sRGB] Fresnel color warp (should be sRGB?)
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true );
			}
			if( bOpacityTexture )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER6, true );		//		 Opacity
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, false );
			}
			if( bEffectMasks )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER10, true );		//		 Effect masks
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, false );
			}
			if( bIridescentWarp )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER11, true );		// [sRGB] Iridescent warp
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER11, true );
			}
			if( bDetail )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER12, true );		// [sRGB] Detail
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER12, true );
			}
			if ( bHasFlashlight )
			{
				pShaderShadow->EnableTexture( SHADER_SAMPLER7, true );	//		 Shadow depth map
				pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER7 );
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, false );
				pShaderShadow->EnableTexture( SHADER_SAMPLER8, true );	//		 Noise map
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, false );
				pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );	//[sRGB] Flashlight cookie
				pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true );

				// Flashlight passes - additive blending
				pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE );
				pShaderShadow->EnableAlphaWrites( false );
				pShaderShadow->EnableDepthWrites( false );
			}
			else if ( bAlphaBlend )
			{
				// Base pass - alpha blending (regular translucency)
				pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
				pShaderShadow->EnableAlphaWrites( false );	// TODO: write alpha for fog or not?
				pShaderShadow->EnableDepthWrites( true );	// Rely on depth-sorting
			}
			else
			{
				// Base pass - opaque blending (solid flesh or refractive translucency)
				pShader->DisableAlphaBlending();
				pShaderShadow->EnableAlphaWrites( true );
				pShaderShadow->EnableDepthWrites( true );
			}

			pShaderShadow->EnableSRGBWrite( true );

			// Per-instance state
			pShader->PI_BeginCommandBuffer();
			pShader->PI_SetVertexShaderAmbientLightCube();
			pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE );
			pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY );
			pShader->PI_EndCommandBuffer();
		}
		if ( pShaderAPI && ( (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) )
		{
			if ( !pContextData )								// make sure allocated
			{
				pContextData = new CFlesh_DX9_Context;
				*pContextDataPtr = pContextData;
			}
			pContextData->m_bMaterialVarsChanged = false;
			pContextData->m_SemiStaticCmdsOut.Reset();
			///////////////////////////
			// Semi-static block
			///////////////////////////
			float flConsts[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

			flConsts[0] = IS_PARAM_DEFINED( info.m_nBumpStrength ) ? params[info.m_nBumpStrength]->GetFloatValue() : kDefaultBumpStrength;
			flConsts[1] = (g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT) ? 8192.0f : 192.0f;	// destalpha dest scale factor. TODO: put this in its own const and call shaderAPI method to set
			flConsts[2] = IS_PARAM_DEFINED( info.m_nInteriorFogStrength ) ? params[info.m_nInteriorFogStrength]->GetFloatValue() : kDefaultInteriorFogStrength;
			flConsts[3] = IS_PARAM_DEFINED( info.m_nInteriorRefractStrength ) ? params[info.m_nInteriorRefractStrength]->GetFloatValue() : kDefaultInteriorRefractStrength;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 0, flConsts, 1 );

			Assert( IS_PARAM_DEFINED( info.m_nFresnelParams ) );
			if ( IS_PARAM_DEFINED( info.m_nFresnelParams ) )
				params[info.m_nFresnelParams]->GetVecValue( flConsts, 3 );
			else
				memcpy( flConsts, kDefaultFresnelParams, sizeof( kDefaultFresnelParams ) );
			flConsts[3] = params[info.m_nInteriorBackgroundBoost]->GetFloatValue();
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 1, flConsts, 1 );

			flConsts[0] = IS_PARAM_DEFINED( info.m_nRimLightExp ) ? params[info.m_nRimLightExp]->GetFloatValue() : kDefaultRimLightExp;
			flConsts[1] = IS_PARAM_DEFINED( info.m_nRimLightScale ) ? params[info.m_nRimLightScale]->GetFloatValue() : kDefaultRimLightScale;
			flConsts[2] = IS_PARAM_DEFINED( info.m_nSpecScale ) ? params[info.m_nSpecScale]->GetFloatValue() : kDefaultSpecScale;
			flConsts[3] = IS_PARAM_DEFINED( info.m_nSpecExp2 ) ? params[info.m_nSpecExp2]->GetFloatValue() : kDefaultSpecExp;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 3, flConsts, 1 );

			flConsts[0] = IS_PARAM_DEFINED( info.m_nSpecScale2 ) ? params[info.m_nSpecScale2]->GetFloatValue() : kDefaultSpecScale;
			flConsts[1] = IS_PARAM_DEFINED( info.m_nFresnelBumpStrength ) ? params[info.m_nFresnelBumpStrength]->GetFloatValue() : kDefaultFresnelBumpStrength;
			flConsts[2] = IS_PARAM_DEFINED( info.m_nDiffuseSoftNormal ) ? params[info.m_nDiffuseSoftNormal]->GetFloatValue() : kDefaultDiffuseSoftNormal;
			flConsts[3] = IS_PARAM_DEFINED( info.m_nInteriorAmbientScale ) ? params[info.m_nInteriorAmbientScale]->GetFloatValue() : kDefaultInteriorAmbientScale;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 10, flConsts, 1 );

			// Depth alpha [ TODO: support fog ]
			bool bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha() && !bAlphaBlend;
			if ( IS_PARAM_DEFINED( info.m_nSpecFresnel ) )
				params[info.m_nSpecFresnel]->GetVecValue( flConsts, 3 );
			else
				memcpy( flConsts, kDefaultSpecFresnel, sizeof( kDefaultSpecFresnel ) );
			flConsts[3] = bWriteDepthToAlpha ? 1.0f : 0.0f;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 12, flConsts, 1 );

			if ( IS_PARAM_DEFINED( info.m_nPhongColorTint ) )
				params[info.m_nPhongColorTint]->GetVecValue( flConsts, 3 );
			else
				memcpy( flConsts, kDefaultPhongColorTint, sizeof( kDefaultPhongColorTint ) );
			flConsts[3] = IS_PARAM_DEFINED( info.m_nInteriorBackLightScale ) ? params[info.m_nInteriorBackLightScale]->GetFloatValue() : kDefaultInteriorBackLightScale;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 19, flConsts, 1 );

			if( bIridescentWarp || bFresnelColorWarp )
			{
				flConsts[0] = ( IS_PARAM_DEFINED( info.m_nIridescenceBoost ) ) ? params[info.m_nIridescenceBoost]->GetFloatValue(): kDefaultIridescenceBoost;
				flConsts[1] = ( IS_PARAM_DEFINED( info.m_nIridescenceExponent ) ) ? params[info.m_nIridescenceExponent]->GetFloatValue(): kDefaultIridescenceExponent;
				flConsts[2] = ( IS_PARAM_DEFINED( info.m_nHueShiftIntensity ) ) ? params[info.m_nHueShiftIntensity]->GetFloatValue(): kDefaultHueShiftIntensity;
				flConsts[3] = ( IS_PARAM_DEFINED( info.m_nHueShiftFresnelExponent ) ) ? params[info.m_nHueShiftFresnelExponent]->GetFloatValue(): kDefaultHueShiftFresnelExponent;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 26, flConsts, 1 );
			}

			if ( IS_PARAM_DEFINED( info.m_nSelfIllumTint ) )
				params[info.m_nSelfIllumTint]->GetVecValue( flConsts, 3 );
			else
				memcpy( flConsts, kDefaultSelfIllumTint, sizeof( kDefaultSelfIllumTint ) );
			float flDiffuseExp = IS_PARAM_DEFINED( info.m_nDiffuseExponent ) ? params[info.m_nDiffuseExponent]->GetFloatValue() : kDefaultDiffuseExponent;
			flConsts[3] = pow( 0.5f, flDiffuseExp );
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 27, flConsts, 1 );

			if ( IS_PARAM_DEFINED( info.m_nInteriorColor ) )
				params[info.m_nInteriorColor]->GetVecValue( flConsts, 3 );
			else
				memcpy( flConsts, kDefaultInteriorColor, sizeof( kDefaultInteriorColor ) );
			flConsts[3] = params[info.m_nInteriorRefractBlur]->GetFloatValue();
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 32, flConsts, 1 );

			if ( IS_PARAM_DEFINED( info.m_nSpecFresnel2 ) )
				params[info.m_nSpecFresnel2]->GetVecValue( flConsts, 3 );
			else
				memcpy( flConsts, kDefaultSpecFresnel2, sizeof( kDefaultSpecFresnel2 ) );
			flConsts[3] = IS_PARAM_DEFINED( info.m_nPhong2Softness ) ? params[info.m_nPhong2Softness]->GetFloatValue() : kDefaultPhong2Softness;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 42, flConsts, 1 );

			flConsts[0] = flDiffuseExp;
			flConsts[1] = IS_PARAM_DEFINED( info.m_nNormal2Softness ) ? params[info.m_nNormal2Softness]->GetFloatValue() : kDefaultNormal2Softness;
			flConsts[2] = IS_PARAM_DEFINED( info.m_nAmbientBoost ) ? params[info.m_nAmbientBoost]->GetFloatValue() : kDefaultAmbientBoost;
			flConsts[3] = IS_PARAM_DEFINED( info.m_nAmbientBoostMaskMode ) ? params[info.m_nAmbientBoostMaskMode]->GetIntValue() : kDefaultAmbientBoostMaskMode;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 43, flConsts, 1 );

			if ( bForwardScatter || bBackScatter )
			{
				flConsts[0] = IS_PARAM_DEFINED( info.m_nForwardScatter ) ? params[info.m_nForwardScatter]->GetFloatValue() : kDefaultForwardScatter;
				flConsts[1] = IS_PARAM_DEFINED( info.m_nBackScatter ) ? params[info.m_nBackScatter]->GetFloatValue() : kDefaultBackScatter;
				flConsts[2] = IS_PARAM_DEFINED( info.m_nSSDepth ) ? params[info.m_nSSDepth]->GetFloatValue() : kDefaultSSDepth;
				flConsts[3] = IS_PARAM_DEFINED( info.m_nSSBentNormalIntensity ) ? params[info.m_nSSBentNormalIntensity]->GetFloatValue() : kDefaultSSBentNormalIntensity;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 44, flConsts, 1 );

				if( IS_PARAM_DEFINED( info.m_nSSColorTint ) )
					params[info.m_nSSColorTint]->GetVecValue( flConsts, 3 );
				else
					memcpy( flConsts, kDefaultSSColorTint, sizeof( kDefaultSSColorTint ) );
				flConsts[3] = IS_PARAM_DEFINED( info.m_nSSTintByAlbedo ) ? params[info.m_nSSTintByAlbedo]->GetFloatValue() : kDefaultSSTintByAlbedo;
				pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 45, flConsts, 1 );
			}

			flConsts[0] = 0.0f;
			flConsts[1] = 0.0f;
			if ( bDetail )
			{
				flConsts[0] = IS_PARAM_DEFINED( info.m_nDetailBlendMode ) ? params[info.m_nDetailBlendMode]->GetIntValue() : kDefaultDetailBlendMode;
				flConsts[1] = IS_PARAM_DEFINED( info.m_nDetailBlendFactor) ? params[info.m_nDetailBlendFactor]->GetFloatValue() : kDefaultDetailBlendFactor;
				flConsts[2] = 0.0f;
			}
			flConsts[3] = IS_PARAM_DEFINED( info.m_nSpecExp ) ? params[info.m_nSpecExp]->GetFloatValue() : kDefaultSpecExp;
			pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( 46, flConsts, 1 );

			pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, BASETEXTURE, -1 );
			pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, info.m_nNormalMap, -1 );
			pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); // Refraction Map

			if ( bTransMatMasks )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, info.m_nTransMatMasksTexture, -1 );
			}

			if ( bColorWarp )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER4, info.m_nColorWarpTexture, -1 );
			}

			if ( bFresnelColorWarp )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER5, info.m_nFresnelColorWarpTexture, -1 );
			}

			if ( bOpacityTexture )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER6, info.m_nOpacityTexture, -1 );
			}

			if ( bEffectMasks )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER10, info.m_nEffectMasksTexture, -1 );
			}

			if ( bIridescentWarp )
			{
				pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, info.m_nIridescentWarpTexture, -1 );
			}

			// VS consts
			flConsts[0] = IS_PARAM_DEFINED( info.m_nUVScale ) ? params[info.m_nUVScale]->GetFloatValue() : kDefaultUVScale;
			pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, flConsts, 1 );

			flConsts[0] = IS_PARAM_DEFINED( info.m_nDetailScale ) ? params[info.m_nDetailScale]->GetFloatValue() : kDefaultDetailScale;
			pContextData->m_SemiStaticCmdsOut.SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, flConsts, 1 );

			if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) )
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nDetailTextureTransform, info.m_nDetailScale );
			else
				pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBaseTextureTransform, info.m_nDetailScale );

			pContextData->m_SemiStaticCmdsOut.End();
			// end semi-static block
		}
	}

	if ( pShaderAPI ) //DYNAMIC_STATE
	{
		CCommandBufferBuilder< CFixedCommandStorageBuffer< 400 > > DynamicCmdsOut;
		DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() );
		///////////////////////////
		// dynamic block
		///////////////////////////

		float camPos[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
		pShaderAPI->GetWorldSpaceCameraPosition( camPos );
		DynamicCmdsOut.SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, camPos );

		if ( bDetail )
		{
			DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, info.m_nDetailTexture, info.m_nDetailFrame );
		}

		float mView[16];
		pShaderAPI->GetMatrix( MATERIAL_VIEW, mView );
		DynamicCmdsOut.SetPixelShaderConstant( 33, mView, 3 );

		DynamicCmdsOut.SetPixelShaderFogParams( 36 );

		LightState_t lightState = { 0, false, false };
		pShaderAPI->GetDX9LightState( &lightState );

		// flashlightfixme: put this in common code.
		bool bFlashlightShadows = false;
		if ( bHasFlashlight )
		{
			Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 );
			VMatrix worldToTexture;
			ITexture *pFlashlightDepthTexture;
			FlashlightState_t state = pShaderAPI->GetFlashlightStateEx( worldToTexture, &pFlashlightDepthTexture );
			DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, state.m_pSpotlightTexture, state.m_nSpotlightTextureFrame );
			bFlashlightShadows = state.m_bEnableShadows;
			
			SetFlashLightColorFromState( state, pShaderAPI, PSREG_FLASHLIGHT_COLOR );

			if( pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows )
			{
				DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, pFlashlightDepthTexture, -1 );
				DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_SHADOW_NOISE_2D );
			}

			float atten[4], pos[4], tweaks[4];

			atten[0] = state.m_fConstantAtten;		// Set the flashlight attenuation factors
			atten[1] = state.m_fLinearAtten;
			atten[2] = state.m_fQuadraticAtten;
			atten[3] = state.m_FarZAtten;
			DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 );

			pos[0] = state.m_vecLightOrigin[0];		// Set the flashlight origin
			pos[1] = state.m_vecLightOrigin[1];
			pos[2] = state.m_vecLightOrigin[2];
			pos[3] = state.m_FarZ;

			DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1 );	// steps on rim boost
			DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4 );

			// Tweaks associated with a given flashlight
			tweaks[0] = ShadowFilterFromState( state );
			tweaks[1] = ShadowAttenFromState( state );
			pShader->HashShadow2DJitter( state.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
			DynamicCmdsOut.SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 );

			// Dimensions of screen, used for screen-space noise map sampling
			float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
			int nWidth, nHeight;
			pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );

			int nTexWidth, nTexHeight;
			pShaderAPI->GetStandardTextureDimensions( &nTexWidth, &nTexHeight, TEXTURE_SHADOW_NOISE_2D );

			vScreenScale[0] = (float) nWidth  / nTexWidth;
			vScreenScale[1] = (float) nHeight / nTexHeight;

			DynamicCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );
		}
		DynamicCmdsOut.End();

		// end dynamic block
		pShaderAPI->ExecuteCommandBuffer( DynamicCmdsOut.Base() );

		// Set Vertex Shader Combos
		DECLARE_DYNAMIC_VERTEX_SHADER( flesh_vs30 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 );
		SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
		SET_DYNAMIC_VERTEX_SHADER( flesh_vs30 );
		
		// Set Pixel Shader Combos
		if( /*g_pHardwareConfig->SupportsPixelShaders_2_b()*/ true )
		{
			DECLARE_DYNAMIC_PIXEL_SHADER( flesh_ps30 );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
			SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
			SET_DYNAMIC_PIXEL_SHADER( flesh_ps30 );
		}
		else
		{
			Assert( !"No ps_3_0" );
		}
	}
	pShader->Draw();
}