diff options
Diffstat (limited to 'mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp')
| -rw-r--r-- | mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp new file mode 100644 index 00000000..8464f94f --- /dev/null +++ b/mp/src/materialsystem/stdshaders/lightmappedgeneric_dx8.cpp @@ -0,0 +1,802 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Lightmap only shader +// +// $Header: $ +// $NoKeywords: $ +//=============================================================================// + +#include "BaseVSShader.h" + + +#include "lightmappedgeneric_vs11.inc" +#include "unlitgeneric_vs11.inc" +#include "worldvertextransition_seamless.inc" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); + +DEFINE_FALLBACK_SHADER( LightmappedGeneric, LightmappedGeneric_DX8 ) + +BEGIN_VS_SHADER( LightmappedGeneric_DX8, + "Help for LightmappedGeneric_DX8" ) + + BEGIN_SHADER_PARAMS + SHADER_PARAM( ALBEDO, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "albedo (Base texture with no baked lighting)" ) + SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" ) + SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" ) + SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" ) + SHADER_PARAM( DETAILBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1", "amount of detail texture to apply" ) + SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" ) + SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" ) + SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" ) + SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" ) + SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" ) + SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "models/shadertest/shader1_normal", "bump map" ) + SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" ) + SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" ) + SHADER_PARAM( ENVMAPCONTRAST, SHADER_PARAM_TYPE_FLOAT, "0.0", "contrast 0 == normal 1 == color*color" ) + SHADER_PARAM( ENVMAPSATURATION, SHADER_PARAM_TYPE_FLOAT, "1.0", "saturation 0 == greyscale 1 == normal" ) + SHADER_PARAM( FRESNELREFLECTION, SHADER_PARAM_TYPE_FLOAT, "1.0", "1.0 == mirror, 0.0 == water" ) + SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_INTEGER, "90", "Do specular pass only on dxlevel or higher (ie.80, 81, 90)" ) + SHADER_PARAM( NODIFFUSEBUMPLIGHTING, SHADER_PARAM_TYPE_BOOL, "0", "0 == Use diffuse bump lighting, 1 = No diffuse bump lighting" ) + SHADER_PARAM( FORCEBUMP, SHADER_PARAM_TYPE_BOOL, "0", "0 == Do bumpmapping if the card says it can handle it. 1 == Always do bumpmapping." ) + SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" ) + SHADER_PARAM( SSBUMP, SHADER_PARAM_TYPE_INTEGER, "0", "whether or not to use alternate bumpmap format with height" ) + SHADER_PARAM( SEAMLESS_SCALE, SHADER_PARAM_TYPE_FLOAT, "0", "Scale factor for 'seamless' texture mapping. 0 means to use ordinary mapping" ) + END_SHADER_PARAMS + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + return g_pConfig->UseBumpmapping() && params[BUMPMAP]->IsDefined(); + } + + // Set up anything that is necessary to make decisions in SHADER_FALLBACK. + SHADER_INIT_PARAMS() + { + // FLASHLIGHTFIXME + params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" ); + + // Write over $basetexture with $albedo if we are going to be using diffuse normal mapping. + if( ShouldUseBumpmapping( params ) && params[ALBEDO]->IsDefined() && + params[BASETEXTURE]->IsDefined() && + !( params[NODIFFUSEBUMPLIGHTING]->IsDefined() && params[NODIFFUSEBUMPLIGHTING]->GetIntValue() ) ) + { + params[BASETEXTURE]->SetStringValue( params[ALBEDO]->GetStringValue() ); + } + + if( IsUsingGraphics() && params[ENVMAP]->IsDefined() && !CanUseEditorMaterials() ) + { + if( stricmp( params[ENVMAP]->GetStringValue(), "env_cubemap" ) == 0 ) + { + Warning( "env_cubemap used on world geometry without rebuilding map. . ignoring: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if( !params[ENVMAPMASKSCALE]->IsDefined() ) + { + params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPTINT]->IsDefined() ) + { + params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[SELFILLUMTINT]->IsDefined() ) + { + params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f ); + } + + if( !params[DETAILSCALE]->IsDefined() ) + { + params[DETAILSCALE]->SetFloatValue( 4.0f ); + } + + if( !params[DETAILBLENDFACTOR]->IsDefined() ) + { + params[DETAILBLENDFACTOR]->SetFloatValue( 1.0f ); + } + + if( !params[FRESNELREFLECTION]->IsDefined() ) + { + params[FRESNELREFLECTION]->SetFloatValue( 1.0f ); + } + + if( !params[ENVMAPMASKFRAME]->IsDefined() ) + { + params[ENVMAPMASKFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPFRAME]->IsDefined() ) + { + params[ENVMAPFRAME]->SetIntValue( 0 ); + } + + if( !params[BUMPFRAME]->IsDefined() ) + { + params[BUMPFRAME]->SetIntValue( 0 ); + } + + if( !params[ENVMAPCONTRAST]->IsDefined() ) + { + params[ENVMAPCONTRAST]->SetFloatValue( 0.0f ); + } + + if( !params[ENVMAPSATURATION]->IsDefined() ) + { + params[ENVMAPSATURATION]->SetFloatValue( 1.0f ); + } + + if( !params[ALPHATESTREFERENCE]->IsDefined() ) + { + params[ALPHATESTREFERENCE]->SetFloatValue( 0.0f ); + } + + // No texture means no self-illum or env mask in base alpha + if ( !params[BASETEXTURE]->IsDefined() ) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + + // If in decal mode, no debug override... + if (IS_FLAG_SET(MATERIAL_VAR_DECAL)) + { + SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + } + + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_LIGHTMAP ); + if( ShouldUseBumpmapping( params ) && (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0) ) + { + SET_FLAGS2( MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ); + } + + // Get rid of the envmap if it's optional for this dx level. + if( params[ENVMAPOPTIONAL]->IsDefined() && (params[ENVMAPOPTIONAL]->GetIntValue() > g_pHardwareConfig->GetDXSupportLevel()) ) + { + params[ENVMAP]->SetUndefined(); + } + + // If mat_specular 0, then get rid of envmap + if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + + if( params[SEAMLESS_SCALE]->IsDefined() && params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + if( params[BUMPMAP]->IsDefined() ) + { + Warning( "Can't use $bumpmap with $seamless_scale for lightmappedgeneric_dx8. Implicitly disabling $bumpmap: %s\n", pMaterialName ); + params[BUMPMAP]->SetUndefined(); + } + if( params[ENVMAP]->IsDefined() ) + { + Warning( "Can't use $envmap with $seamless_scale for lightmappedgeneric_dx8. Implicitly disabling $envmap: %s\n", pMaterialName ); + params[ENVMAP]->SetUndefined(); + } + } + + if ( !params[SEAMLESS_SCALE]->IsDefined() ) + { + // zero means don't do seamless mapping. + params[SEAMLESS_SCALE]->SetFloatValue( 0.0f ); + } + + // Get rid of envmap if we aren't using bumpmapping + // *and* we have normalmapalphaenvmapmask *and* we don't have envmapmask elsewhere + if ( params[ENVMAP]->IsDefined() && params[BUMPMAP]->IsDefined() && IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) && !ShouldUseBumpmapping( params ) ) + { + if ( !IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) && !params[ENVMAPMASK]->IsDefined() ) + { + params[ENVMAP]->SetUndefined(); + } + } + } + + SHADER_FALLBACK + { + if ( IsPC() && g_pHardwareConfig->GetDXSupportLevel() < 80) + return "LightmappedGeneric_DX6"; + + if ( IsPC() && g_pHardwareConfig->PreferReducedFillrate() ) + return "LightmappedGeneric_NoBump_DX8"; + + return 0; + } + + SHADER_INIT + { + LoadTexture( FLASHLIGHTTEXTURE ); + + if( ShouldUseBumpmapping( params ) ) + { + LoadBumpMap( BUMPMAP ); + } + + if (params[BASETEXTURE]->IsDefined()) + { + LoadTexture( BASETEXTURE ); + + if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent()) + { + CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM ); + CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK ); + } + } + + if (params[DETAIL]->IsDefined()) + { + LoadTexture( DETAIL ); + } + + // Don't alpha test if the alpha channel is used for other purposes + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST ); + + if (params[ENVMAP]->IsDefined()) + { + if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + LoadCubeMap( ENVMAP ); + else + LoadTexture( ENVMAP ); + + if( !g_pHardwareConfig->SupportsCubeMaps() ) + { + SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE ); + } + + if (params[ENVMAPMASK]->IsDefined()) + LoadTexture( ENVMAPMASK ); + } + + if( ShouldUseBumpmapping( params ) ) + { + SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES ); + } + } + +#ifndef USE_HLSL_PIXEL_SHADERS + inline const char *GetPixelShaderName( IMaterialVar** params, bool bBumpedEnvMap ) + { + static char const* s_pPixelShaders[] = + { + // Unmasked + "LightmappedGeneric_EnvMapV2", + "LightmappedGeneric_SelfIlluminatedEnvMapV2", + + "LightmappedGeneric_BaseAlphaMaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedEnvMapV2", + + // Env map mask + "LightmappedGeneric_MaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2", + + "LightmappedGeneric_MaskedEnvMapV2", + "LightmappedGeneric_SelfIlluminatedMaskedEnvMapV2", + }; + + if (!params[BASETEXTURE]->IsTexture()) + { + if (params[ENVMAP]->IsTexture() && !bBumpedEnvMap ) + { + if (!params[ENVMAPMASK]->IsDefined() ) + { + return "LightmappedGeneric_EnvmapNoTexture"; + } + else + { + return "LightmappedGeneric_MaskedEnvmapNoTexture"; + } + } + else + { + return "LightmappedGeneric_NoTexture"; + } + } + else + { + if (params[ENVMAP]->IsTexture() && !bBumpedEnvMap ) + { + int pshIndex = 0; + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + pshIndex |= 0x1; + if (IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + pshIndex |= 0x2; + if (params[ENVMAPMASK]->IsTexture()) + pshIndex |= 0x4; + return s_pPixelShaders[pshIndex]; + } + else + { + if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM)) + return "LightmappedGeneric_SelfIlluminated"; + else + return "LightmappedGeneric"; + } + } + } +#endif + + void DrawUnbumpedUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + bool hasEnvmap = params[ENVMAP]->IsTexture() && !bBumpedEnvMap; + bool hasBaseTexture = params[BASETEXTURE]->IsTexture(); + bool hasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ); + bool hasEnvmapCameraSpace = IS_FLAG_SET( MATERIAL_VAR_ENVMAPCAMERASPACE ); + bool hasEnvmapSphere = IS_FLAG_SET( MATERIAL_VAR_ENVMAPSPHERE ); + + if ( hasEnvmap || hasBaseTexture || hasVertexColor || !bBumpedEnvMap ) + { + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + if ( params[ALPHATESTREFERENCE]->GetFloatValue() > 0.0f ) + { + pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[ALPHATESTREFERENCE]->GetFloatValue() ); + } + + // Base texture on stage 0 + if (params[BASETEXTURE]->IsTexture()) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + } + + // Lightmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + int fmt = VERTEX_POSITION; + + if ( hasEnvmap ) + { + fmt |= VERTEX_NORMAL; + + // envmap on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // envmapmask on stage 3 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + } + + if (params[BASETEXTURE]->IsTexture() || bBumpedEnvMap) + { + SetDefaultBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetDefaultBlendingShadowState( ENVMAPMASK, false ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + { + fmt |= VERTEX_COLOR; + } + + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( hasEnvmap ); + vshIndex.SetENVMAPCAMERASPACE( hasEnvmap && hasEnvmapCameraSpace ); + vshIndex.SetENVMAPSPHERE( hasEnvmap && hasEnvmapSphere ); + vshIndex.SetVERTEXCOLOR( hasVertexColor ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetPixelShaderName( params, bBumpedEnvMap ); + pShaderShadow->SetPixelShader( pshName ); + DefaultFog(); + } + DYNAMIC_STATE + { + if (hasBaseTexture) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + if ( hasEnvmap ) + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) ) + { + if (params[ENVMAPMASK]->IsTexture() ) + BindTexture( SHADER_SAMPLER3, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || + IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + SetEnvMapTintPixelShaderDynamicState( 2, ENVMAPTINT, -1 ); + } + + if ( !hasEnvmap || hasBaseTexture || hasVertexColor ) + { + SetModulationVertexShaderDynamicState(); + } + EnablePixelShaderOverbright( 0, true, true ); + SetPixelShaderConstant( 1, SELFILLUMTINT ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + if ( bBumpedEnvMap ) + { + DrawWorldBumpedSpecularLighting( + BUMPMAP, ENVMAP, BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + hasEnvmap || hasBaseTexture || hasVertexColor ); + } + } + + void DrawDetailNoEnvmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool doSelfIllum ) + { + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); + + // Base texture on stage 0 + if (params[BASETEXTURE]->IsTexture()) + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + + // Lightmap on stage 1 + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + + // Detail on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + int fmt = VERTEX_POSITION; + + SetDefaultBlendingShadowState( BASETEXTURE, true ); + + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR)) + fmt |= VERTEX_COLOR; + + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( true ); + vshIndex.SetENVMAP( false ); + vshIndex.SetENVMAPCAMERASPACE( false ); + vshIndex.SetENVMAPSPHERE( false ); + vshIndex.SetVERTEXCOLOR( IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR ) ); + pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + if (!params[BASETEXTURE]->IsTexture()) + { + pShaderShadow->SetPixelShader("LightmappedGeneric_DetailNoTexture"); + } + else + { + if (!IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || (!doSelfIllum)) + { + pShaderShadow->SetPixelShader("LightmappedGeneric_Detail"); + } + else + { + pShaderShadow->SetPixelShader("LightmappedGeneric_DetailSelfIlluminated"); + } + } + DefaultFog(); + } + DYNAMIC_STATE + { + if (params[BASETEXTURE]->IsTexture()) + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BASETEXTURETRANSFORM ); + } + + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_LIGHTMAP ); + + BindTexture( SHADER_SAMPLER2, DETAIL, FRAME ); + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, BASETEXTURETRANSFORM, DETAILSCALE ); + + SetModulationVertexShaderDynamicState(); + EnablePixelShaderOverbright( 0, true, true ); + + if (doSelfIllum) + { + SetPixelShaderConstant( 1, SELFILLUMTINT ); + } + float c2[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + c2[0] = c2[1] = c2[2] = c2[3] = params[DETAILBLENDFACTOR]->GetFloatValue(); + pShaderAPI->SetPixelShaderConstant( 2, c2, 1 ); + + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + inline const char *GetAdditiveEnvmapPixelShaderName( bool usingMask, + bool usingBaseTexture, bool usingBaseAlphaEnvmapMask ) + { + static char const* s_pPixelShaders[] = + { + "LightmappedGeneric_AddEnvmapNoTexture", + "LightmappedGeneric_AddEnvmapMaskNoTexture", + }; + + if ( !usingMask && usingBaseTexture && usingBaseAlphaEnvmapMask ) + return "LightmappedGeneric_AddBaseAlphaMaskedEnvMap"; + + int pshIndex = 0; + if (usingMask) + pshIndex |= 0x1; + return s_pPixelShaders[pshIndex]; + } + + void DrawAdditiveEnvmap( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + bool usingBaseTexture = params[BASETEXTURE]->IsTexture(); + bool usingMask = params[ENVMAPMASK]->IsTexture(); + bool usingBaseAlphaEnvmapMask = IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK); + SHADOW_STATE + { + // Alpha test + pShaderShadow->EnableAlphaTest( false ); + + pShaderShadow->EnableTexture( SHADER_SAMPLER0, false ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, false ); + + // envmap on stage 2 + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // envmapmask on stage 3 + if (params[ENVMAPMASK]->IsTexture() || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK ) ) + { + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + } + + if (params[BASETEXTURE]->IsTexture()) + { + SetAdditiveBlendingShadowState( BASETEXTURE, true ); + } + else + { + SetAdditiveBlendingShadowState( ENVMAPMASK, false ); + } + + int fmt = VERTEX_POSITION | VERTEX_NORMAL; + + pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 ); + + // Compute the vertex shader index. + lightmappedgeneric_vs11_Static_Index vshIndex; + vshIndex.SetDETAIL( false ); + vshIndex.SetENVMAP( true ); + vshIndex.SetENVMAPCAMERASPACE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE) ); + vshIndex.SetENVMAPSPHERE( IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ); + vshIndex.SetVERTEXCOLOR( false ); + s_pShaderShadow->SetVertexShader( "LightmappedGeneric_vs11", vshIndex.GetIndex() ); + + const char *pshName = GetAdditiveEnvmapPixelShaderName( usingMask, + usingBaseTexture, usingBaseAlphaEnvmapMask ); + pShaderShadow->SetPixelShader( pshName ); + FogToBlack(); + } + DYNAMIC_STATE + { + BindTexture( SHADER_SAMPLER2, ENVMAP, ENVMAPFRAME ); + + if (usingMask || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK)) + { + if (usingMask) + BindTexture( SHADER_SAMPLER3, ENVMAPMASK, ENVMAPMASKFRAME ); + else + BindTexture( SHADER_SAMPLER3, BASETEXTURE, FRAME ); + + SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, BASETEXTURETRANSFORM, ENVMAPMASKSCALE ); + } + + SetPixelShaderConstant( 2, ENVMAPTINT ); + + if (IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) || IS_FLAG_SET(MATERIAL_VAR_ENVMAPCAMERASPACE)) + { + LoadViewMatrixIntoVertexShaderConstant( VERTEX_SHADER_VIEWMODEL ); + } + + SetModulationVertexShaderDynamicState(); + + // Compute the vertex shader index. + lightmappedgeneric_vs11_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( s_pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + s_pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + void DrawDetailMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + // Mode 1 : + // Pass 1 : B * L * D + Self Illum + // Pass 2 : Add E * M + + // Draw the detail w/ no envmap + DrawDetailNoEnvmap( params, pShaderAPI, pShaderShadow, true ); + + if ( !bBumpedEnvMap ) + { + DrawAdditiveEnvmap( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawWorldBumpedSpecularLighting( + BUMPMAP, ENVMAP, BUMPFRAME, ENVMAPFRAME, + ENVMAPTINT, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, + BUMPTRANSFORM, FRESNELREFLECTION, + true ); + } + } + + void DrawDetailUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, bool bBumpedEnvMap ) + { + // We don't have enough textures; gotta do this in two passes if there's envmapping + if (!params[ENVMAP]->IsTexture()) + { + DrawDetailNoEnvmap( params, pShaderAPI, pShaderShadow, IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) ); + } + else + { + if (!params[BASETEXTURE]->IsTexture()) + { + // If there's an envmap but no base texture, ignore detail + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + else + { + DrawDetailMode1( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + } + + void DrawUnbumpedSeamlessUsingVertexShader( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow ) + { + // This is the seamless_scale version, which doesn't use $detail or $bumpmap + SHADOW_STATE + { + // three copies of the base texture for seamless blending + pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); + pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); + + // lightmap + pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); + + int fmt = VERTEX_POSITION; + pShaderShadow->VertexShaderVertexFormat( fmt, 2, 0, 0 ); + + worldvertextransition_seamless_Static_Index vshIndex; + pShaderShadow->SetVertexShader( "WorldVertexTransition_Seamless", vshIndex.GetIndex() ); + + int pshIndex = 0; + pShaderShadow->SetPixelShader( "WorldVertexTransition_Seamless", pshIndex ); + + FogToFogColor(); + } + DYNAMIC_STATE + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE ); + // Texture 0..2 + if( bLightingOnly ) + { + pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER1, TEXTURE_GREY ); + pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_GREY ); + } + else + { + BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER1, BASETEXTURE, FRAME ); + BindTexture( SHADER_SAMPLER2, BASETEXTURE, FRAME ); + } + + // Texture 3 = lightmap + pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LIGHTMAP ); + + EnablePixelShaderOverbright( 0, true, true ); + + float fSeamlessScale = params[SEAMLESS_SCALE]->GetFloatValue(); + float map_scale[4]= { fSeamlessScale, fSeamlessScale, fSeamlessScale, fSeamlessScale }; + pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, map_scale ); + + worldvertextransition_seamless_Dynamic_Index vshIndex; + vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ); + pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() ); + } + Draw(); + } + + SHADER_DRAW + { + bool hasFlashlight = UsingFlashlight( params ); + bool bBump = ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture() && + (params[NODIFFUSEBUMPLIGHTING]->GetIntValue() == 0); + bool bSSBump = bBump && ( params[SSBUMP]->GetIntValue() != 0 ); + + if( hasFlashlight ) + { + DrawFlashlight_dx80( params, pShaderAPI, pShaderShadow, bBump, BUMPMAP, BUMPFRAME, BUMPTRANSFORM, + FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME, true, false, 0, -1, -1 ); + } + else if( bBump ) + { + DrawWorldBumpedUsingVertexShader( + BASETEXTURE, BASETEXTURETRANSFORM, + BUMPMAP, BUMPFRAME, BUMPTRANSFORM, ENVMAPMASK, ENVMAPMASKFRAME, ENVMAP, + ENVMAPFRAME, ENVMAPTINT, COLOR, ALPHA, ENVMAPCONTRAST, ENVMAPSATURATION, FRAME, FRESNELREFLECTION, + false, -1, -1, -1, bSSBump ); + } + else + { + bool bBumpedEnvMap = ShouldUseBumpmapping( params ) && params[BUMPMAP]->IsTexture() && params[ENVMAP]->IsTexture(); + if (!params[DETAIL]->IsTexture()) + { + if( params[SEAMLESS_SCALE]->GetFloatValue() != 0.0f ) + { + DrawUnbumpedSeamlessUsingVertexShader( params, pShaderAPI, pShaderShadow ); + } + else + { + DrawUnbumpedUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + else + { + DrawDetailUsingVertexShader( params, pShaderAPI, pShaderShadow, bBumpedEnvMap ); + } + } + } +END_SHADER + + +//----------------------------------------------------------------------------- +// Version that doesn't do bumpmapping +//----------------------------------------------------------------------------- +BEGIN_INHERITED_SHADER( LightmappedGeneric_NoBump_DX8, LightmappedGeneric_DX8, + "Help for LightmappedGeneric_NoBump_DX8" ) + + SHADER_FALLBACK + { + if (g_pHardwareConfig->GetDXSupportLevel() < 80) + return "LightmappedGeneric_DX6"; + + return 0; + } + + virtual bool ShouldUseBumpmapping( IMaterialVar **params ) + { + if ( !g_pConfig->UseBumpmapping() ) + return false; + + if ( !params[BUMPMAP]->IsDefined() ) + return false; + + return ( params[FORCEBUMP]->GetIntValue() != 0 ); + } + +END_INHERITED_SHADER |