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 DrawRefract_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, Refract_DX9_Vars_t &info, VertexCompressionType_t vertexCompression ) { bool bIsModel = IS_FLAG_SET( MATERIAL_VAR_MODEL ); bool bHasEnvmap = params[info.m_nEnvmap]->IsTexture(); bool bRefractTintTexture = params[info.m_nRefractTintTexture]->IsTexture(); bool bFadeOutOnSilhouette = params[info.m_nFadeOutOnSilhouette]->GetIntValue() != 0; int blurAmount = params[info.m_nBlurAmount]->GetIntValue(); bool bMasked = (params[info.m_nMasked]->GetIntValue() != 0); bool bSecondaryNormal = ( ( info.m_nNormalMap2 != -1 ) && ( params[info.m_nNormalMap2]->IsTexture() ) ); bool bColorModulate = ( ( info.m_nVertexColorModulate != -1 ) && ( params[info.m_nVertexColorModulate]->GetIntValue() ) ); bool bWriteZ = params[info.m_nNoWriteZ]->GetIntValue() == 0; if( blurAmount < 0 ) { blurAmount = 0; } else if( blurAmount > MAXBLUR ) { blurAmount = MAXBLUR; } BlendType_t nBlendType = pShader->EvaluateBlendRequirements( BASETEXTURE, true ); bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET(MATERIAL_VAR_ALPHATEST); //dest alpha is free for special use bFullyOpaque &= !bMasked; bool bTranslucentNormal = pShader->TextureIsTranslucent( info.m_nNormalMap, false ); bFullyOpaque &= (! bTranslucentNormal ); NormalDecodeMode_t nNormalDecodeMode = NORMAL_DECODE_NONE; if ( g_pHardwareConfig->SupportsNormalMapCompression() ) { ITexture *pBumpTex = params[info.m_nNormalMap]->GetTextureValue(); if ( pBumpTex ) { nNormalDecodeMode = pBumpTex->GetNormalDecodeMode(); if ( bSecondaryNormal ) // Check encoding of secondary normal if there is one { ITexture *pBumpTex2 = params[info.m_nNormalMap2]->GetTextureValue(); if ( pBumpTex2 && ( pBumpTex2->GetNormalDecodeMode() != nNormalDecodeMode ) ) { DevMsg("Refract: Primary and Secondary normal map compression formats don't match. This is unsupported!\n"); Assert(0); } } } } SHADOW_STATE { pShader->SetInitialShadowState( ); pShaderShadow->EnableDepthWrites( bWriteZ ); // Alpha test: FIXME: shouldn't this be handled in Shader_t::SetInitialShadowState pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) ); // If envmap is not specified, the alpha channel is the translucency // (If envmap *is* specified, alpha channel is the reflection amount) if ( params[info.m_nNormalMap]->IsTexture() && !bHasEnvmap ) { pShader->SetDefaultBlendingShadowState( info.m_nNormalMap, false ); } // source render target that contains the image that we are warping. pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, true ); // normal map pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) { pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Normal map alpha, in the compressed normal case } if ( bSecondaryNormal ) { pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) { pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); // Secondary normal map alpha, in the compressed normal case } } if( bHasEnvmap ) { // envmap pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, true ); } if( bRefractTintTexture ) { // refract tint texture pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, true ); } pShaderShadow->EnableSRGBWrite( true ); unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; int userDataSize = 0; int nTexCoordCount = 1; if( bIsModel ) { userDataSize = 4; } else { flags |= VERTEX_TANGENT_S | VERTEX_TANGENT_T; } if ( bColorModulate ) { flags |= VERTEX_COLOR; } // This shader supports compressed vertices, so OR in that flag: flags |= VERTEX_FORMAT_COMPRESSED; pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, NULL, userDataSize ); DECLARE_STATIC_VERTEX_SHADER( jl_refract_vs20 ); SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bIsModel ); SET_STATIC_VERTEX_SHADER_COMBO( COLORMODULATE, bColorModulate ); SET_STATIC_VERTEX_SHADER( jl_refract_vs20 ); // We have to do this in the shader on R500 or Leopard bool bShaderSRGBConvert = IsOSX() && ( g_pHardwareConfig->FakeSRGBWrite() || !g_pHardwareConfig->CanDoSRGBReadFromRTs() ); if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send OpenGL down the ps2b path { DECLARE_STATIC_PIXEL_SHADER( jl_refract_ps20b ); SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSRGBConvert ); SET_STATIC_PIXEL_SHADER( jl_refract_ps20b ); } else { DECLARE_STATIC_PIXEL_SHADER( jl_refract_ps20 ); SET_STATIC_PIXEL_SHADER_COMBO( BLUR, blurAmount ); SET_STATIC_PIXEL_SHADER_COMBO( FADEOUTONSILHOUETTE, bFadeOutOnSilhouette ); SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap ); SET_STATIC_PIXEL_SHADER_COMBO( REFRACTTINTTEXTURE, bRefractTintTexture ); SET_STATIC_PIXEL_SHADER_COMBO( MASKED, bMasked ); SET_STATIC_PIXEL_SHADER_COMBO( COLORMODULATE, bColorModulate ); SET_STATIC_PIXEL_SHADER_COMBO( SECONDARY_NORMAL, bSecondaryNormal ); SET_STATIC_PIXEL_SHADER_COMBO( NORMAL_DECODE_MODE, (int) nNormalDecodeMode ); SET_STATIC_PIXEL_SHADER( jl_refract_ps20 ); } pShader->DefaultFog(); if( bMasked ) { pShader->EnableAlphaBlending( SHADER_BLEND_ONE_MINUS_SRC_ALPHA, SHADER_BLEND_SRC_ALPHA ); } bool bAlphaWrites = bFullyOpaque || ( params[ info.m_nForceAlphaWrite ]->GetIntValue() != 0 ); pShaderShadow->EnableAlphaWrites( bAlphaWrites ); } DYNAMIC_STATE { pShaderAPI->SetDefaultState(); if ( params[info.m_nBaseTexture]->IsTexture() ) { pShader->BindTexture( SHADER_SAMPLER2, info.m_nBaseTexture, info.m_nFrame ); } else { pShaderAPI->BindStandardTexture( SHADER_SAMPLER2, TEXTURE_FRAME_BUFFER_FULL_TEXTURE_0 ); } if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) { pShader->BindTexture( SHADER_SAMPLER3, SHADER_SAMPLER6, info.m_nNormalMap, info.m_nBumpFrame ); } else { pShader->BindTexture( SHADER_SAMPLER3, info.m_nNormalMap, info.m_nBumpFrame ); } if ( bSecondaryNormal ) { if ( nNormalDecodeMode == NORMAL_DECODE_ATI2N_ALPHA ) { pShader->BindTexture( SHADER_SAMPLER1, SHADER_SAMPLER7, info.m_nNormalMap2, info.m_nBumpFrame2 ); } else { pShader->BindTexture( SHADER_SAMPLER1, info.m_nNormalMap2, info.m_nBumpFrame2 ); } } if( bHasEnvmap ) { pShader->BindTexture( SHADER_SAMPLER4, info.m_nEnvmap, info.m_nEnvmapFrame ); } if( bRefractTintTexture ) { pShader->BindTexture( SHADER_SAMPLER5, info.m_nRefractTintTexture, info.m_nRefractTintTextureFrame ); } DECLARE_DYNAMIC_VERTEX_SHADER( jl_refract_vs20 ); SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, pShaderAPI->GetCurrentNumBones() > 0 ); SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression ); SET_DYNAMIC_VERTEX_SHADER( jl_refract_vs20 ); if ( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // always send Posix down the ps2b path { DECLARE_DYNAMIC_PIXEL_SHADER( jl_refract_ps20b ); SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteZ && bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() ); SET_DYNAMIC_PIXEL_SHADER( jl_refract_ps20b ); } else { DECLARE_DYNAMIC_PIXEL_SHADER( jl_refract_ps20 ); SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); SET_DYNAMIC_PIXEL_SHADER( jl_refract_ps20 ); } pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.m_nBumpTransform ); // 1 & 2 pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.m_nBumpTransform2 ); // 3 & 4 pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS ); float vEyePos_SpecExponent[4]; pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); vEyePos_SpecExponent[3] = 0.0f; pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1 ); pShader->SetPixelShaderConstantGammaToLinear( 0, info.m_nEnvmapTint ); pShader->SetPixelShaderConstantGammaToLinear( 1, info.m_nRefractTint ); pShader->SetPixelShaderConstant( 2, info.m_nEnvmapContrast ); pShader->SetPixelShaderConstant( 3, info.m_nEnvmapSaturation ); float c5[4] = { params[info.m_nRefractAmount]->GetFloatValue(), params[info.m_nRefractAmount]->GetFloatValue(), 0.0f, 0.0f }; // Time % 1000 c5[3] = pShaderAPI->CurrentTime(); c5[3] -= (float)( (int)( c5[3] / 1000.0f ) ) * 1000.0f; pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); float cVs3[4] = { c5[3], 0.0f, 0.0f, 0.0f }; pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, cVs3, 1 ); } pShader->Draw(); }