void CDAViewRender::SetupRenderTargets() { ITexture *depthOld = materials->FindTexture("_rt_ResolvedFullFrameDepth", TEXTURE_GROUP_RENDER_TARGET); static int flags = TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_RENDERTARGET; if ( depthOld ) flags = depthOld->GetFlags(); int iW, iH; materials->GetBackBufferDimensions( iW, iH ); materials->BeginRenderTargetAllocation(); materials->CreateNamedRenderTargetTextureEx( "_rt_ResolvedFullFrameDepth_DA", iW, iH, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_RGBA16161616F, MATERIAL_RT_DEPTH_NONE, flags, 0); materials->CreateNamedRenderTargetTextureEx( "_rt_ssao_0", iW, iH, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_RGBA16161616F, MATERIAL_RT_DEPTH_NONE, flags, 0); materials->CreateNamedRenderTargetTextureEx( "_rt_ssao_1", iW, iH, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_RGBA16161616F, MATERIAL_RT_DEPTH_NONE, flags, 0); materials->EndRenderTargetAllocation(); }
//----------------------------------------------------------------------------- // Purpose: Initializes all view systems //----------------------------------------------------------------------------- void CViewRender::Init( void ) { memset( &m_PitchDrift, 0, sizeof( m_PitchDrift ) ); m_bDrawOverlay = false; m_pDrawEntities = cvar->FindVar( "r_drawentities" ); m_pDrawBrushModels = cvar->FindVar( "r_drawbrushmodels" ); beams->InitBeams(); tempents->Init(); m_TranslucentSingleColor.Init( "debug/debugtranslucentsinglecolor", TEXTURE_GROUP_OTHER ); m_ModulateSingleColor.Init( "engine/modulatesinglecolor", TEXTURE_GROUP_OTHER ); extern CMaterialReference g_material_WriteZ; g_material_WriteZ.Init( "engine/writez", TEXTURE_GROUP_OTHER ); // FIXME: QAngle angles; engine->GetViewAngles( angles ); AngleVectors( angles, &m_vecLastFacing ); #if defined( REPLAY_ENABLED ) m_pReplayScreenshotTaker = NULL; #endif #if defined( CSTRIKE_DLL ) m_flLastFOV = default_fov.GetFloat(); #endif ITexture *depthOld = materials->FindTexture("_rt_FullFrameDepth", TEXTURE_GROUP_RENDER_TARGET); static int flags = TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_DEPTHRENDERTARGET; if (depthOld) flags = depthOld->GetFlags(); int iW, iH; materials->GetBackBufferDimensions(iW, iH); materials->BeginRenderTargetAllocation(); materials->CreateNamedRenderTargetTextureEx( "_rt_FullFrameDepth_Alt", iW, iH, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_A8, MATERIAL_RT_DEPTH_NONE, flags, 0); materials->EndRenderTargetAllocation(); }
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(); } }
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(); }
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(); }
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 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(); }