mirror of
https://github.com/ValveSoftware/source-sdk-2013.git
synced 2024-12-31 01:05:33 +03:00
Glow Outlines: Improved performance and fixed "glow when occluded" and "glow when unoccluded" functionality.
This commit is contained in:
parent
0d8dceea43
commit
d43a67a2ff
5
mp/game/mod_hl2mp/materials/debug/debugfbtexture1.vmt
Normal file
5
mp/game/mod_hl2mp/materials/debug/debugfbtexture1.vmt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"unlitgeneric"
|
||||||
|
{
|
||||||
|
"$basetexture" "_rt_FullFrameFB1"
|
||||||
|
"%noToolTexture" 1
|
||||||
|
}
|
@ -17,8 +17,27 @@
|
|||||||
|
|
||||||
#ifdef GLOWS_ENABLE
|
#ifdef GLOWS_ENABLE
|
||||||
|
|
||||||
|
// If you've added IMatRenderContext::OverrideDepthFunc (see ::DrawGlowOccluded below),
|
||||||
|
// then you can enable this and have single-pass glows for "glow when occluded" outlines.
|
||||||
|
// ***PLEASE*** increment MATERIAL_SYSTEM_INTERFACE_VERSION when you add this!
|
||||||
|
#define ADDED_OVERRIDE_DEPTH_FUNC 0
|
||||||
|
|
||||||
|
// If you've fixed IMatRenderContext::CopyTextureToRenderTargetEx
|
||||||
|
// (see CGlowObjectManager::RenderGlowModels below), then you can enable this and have
|
||||||
|
// code that's a bit cleaner. Also, then you won't have to ship debug/debugfbtexture1.
|
||||||
|
#define FIXED_COPY_TEXTURE_TO_RENDER_TARGET 0
|
||||||
|
|
||||||
ConVar glow_outline_effect_enable( "glow_outline_effect_enable", "1", FCVAR_ARCHIVE, "Enable entity outline glow effects." );
|
ConVar glow_outline_effect_enable( "glow_outline_effect_enable", "1", FCVAR_ARCHIVE, "Enable entity outline glow effects." );
|
||||||
ConVar glow_outline_effect_width( "glow_outline_width", "10.0f", FCVAR_CHEAT, "Width of glow outline effect in screen space." );
|
|
||||||
|
// This doesn't actually do anything.
|
||||||
|
ConVar glow_outline_effect_width( "glow_outline_width", "10.0f", FCVAR_CHEAT | FCVAR_UNREGISTERED, "Width of glow outline effect in screen space." );
|
||||||
|
|
||||||
|
// Not really necessary, but it's two different styles. I prefer style 0, but style 1 "closes off" partially occluded glows.
|
||||||
|
static ConVar glow_outline_effect_stencil_mode("glow_outline_effect_stencil_mode", "0", 0,
|
||||||
|
"\n\t0: Draws partially occluded glows in a more 3d-esque way, making them look more like they're actually surrounding the model."
|
||||||
|
"\n\t1: Draws partially occluded glows in a more 2d-esque way, which can make them more visible."
|
||||||
|
"\n\tSee https://i.imgur.com/OJQkXei.gif",
|
||||||
|
true, 0, true, 1);
|
||||||
|
|
||||||
extern bool g_bDumpRenderTargets; // in viewpostprocess.cpp
|
extern bool g_bDumpRenderTargets; // in viewpostprocess.cpp
|
||||||
|
|
||||||
@ -46,14 +65,18 @@ struct ShaderStencilState_t
|
|||||||
|
|
||||||
void SetStencilState( CMatRenderContextPtr &pRenderContext )
|
void SetStencilState( CMatRenderContextPtr &pRenderContext )
|
||||||
{
|
{
|
||||||
pRenderContext->SetStencilEnable( m_bEnable );
|
pRenderContext->SetStencilEnable(m_bEnable);
|
||||||
pRenderContext->SetStencilFailOperation( m_FailOp );
|
|
||||||
pRenderContext->SetStencilZFailOperation( m_ZFailOp );
|
if (m_bEnable)
|
||||||
pRenderContext->SetStencilPassOperation( m_PassOp );
|
{
|
||||||
pRenderContext->SetStencilCompareFunction( m_CompareFunc );
|
pRenderContext->SetStencilFailOperation(m_FailOp);
|
||||||
pRenderContext->SetStencilReferenceValue( m_nReferenceValue );
|
pRenderContext->SetStencilZFailOperation(m_ZFailOp);
|
||||||
pRenderContext->SetStencilTestMask( m_nTestMask );
|
pRenderContext->SetStencilPassOperation(m_PassOp);
|
||||||
pRenderContext->SetStencilWriteMask( m_nWriteMask );
|
pRenderContext->SetStencilCompareFunction(m_CompareFunc);
|
||||||
|
pRenderContext->SetStencilReferenceValue(m_nReferenceValue);
|
||||||
|
pRenderContext->SetStencilTestMask(m_nTestMask);
|
||||||
|
pRenderContext->SetStencilWriteMask(m_nWriteMask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,240 +97,294 @@ void CGlowObjectManager::RenderGlowEffects( const CViewSetup *pSetup, int nSplit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetRenderTargetAndViewPort( ITexture *rt, int w, int h )
|
void CGlowObjectManager::DrawGlowAlways(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext)
|
||||||
{
|
{
|
||||||
CMatRenderContextPtr pRenderContext( materials );
|
|
||||||
pRenderContext->SetRenderTarget(rt);
|
|
||||||
pRenderContext->Viewport(0,0,w,h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGlowObjectManager::RenderGlowModels( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext )
|
|
||||||
{
|
|
||||||
//==========================================================================================//
|
|
||||||
// This renders solid pixels with the correct coloring for each object that needs the glow. //
|
|
||||||
// After this function returns, this image will then be blurred and added into the frame //
|
|
||||||
// buffer with the objects stenciled out. //
|
|
||||||
//==========================================================================================//
|
|
||||||
pRenderContext->PushRenderTargetAndViewport();
|
|
||||||
|
|
||||||
// Save modulation color and blend
|
|
||||||
Vector vOrigColor;
|
|
||||||
render->GetColorModulation( vOrigColor.Base() );
|
|
||||||
float flOrigBlend = render->GetBlend();
|
|
||||||
|
|
||||||
// Get pointer to FullFrameFB
|
|
||||||
ITexture *pRtFullFrame = NULL;
|
|
||||||
pRtFullFrame = materials->FindTexture( FULL_FRAME_TEXTURE, TEXTURE_GROUP_RENDER_TARGET );
|
|
||||||
|
|
||||||
SetRenderTargetAndViewPort( pRtFullFrame, pSetup->width, pSetup->height );
|
|
||||||
|
|
||||||
pRenderContext->ClearColor3ub( 0, 0, 0 );
|
|
||||||
pRenderContext->ClearBuffers( true, false, false );
|
|
||||||
|
|
||||||
// Set override material for glow color
|
|
||||||
IMaterial *pMatGlowColor = NULL;
|
|
||||||
|
|
||||||
pMatGlowColor = materials->FindMaterial( "dev/glow_color", TEXTURE_GROUP_OTHER, true );
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( pMatGlowColor );
|
|
||||||
|
|
||||||
ShaderStencilState_t stencilState;
|
ShaderStencilState_t stencilState;
|
||||||
stencilState.m_bEnable = false;
|
stencilState.m_bEnable = true;
|
||||||
stencilState.m_nReferenceValue = 0;
|
stencilState.m_nReferenceValue = 1;
|
||||||
stencilState.m_nTestMask = 0xFF;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
render->SetBlend(1);
|
||||||
//==================//
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
// Draw the objects //
|
|
||||||
//==================//
|
|
||||||
for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i )
|
|
||||||
{
|
{
|
||||||
if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) )
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || !current.m_bRenderWhenUnoccluded)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
render->SetBlend( m_GlowObjectDefinitions[i].m_flGlowAlpha );
|
Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
Vector vGlowColor = m_GlowObjectDefinitions[i].m_vGlowColor * m_GlowObjectDefinitions[i].m_flGlowAlpha;
|
render->SetColorModulation(vGlowColor.Base()); // This only sets rgb, not alpha
|
||||||
render->SetColorModulation( &vGlowColor[0] ); // This only sets rgb, not alpha
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
current.DrawModel();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( g_bDumpRenderTargets )
|
void CGlowObjectManager::DrawGlowOccluded(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext)
|
||||||
|
{
|
||||||
|
#if ADDED_OVERRIDE_DEPTH_FUNC // Enable this when the TF2 team has added IMatRenderContext::OverrideDepthFunc or similar.
|
||||||
|
ShaderStencilState_t stencilState;
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 1;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
|
stencilState.m_PassOp = glow_outline_effect_stencil_mode.GetBool() ? STENCILOPERATION_KEEP : STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
|
|
||||||
|
// Not implemented, we need this feature to be able to do this in 1 pass. Otherwise,
|
||||||
|
// we'd have to do 2 passes, 1st to mark on the stencil where the depth test failed,
|
||||||
|
// 2nd to actually utilize that information and draw color there.
|
||||||
|
pRenderContext->OverrideDepthFunc(true, SHADER_DEPTHFUNC_NEARER);
|
||||||
|
|
||||||
|
for (int i = 0; i < glowObjectDefinitions.Count(); i++)
|
||||||
{
|
{
|
||||||
DumpTGAofRenderTarget( pSetup->width, pSetup->height, "GlowModels" );
|
auto& current = glowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
render->SetBlend(current.m_flGlowAlpha);
|
||||||
|
Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
|
render->SetColorModulation(&vGlowColor[0]); // This only sets rgb, not alpha
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( NULL );
|
pRenderContext->OverrideDepthFunc(false, SHADER_DEPTHFUNC_NEAREROREQUAL)
|
||||||
render->SetColorModulation( vOrigColor.Base() );
|
#else // 2-pass as a proof of concept so I can take a nice screenshot.
|
||||||
render->SetBlend( flOrigBlend );
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
|
|
||||||
ShaderStencilState_t stencilStateDisable;
|
|
||||||
stencilStateDisable.m_bEnable = false;
|
|
||||||
stencilStateDisable.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
pRenderContext->PopRenderTargetAndViewport();
|
ShaderStencilState_t stencilState;
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 2;
|
||||||
|
stencilState.m_nWriteMask = 2;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
// Draw depthtest-passing pixels to the stencil buffer
|
||||||
|
{
|
||||||
|
render->SetBlend(0);
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(true, false);
|
||||||
|
pRenderContext->OverrideColorWriteEnable(true, false);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
|
{
|
||||||
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(false, true);
|
||||||
|
pRenderContext->OverrideColorWriteEnable(false, true);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 3;
|
||||||
|
stencilState.m_nTestMask = 2;
|
||||||
|
stencilState.m_nWriteMask = 1;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_NOTEQUAL;
|
||||||
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = glow_outline_effect_stencil_mode.GetBool() ? STENCILOPERATION_KEEP : STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
// Draw color+alpha, stenciling out pixels from the first pass
|
||||||
|
render->SetBlend(1);
|
||||||
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
|
{
|
||||||
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
|
render->SetColorModulation(vGlowColor.Base()); // This only sets rgb, not alpha
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGlowObjectManager::DrawGlowVisible(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext)
|
||||||
|
{
|
||||||
|
ShaderStencilState_t stencilState;
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 1;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.m_ZFailOp = glow_outline_effect_stencil_mode.GetBool() ? STENCILOPERATION_KEEP : STENCILOPERATION_REPLACE;
|
||||||
|
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
|
render->SetBlend(1);
|
||||||
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
|
{
|
||||||
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || current.m_bRenderWhenOccluded || !current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
|
render->SetColorModulation(vGlowColor.Base()); // This only sets rgb, not alpha
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h )
|
void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h )
|
||||||
{
|
{
|
||||||
//=======================================================//
|
const PIXEvent pixEvent(pRenderContext, "ApplyEntityGlowEffects");
|
||||||
// Render objects into stencil buffer //
|
|
||||||
//=======================================================//
|
|
||||||
// Set override shader to the same simple shader we use to render the glow models
|
|
||||||
IMaterial *pMatGlowColor = materials->FindMaterial( "dev/glow_color", TEXTURE_GROUP_OTHER, true );
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( pMatGlowColor );
|
|
||||||
|
|
||||||
ShaderStencilState_t stencilStateDisable;
|
// Optimization: only do all the framebuffer shuffling if there's at least one glow to be drawn
|
||||||
stencilStateDisable.m_bEnable = false;
|
|
||||||
float flSavedBlend = render->GetBlend();
|
|
||||||
|
|
||||||
// Set alpha to 0 so we don't touch any color pixels
|
|
||||||
render->SetBlend( 0.0f );
|
|
||||||
pRenderContext->OverrideDepthEnable( true, false );
|
|
||||||
|
|
||||||
int iNumGlowObjects = 0;
|
|
||||||
|
|
||||||
for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i )
|
|
||||||
{
|
{
|
||||||
if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) )
|
bool atLeastOneGlow = false;
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded || m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
{
|
{
|
||||||
if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded && m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
if (m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw(nSplitScreenSlot))
|
||||||
{
|
continue;
|
||||||
ShaderStencilState_t stencilState;
|
|
||||||
stencilState.m_bEnable = true;
|
|
||||||
stencilState.m_nReferenceValue = 1;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
|
||||||
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
atLeastOneGlow = true;
|
||||||
|
break;
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
|
||||||
else if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded )
|
|
||||||
{
|
|
||||||
ShaderStencilState_t stencilState;
|
|
||||||
stencilState.m_bEnable = true;
|
|
||||||
stencilState.m_nReferenceValue = 1;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
|
||||||
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
|
||||||
else if ( m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
|
||||||
{
|
|
||||||
ShaderStencilState_t stencilState;
|
|
||||||
stencilState.m_bEnable = true;
|
|
||||||
stencilState.m_nReferenceValue = 2;
|
|
||||||
stencilState.m_nTestMask = 0x1;
|
|
||||||
stencilState.m_nWriteMask = 0x3;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_EQUAL;
|
|
||||||
stencilState.m_PassOp = STENCILOPERATION_INCRSAT;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iNumGlowObjects++;
|
if (!atLeastOneGlow)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to do a 2nd pass to warm stencil for objects which are rendered only when occluded
|
ITexture* const pRtFullFrameFB0 = materials->FindTexture("_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i )
|
ITexture* const pRtFullFrameFB1 = materials->FindTexture("_rt_FullFrameFB1", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
{
|
|
||||||
if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded && !m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
pRenderContext->PushRenderTargetAndViewport();
|
||||||
|
|
||||||
|
// Set backbuffer + hardware depth as MRT 0. We CANNOT CHANGE RENDER TARGETS after this point!!!
|
||||||
|
// In CShaderAPIDx8::CreateDepthTexture all depth+stencil buffers are created with the "discard"
|
||||||
|
// flag set to TRUE. Not sure about OpenGL, but according to
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb174356(v=vs.85).aspx, if you change
|
||||||
|
// the depth+stencil buffer away from a buffer that has discard=TRUE, the contents become garbage.
|
||||||
|
pRenderContext->SetRenderTargetEx(0, nullptr);
|
||||||
|
|
||||||
|
// Save current backbuffer to _rt_FullFrameFB1
|
||||||
|
pRenderContext->CopyRenderTargetToTexture(pRtFullFrameFB1);
|
||||||
|
|
||||||
|
// Clear backbuffer color and stencil, keep depth for testing
|
||||||
|
pRenderContext->ClearColor4ub(0, 0, 0, 0);
|
||||||
|
pRenderContext->ClearBuffers(true, false, true);
|
||||||
|
|
||||||
|
// Draw glow models
|
||||||
|
{
|
||||||
|
// Save modulation color and blend
|
||||||
|
Vector vOrigColor;
|
||||||
|
render->GetColorModulation(vOrigColor.Base());
|
||||||
|
const float flOrigBlend = render->GetBlend();
|
||||||
|
|
||||||
|
// Set override material for glow color
|
||||||
|
g_pStudioRender->ForcedMaterialOverride(materials->FindMaterial("dev/glow_color", TEXTURE_GROUP_OTHER, true));
|
||||||
|
pRenderContext->OverrideColorWriteEnable(true, true);
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(true, true);
|
||||||
|
|
||||||
|
// Draw "glow when visible" objects
|
||||||
|
DrawGlowVisible(nSplitScreenSlot, pRenderContext);
|
||||||
|
|
||||||
|
// Draw "glow when occluded" objects
|
||||||
|
DrawGlowOccluded(nSplitScreenSlot, pRenderContext);
|
||||||
|
|
||||||
|
// Draw "glow always" objects
|
||||||
|
DrawGlowAlways(nSplitScreenSlot, pRenderContext);
|
||||||
|
|
||||||
|
// Unset override material
|
||||||
|
g_pStudioRender->ForcedMaterialOverride(NULL);
|
||||||
|
|
||||||
|
// Restore modulation color and blend
|
||||||
|
render->SetColorModulation(vOrigColor.Base());
|
||||||
|
render->SetBlend(flOrigBlend);
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy MSAA'd glow models to _rt_FullFrameFB0
|
||||||
|
pRenderContext->CopyRenderTargetToTexture(pRtFullFrameFB0);
|
||||||
|
|
||||||
|
// Move original contents of the backbuffer from _rt_FullFrameFB1 to the backbuffer
|
||||||
|
{
|
||||||
|
#if FIXED_COPY_TEXTURE_TO_RENDER_TARGET // Coordinates don't seem to be mapped 1:1 properly, screen becomes slightly blurry
|
||||||
|
pRenderContext->CopyTextureToRenderTargetEx(0, pRtFullFrameFB1, nullptr);
|
||||||
|
#else
|
||||||
|
pRenderContext->SetStencilEnable(false);
|
||||||
|
|
||||||
|
IMaterial* const pFullFrameFB1 = materials->FindMaterial("debug/debugfbtexture1", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
|
pFullFrameFB1->AddRef();
|
||||||
|
pRenderContext->Bind(pFullFrameFB1);
|
||||||
|
|
||||||
|
const int nSrcWidth = pSetup->width;
|
||||||
|
const int nSrcHeight = pSetup->height;
|
||||||
|
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
||||||
|
pRenderContext->GetViewport(nViewportX, nViewportY, nViewportWidth, nViewportHeight);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
{
|
{
|
||||||
ShaderStencilState_t stencilState;
|
pRenderContext->DrawScreenSpaceRectangle(pFullFrameFB1,
|
||||||
stencilState.m_bEnable = true;
|
0, 0, nViewportWidth, nViewportHeight,
|
||||||
stencilState.m_nReferenceValue = 2;
|
0, 0, nSrcWidth - 1, nSrcHeight - 1,
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
pRtFullFrameFB1->GetActualWidth(), pRtFullFrameFB1->GetActualHeight());
|
||||||
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
}
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
|
||||||
|
pFullFrameFB1->Release();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pRenderContext->OverrideDepthEnable( false, false );
|
// Bloom glow models from _rt_FullFrameFB0 to backbuffer while stenciling out inside of models
|
||||||
render->SetBlend( flSavedBlend );
|
|
||||||
stencilStateDisable.SetStencilState( pRenderContext );
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( NULL );
|
|
||||||
|
|
||||||
// If there aren't any objects to glow, don't do all this other stuff
|
|
||||||
// this fixes a bug where if there are glow objects in the list, but none of them are glowing,
|
|
||||||
// the whole screen blooms.
|
|
||||||
if ( iNumGlowObjects <= 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
//=============================================
|
|
||||||
// Render the glow colors to _rt_FullFrameFB
|
|
||||||
//=============================================
|
|
||||||
{
|
{
|
||||||
PIXEvent pixEvent( pRenderContext, "RenderGlowModels" );
|
|
||||||
RenderGlowModels( pSetup, nSplitScreenSlot, pRenderContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get viewport
|
|
||||||
int nSrcWidth = pSetup->width;
|
|
||||||
int nSrcHeight = pSetup->height;
|
|
||||||
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
|
||||||
pRenderContext->GetViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight );
|
|
||||||
|
|
||||||
// Get material and texture pointers
|
|
||||||
ITexture *pRtQuarterSize1 = materials->FindTexture( "_rt_SmallFB1", TEXTURE_GROUP_RENDER_TARGET );
|
|
||||||
|
|
||||||
{
|
|
||||||
//=======================================================================================================//
|
|
||||||
// At this point, pRtQuarterSize0 is filled with the fully colored glow around everything as solid glowy //
|
|
||||||
// blobs. Now we need to stencil out the original objects by only writing pixels that have no //
|
|
||||||
// stencil bits set in the range we care about. //
|
|
||||||
//=======================================================================================================//
|
|
||||||
IMaterial *pMatHaloAddToScreen = materials->FindMaterial( "dev/halo_add_to_screen", TEXTURE_GROUP_OTHER, true );
|
|
||||||
|
|
||||||
// Do not fade the glows out at all (weight = 1.0)
|
|
||||||
IMaterialVar *pDimVar = pMatHaloAddToScreen->FindVar( "$C0_X", NULL );
|
|
||||||
pDimVar->SetFloatValue( 1.0f );
|
|
||||||
|
|
||||||
// Set stencil state
|
// Set stencil state
|
||||||
ShaderStencilState_t stencilState;
|
ShaderStencilState_t stencilState;
|
||||||
stencilState.m_bEnable = true;
|
stencilState.m_bEnable = true;
|
||||||
stencilState.m_nWriteMask = 0x0; // We're not changing stencil
|
stencilState.m_nWriteMask = 0; // We're not changing stencil
|
||||||
stencilState.m_nTestMask = 0xFF;
|
stencilState.m_nReferenceValue = 1;
|
||||||
stencilState.m_nReferenceValue = 0x0;
|
stencilState.m_nTestMask = 1;
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_EQUAL;
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_NOTEQUAL;
|
||||||
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.SetStencilState( pRenderContext );
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
ITexture* const pRtQuarterSize1 = materials->FindTexture("_rt_SmallFB1", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
|
IMaterial* const pMatHaloAddToScreen = materials->FindMaterial("dev/halo_add_to_screen", TEXTURE_GROUP_OTHER, true);
|
||||||
|
|
||||||
|
// Write to alpha
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(true, true);
|
||||||
|
|
||||||
|
const int nSrcWidth = pSetup->width;
|
||||||
|
const int nSrcHeight = pSetup->height;
|
||||||
|
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
||||||
|
pRenderContext->GetViewport(nViewportX, nViewportY, nViewportWidth, nViewportHeight);
|
||||||
|
|
||||||
// Draw quad
|
// Draw quad
|
||||||
pRenderContext->DrawScreenSpaceRectangle( pMatHaloAddToScreen, 0, 0, nViewportWidth, nViewportHeight,
|
pRenderContext->DrawScreenSpaceRectangle(pMatHaloAddToScreen,
|
||||||
0.0f, -0.5f, nSrcWidth / 4 - 1, nSrcHeight / 4 - 1,
|
0, 0, nViewportWidth, nViewportHeight,
|
||||||
|
0, 0, nSrcWidth / 4 - 1, nSrcHeight / 4 - 1,
|
||||||
pRtQuarterSize1->GetActualWidth(),
|
pRtQuarterSize1->GetActualWidth(),
|
||||||
pRtQuarterSize1->GetActualHeight() );
|
pRtQuarterSize1->GetActualHeight());
|
||||||
|
|
||||||
stencilStateDisable.SetStencilState( pRenderContext );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Done with all of our "advanced" 3D rendering.
|
||||||
|
pRenderContext->SetStencilEnable(false);
|
||||||
|
pRenderContext->OverrideColorWriteEnable(false, false);
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(false, false);
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
|
||||||
|
pRenderContext->PopRenderTargetAndViewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGlowObjectManager::GlowObjectDefinition_t::DrawModel()
|
void CGlowObjectManager::GlowObjectDefinition_t::DrawModel()
|
||||||
|
@ -117,7 +117,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void RenderGlowModels( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext );
|
|
||||||
void ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h );
|
void ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h );
|
||||||
|
|
||||||
struct GlowObjectDefinition_t
|
struct GlowObjectDefinition_t
|
||||||
@ -150,6 +149,10 @@ private:
|
|||||||
static const int ENTRY_IN_USE = -2;
|
static const int ENTRY_IN_USE = -2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DrawGlowVisible(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext);
|
||||||
|
void DrawGlowOccluded(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext);
|
||||||
|
void DrawGlowAlways(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext);
|
||||||
|
|
||||||
CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
|
CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
|
||||||
int m_nFirstFreeSlot;
|
int m_nFirstFreeSlot;
|
||||||
};
|
};
|
||||||
|
5
sp/game/mod_episodic/materials/debug/debugfbtexture1.vmt
Normal file
5
sp/game/mod_episodic/materials/debug/debugfbtexture1.vmt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"unlitgeneric"
|
||||||
|
{
|
||||||
|
"$basetexture" "_rt_FullFrameFB1"
|
||||||
|
"%noToolTexture" 1
|
||||||
|
}
|
5
sp/game/mod_hl2/materials/debug/debugfbtexture1.vmt
Normal file
5
sp/game/mod_hl2/materials/debug/debugfbtexture1.vmt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"unlitgeneric"
|
||||||
|
{
|
||||||
|
"$basetexture" "_rt_FullFrameFB1"
|
||||||
|
"%noToolTexture" 1
|
||||||
|
}
|
@ -17,8 +17,27 @@
|
|||||||
|
|
||||||
#ifdef GLOWS_ENABLE
|
#ifdef GLOWS_ENABLE
|
||||||
|
|
||||||
|
// If you've added IMatRenderContext::OverrideDepthFunc (see ::DrawGlowOccluded below),
|
||||||
|
// then you can enable this and have single-pass glows for "glow when occluded" outlines.
|
||||||
|
// ***PLEASE*** increment MATERIAL_SYSTEM_INTERFACE_VERSION when you add this!
|
||||||
|
#define ADDED_OVERRIDE_DEPTH_FUNC 0
|
||||||
|
|
||||||
|
// If you've fixed IMatRenderContext::CopyTextureToRenderTargetEx
|
||||||
|
// (see CGlowObjectManager::RenderGlowModels below), then you can enable this and have
|
||||||
|
// code that's a bit cleaner. Also, then you won't have to ship debug/debugfbtexture1.
|
||||||
|
#define FIXED_COPY_TEXTURE_TO_RENDER_TARGET 0
|
||||||
|
|
||||||
ConVar glow_outline_effect_enable( "glow_outline_effect_enable", "1", FCVAR_ARCHIVE, "Enable entity outline glow effects." );
|
ConVar glow_outline_effect_enable( "glow_outline_effect_enable", "1", FCVAR_ARCHIVE, "Enable entity outline glow effects." );
|
||||||
ConVar glow_outline_effect_width( "glow_outline_width", "10.0f", FCVAR_CHEAT, "Width of glow outline effect in screen space." );
|
|
||||||
|
// This doesn't actually do anything.
|
||||||
|
ConVar glow_outline_effect_width( "glow_outline_width", "10.0f", FCVAR_CHEAT | FCVAR_UNREGISTERED, "Width of glow outline effect in screen space." );
|
||||||
|
|
||||||
|
// Not really necessary, but it's two different styles. I prefer style 0, but style 1 "closes off" partially occluded glows.
|
||||||
|
static ConVar glow_outline_effect_stencil_mode("glow_outline_effect_stencil_mode", "0", 0,
|
||||||
|
"\n\t0: Draws partially occluded glows in a more 3d-esque way, making them look more like they're actually surrounding the model."
|
||||||
|
"\n\t1: Draws partially occluded glows in a more 2d-esque way, which can make them more visible."
|
||||||
|
"\n\tSee https://i.imgur.com/OJQkXei.gif",
|
||||||
|
true, 0, true, 1);
|
||||||
|
|
||||||
extern bool g_bDumpRenderTargets; // in viewpostprocess.cpp
|
extern bool g_bDumpRenderTargets; // in viewpostprocess.cpp
|
||||||
|
|
||||||
@ -46,14 +65,18 @@ struct ShaderStencilState_t
|
|||||||
|
|
||||||
void SetStencilState( CMatRenderContextPtr &pRenderContext )
|
void SetStencilState( CMatRenderContextPtr &pRenderContext )
|
||||||
{
|
{
|
||||||
pRenderContext->SetStencilEnable( m_bEnable );
|
pRenderContext->SetStencilEnable(m_bEnable);
|
||||||
pRenderContext->SetStencilFailOperation( m_FailOp );
|
|
||||||
pRenderContext->SetStencilZFailOperation( m_ZFailOp );
|
if (m_bEnable)
|
||||||
pRenderContext->SetStencilPassOperation( m_PassOp );
|
{
|
||||||
pRenderContext->SetStencilCompareFunction( m_CompareFunc );
|
pRenderContext->SetStencilFailOperation(m_FailOp);
|
||||||
pRenderContext->SetStencilReferenceValue( m_nReferenceValue );
|
pRenderContext->SetStencilZFailOperation(m_ZFailOp);
|
||||||
pRenderContext->SetStencilTestMask( m_nTestMask );
|
pRenderContext->SetStencilPassOperation(m_PassOp);
|
||||||
pRenderContext->SetStencilWriteMask( m_nWriteMask );
|
pRenderContext->SetStencilCompareFunction(m_CompareFunc);
|
||||||
|
pRenderContext->SetStencilReferenceValue(m_nReferenceValue);
|
||||||
|
pRenderContext->SetStencilTestMask(m_nTestMask);
|
||||||
|
pRenderContext->SetStencilWriteMask(m_nWriteMask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,240 +97,294 @@ void CGlowObjectManager::RenderGlowEffects( const CViewSetup *pSetup, int nSplit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetRenderTargetAndViewPort( ITexture *rt, int w, int h )
|
void CGlowObjectManager::DrawGlowAlways(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext)
|
||||||
{
|
{
|
||||||
CMatRenderContextPtr pRenderContext( materials );
|
|
||||||
pRenderContext->SetRenderTarget(rt);
|
|
||||||
pRenderContext->Viewport(0,0,w,h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGlowObjectManager::RenderGlowModels( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext )
|
|
||||||
{
|
|
||||||
//==========================================================================================//
|
|
||||||
// This renders solid pixels with the correct coloring for each object that needs the glow. //
|
|
||||||
// After this function returns, this image will then be blurred and added into the frame //
|
|
||||||
// buffer with the objects stenciled out. //
|
|
||||||
//==========================================================================================//
|
|
||||||
pRenderContext->PushRenderTargetAndViewport();
|
|
||||||
|
|
||||||
// Save modulation color and blend
|
|
||||||
Vector vOrigColor;
|
|
||||||
render->GetColorModulation( vOrigColor.Base() );
|
|
||||||
float flOrigBlend = render->GetBlend();
|
|
||||||
|
|
||||||
// Get pointer to FullFrameFB
|
|
||||||
ITexture *pRtFullFrame = NULL;
|
|
||||||
pRtFullFrame = materials->FindTexture( FULL_FRAME_TEXTURE, TEXTURE_GROUP_RENDER_TARGET );
|
|
||||||
|
|
||||||
SetRenderTargetAndViewPort( pRtFullFrame, pSetup->width, pSetup->height );
|
|
||||||
|
|
||||||
pRenderContext->ClearColor3ub( 0, 0, 0 );
|
|
||||||
pRenderContext->ClearBuffers( true, false, false );
|
|
||||||
|
|
||||||
// Set override material for glow color
|
|
||||||
IMaterial *pMatGlowColor = NULL;
|
|
||||||
|
|
||||||
pMatGlowColor = materials->FindMaterial( "dev/glow_color", TEXTURE_GROUP_OTHER, true );
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( pMatGlowColor );
|
|
||||||
|
|
||||||
ShaderStencilState_t stencilState;
|
ShaderStencilState_t stencilState;
|
||||||
stencilState.m_bEnable = false;
|
stencilState.m_bEnable = true;
|
||||||
stencilState.m_nReferenceValue = 0;
|
stencilState.m_nReferenceValue = 1;
|
||||||
stencilState.m_nTestMask = 0xFF;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
render->SetBlend(1);
|
||||||
//==================//
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
// Draw the objects //
|
|
||||||
//==================//
|
|
||||||
for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i )
|
|
||||||
{
|
{
|
||||||
if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) )
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || !current.m_bRenderWhenUnoccluded)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
render->SetBlend( m_GlowObjectDefinitions[i].m_flGlowAlpha );
|
Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
Vector vGlowColor = m_GlowObjectDefinitions[i].m_vGlowColor * m_GlowObjectDefinitions[i].m_flGlowAlpha;
|
render->SetColorModulation(vGlowColor.Base()); // This only sets rgb, not alpha
|
||||||
render->SetColorModulation( &vGlowColor[0] ); // This only sets rgb, not alpha
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
current.DrawModel();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( g_bDumpRenderTargets )
|
void CGlowObjectManager::DrawGlowOccluded(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext)
|
||||||
|
{
|
||||||
|
#if ADDED_OVERRIDE_DEPTH_FUNC // Enable this when the TF2 team has added IMatRenderContext::OverrideDepthFunc or similar.
|
||||||
|
ShaderStencilState_t stencilState;
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 1;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
|
stencilState.m_PassOp = glow_outline_effect_stencil_mode.GetBool() ? STENCILOPERATION_KEEP : STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
|
|
||||||
|
// Not implemented, we need this feature to be able to do this in 1 pass. Otherwise,
|
||||||
|
// we'd have to do 2 passes, 1st to mark on the stencil where the depth test failed,
|
||||||
|
// 2nd to actually utilize that information and draw color there.
|
||||||
|
pRenderContext->OverrideDepthFunc(true, SHADER_DEPTHFUNC_NEARER);
|
||||||
|
|
||||||
|
for (int i = 0; i < glowObjectDefinitions.Count(); i++)
|
||||||
{
|
{
|
||||||
DumpTGAofRenderTarget( pSetup->width, pSetup->height, "GlowModels" );
|
auto& current = glowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
render->SetBlend(current.m_flGlowAlpha);
|
||||||
|
Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
|
render->SetColorModulation(&vGlowColor[0]); // This only sets rgb, not alpha
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( NULL );
|
pRenderContext->OverrideDepthFunc(false, SHADER_DEPTHFUNC_NEAREROREQUAL)
|
||||||
render->SetColorModulation( vOrigColor.Base() );
|
#else // 2-pass as a proof of concept so I can take a nice screenshot.
|
||||||
render->SetBlend( flOrigBlend );
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
|
|
||||||
ShaderStencilState_t stencilStateDisable;
|
|
||||||
stencilStateDisable.m_bEnable = false;
|
|
||||||
stencilStateDisable.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
pRenderContext->PopRenderTargetAndViewport();
|
ShaderStencilState_t stencilState;
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 2;
|
||||||
|
stencilState.m_nWriteMask = 2;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
// Draw depthtest-passing pixels to the stencil buffer
|
||||||
|
{
|
||||||
|
render->SetBlend(0);
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(true, false);
|
||||||
|
pRenderContext->OverrideColorWriteEnable(true, false);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
|
{
|
||||||
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(false, true);
|
||||||
|
pRenderContext->OverrideColorWriteEnable(false, true);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 3;
|
||||||
|
stencilState.m_nTestMask = 2;
|
||||||
|
stencilState.m_nWriteMask = 1;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_NOTEQUAL;
|
||||||
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = glow_outline_effect_stencil_mode.GetBool() ? STENCILOPERATION_KEEP : STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
// Draw color+alpha, stenciling out pixels from the first pass
|
||||||
|
render->SetBlend(1);
|
||||||
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
|
{
|
||||||
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || !current.m_bRenderWhenOccluded || current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
|
render->SetColorModulation(vGlowColor.Base()); // This only sets rgb, not alpha
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGlowObjectManager::DrawGlowVisible(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext)
|
||||||
|
{
|
||||||
|
ShaderStencilState_t stencilState;
|
||||||
|
stencilState.m_bEnable = true;
|
||||||
|
stencilState.m_nReferenceValue = 1;
|
||||||
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
||||||
|
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
||||||
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
|
stencilState.m_ZFailOp = glow_outline_effect_stencil_mode.GetBool() ? STENCILOPERATION_KEEP : STENCILOPERATION_REPLACE;
|
||||||
|
|
||||||
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
|
render->SetBlend(1);
|
||||||
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
|
{
|
||||||
|
auto& current = m_GlowObjectDefinitions[i];
|
||||||
|
if (current.IsUnused() || !current.ShouldDraw(nSplitScreenSlot) || current.m_bRenderWhenOccluded || !current.m_bRenderWhenUnoccluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector vGlowColor = current.m_vGlowColor * current.m_flGlowAlpha;
|
||||||
|
render->SetColorModulation(vGlowColor.Base()); // This only sets rgb, not alpha
|
||||||
|
|
||||||
|
current.DrawModel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h )
|
void CGlowObjectManager::ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h )
|
||||||
{
|
{
|
||||||
//=======================================================//
|
const PIXEvent pixEvent(pRenderContext, "ApplyEntityGlowEffects");
|
||||||
// Render objects into stencil buffer //
|
|
||||||
//=======================================================//
|
|
||||||
// Set override shader to the same simple shader we use to render the glow models
|
|
||||||
IMaterial *pMatGlowColor = materials->FindMaterial( "dev/glow_color", TEXTURE_GROUP_OTHER, true );
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( pMatGlowColor );
|
|
||||||
|
|
||||||
ShaderStencilState_t stencilStateDisable;
|
// Optimization: only do all the framebuffer shuffling if there's at least one glow to be drawn
|
||||||
stencilStateDisable.m_bEnable = false;
|
|
||||||
float flSavedBlend = render->GetBlend();
|
|
||||||
|
|
||||||
// Set alpha to 0 so we don't touch any color pixels
|
|
||||||
render->SetBlend( 0.0f );
|
|
||||||
pRenderContext->OverrideDepthEnable( true, false );
|
|
||||||
|
|
||||||
int iNumGlowObjects = 0;
|
|
||||||
|
|
||||||
for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i )
|
|
||||||
{
|
{
|
||||||
if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) )
|
bool atLeastOneGlow = false;
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded || m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
for (int i = 0; i < m_GlowObjectDefinitions.Count(); i++)
|
||||||
{
|
{
|
||||||
if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded && m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
if (m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw(nSplitScreenSlot))
|
||||||
{
|
continue;
|
||||||
ShaderStencilState_t stencilState;
|
|
||||||
stencilState.m_bEnable = true;
|
|
||||||
stencilState.m_nReferenceValue = 1;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
|
||||||
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
atLeastOneGlow = true;
|
||||||
|
break;
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
|
||||||
else if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded )
|
|
||||||
{
|
|
||||||
ShaderStencilState_t stencilState;
|
|
||||||
stencilState.m_bEnable = true;
|
|
||||||
stencilState.m_nReferenceValue = 1;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
|
||||||
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
|
||||||
else if ( m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
|
||||||
{
|
|
||||||
ShaderStencilState_t stencilState;
|
|
||||||
stencilState.m_bEnable = true;
|
|
||||||
stencilState.m_nReferenceValue = 2;
|
|
||||||
stencilState.m_nTestMask = 0x1;
|
|
||||||
stencilState.m_nWriteMask = 0x3;
|
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_EQUAL;
|
|
||||||
stencilState.m_PassOp = STENCILOPERATION_INCRSAT;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_REPLACE;
|
|
||||||
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iNumGlowObjects++;
|
if (!atLeastOneGlow)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to do a 2nd pass to warm stencil for objects which are rendered only when occluded
|
ITexture* const pRtFullFrameFB0 = materials->FindTexture("_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
for ( int i = 0; i < m_GlowObjectDefinitions.Count(); ++ i )
|
ITexture* const pRtFullFrameFB1 = materials->FindTexture("_rt_FullFrameFB1", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
{
|
|
||||||
if ( m_GlowObjectDefinitions[i].IsUnused() || !m_GlowObjectDefinitions[i].ShouldDraw( nSplitScreenSlot ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( m_GlowObjectDefinitions[i].m_bRenderWhenOccluded && !m_GlowObjectDefinitions[i].m_bRenderWhenUnoccluded )
|
pRenderContext->PushRenderTargetAndViewport();
|
||||||
|
|
||||||
|
// Set backbuffer + hardware depth as MRT 0. We CANNOT CHANGE RENDER TARGETS after this point!!!
|
||||||
|
// In CShaderAPIDx8::CreateDepthTexture all depth+stencil buffers are created with the "discard"
|
||||||
|
// flag set to TRUE. Not sure about OpenGL, but according to
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb174356(v=vs.85).aspx, if you change
|
||||||
|
// the depth+stencil buffer away from a buffer that has discard=TRUE, the contents become garbage.
|
||||||
|
pRenderContext->SetRenderTargetEx(0, nullptr);
|
||||||
|
|
||||||
|
// Save current backbuffer to _rt_FullFrameFB1
|
||||||
|
pRenderContext->CopyRenderTargetToTexture(pRtFullFrameFB1);
|
||||||
|
|
||||||
|
// Clear backbuffer color and stencil, keep depth for testing
|
||||||
|
pRenderContext->ClearColor4ub(0, 0, 0, 0);
|
||||||
|
pRenderContext->ClearBuffers(true, false, true);
|
||||||
|
|
||||||
|
// Draw glow models
|
||||||
|
{
|
||||||
|
// Save modulation color and blend
|
||||||
|
Vector vOrigColor;
|
||||||
|
render->GetColorModulation(vOrigColor.Base());
|
||||||
|
const float flOrigBlend = render->GetBlend();
|
||||||
|
|
||||||
|
// Set override material for glow color
|
||||||
|
g_pStudioRender->ForcedMaterialOverride(materials->FindMaterial("dev/glow_color", TEXTURE_GROUP_OTHER, true));
|
||||||
|
pRenderContext->OverrideColorWriteEnable(true, true);
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(true, true);
|
||||||
|
|
||||||
|
// Draw "glow when visible" objects
|
||||||
|
DrawGlowVisible(nSplitScreenSlot, pRenderContext);
|
||||||
|
|
||||||
|
// Draw "glow when occluded" objects
|
||||||
|
DrawGlowOccluded(nSplitScreenSlot, pRenderContext);
|
||||||
|
|
||||||
|
// Draw "glow always" objects
|
||||||
|
DrawGlowAlways(nSplitScreenSlot, pRenderContext);
|
||||||
|
|
||||||
|
// Unset override material
|
||||||
|
g_pStudioRender->ForcedMaterialOverride(NULL);
|
||||||
|
|
||||||
|
// Restore modulation color and blend
|
||||||
|
render->SetColorModulation(vOrigColor.Base());
|
||||||
|
render->SetBlend(flOrigBlend);
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy MSAA'd glow models to _rt_FullFrameFB0
|
||||||
|
pRenderContext->CopyRenderTargetToTexture(pRtFullFrameFB0);
|
||||||
|
|
||||||
|
// Move original contents of the backbuffer from _rt_FullFrameFB1 to the backbuffer
|
||||||
|
{
|
||||||
|
#if FIXED_COPY_TEXTURE_TO_RENDER_TARGET // Coordinates don't seem to be mapped 1:1 properly, screen becomes slightly blurry
|
||||||
|
pRenderContext->CopyTextureToRenderTargetEx(0, pRtFullFrameFB1, nullptr);
|
||||||
|
#else
|
||||||
|
pRenderContext->SetStencilEnable(false);
|
||||||
|
|
||||||
|
IMaterial* const pFullFrameFB1 = materials->FindMaterial("debug/debugfbtexture1", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
|
pFullFrameFB1->AddRef();
|
||||||
|
pRenderContext->Bind(pFullFrameFB1);
|
||||||
|
|
||||||
|
const int nSrcWidth = pSetup->width;
|
||||||
|
const int nSrcHeight = pSetup->height;
|
||||||
|
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
||||||
|
pRenderContext->GetViewport(nViewportX, nViewportY, nViewportWidth, nViewportHeight);
|
||||||
|
|
||||||
|
pRenderContext->OverrideDepthEnable(true, false);
|
||||||
{
|
{
|
||||||
ShaderStencilState_t stencilState;
|
pRenderContext->DrawScreenSpaceRectangle(pFullFrameFB1,
|
||||||
stencilState.m_bEnable = true;
|
0, 0, nViewportWidth, nViewportHeight,
|
||||||
stencilState.m_nReferenceValue = 2;
|
0, 0, nSrcWidth - 1, nSrcHeight - 1,
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_ALWAYS;
|
pRtFullFrameFB1->GetActualWidth(), pRtFullFrameFB1->GetActualHeight());
|
||||||
stencilState.m_PassOp = STENCILOPERATION_REPLACE;
|
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
|
||||||
stencilState.SetStencilState( pRenderContext );
|
|
||||||
|
|
||||||
m_GlowObjectDefinitions[i].DrawModel();
|
|
||||||
}
|
}
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
|
||||||
|
pFullFrameFB1->Release();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pRenderContext->OverrideDepthEnable( false, false );
|
// Bloom glow models from _rt_FullFrameFB0 to backbuffer while stenciling out inside of models
|
||||||
render->SetBlend( flSavedBlend );
|
|
||||||
stencilStateDisable.SetStencilState( pRenderContext );
|
|
||||||
g_pStudioRender->ForcedMaterialOverride( NULL );
|
|
||||||
|
|
||||||
// If there aren't any objects to glow, don't do all this other stuff
|
|
||||||
// this fixes a bug where if there are glow objects in the list, but none of them are glowing,
|
|
||||||
// the whole screen blooms.
|
|
||||||
if ( iNumGlowObjects <= 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
//=============================================
|
|
||||||
// Render the glow colors to _rt_FullFrameFB
|
|
||||||
//=============================================
|
|
||||||
{
|
{
|
||||||
PIXEvent pixEvent( pRenderContext, "RenderGlowModels" );
|
|
||||||
RenderGlowModels( pSetup, nSplitScreenSlot, pRenderContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get viewport
|
|
||||||
int nSrcWidth = pSetup->width;
|
|
||||||
int nSrcHeight = pSetup->height;
|
|
||||||
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
|
||||||
pRenderContext->GetViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight );
|
|
||||||
|
|
||||||
// Get material and texture pointers
|
|
||||||
ITexture *pRtQuarterSize1 = materials->FindTexture( "_rt_SmallFB1", TEXTURE_GROUP_RENDER_TARGET );
|
|
||||||
|
|
||||||
{
|
|
||||||
//=======================================================================================================//
|
|
||||||
// At this point, pRtQuarterSize0 is filled with the fully colored glow around everything as solid glowy //
|
|
||||||
// blobs. Now we need to stencil out the original objects by only writing pixels that have no //
|
|
||||||
// stencil bits set in the range we care about. //
|
|
||||||
//=======================================================================================================//
|
|
||||||
IMaterial *pMatHaloAddToScreen = materials->FindMaterial( "dev/halo_add_to_screen", TEXTURE_GROUP_OTHER, true );
|
|
||||||
|
|
||||||
// Do not fade the glows out at all (weight = 1.0)
|
|
||||||
IMaterialVar *pDimVar = pMatHaloAddToScreen->FindVar( "$C0_X", NULL );
|
|
||||||
pDimVar->SetFloatValue( 1.0f );
|
|
||||||
|
|
||||||
// Set stencil state
|
// Set stencil state
|
||||||
ShaderStencilState_t stencilState;
|
ShaderStencilState_t stencilState;
|
||||||
stencilState.m_bEnable = true;
|
stencilState.m_bEnable = true;
|
||||||
stencilState.m_nWriteMask = 0x0; // We're not changing stencil
|
stencilState.m_nWriteMask = 0; // We're not changing stencil
|
||||||
stencilState.m_nTestMask = 0xFF;
|
stencilState.m_nReferenceValue = 1;
|
||||||
stencilState.m_nReferenceValue = 0x0;
|
stencilState.m_nTestMask = 1;
|
||||||
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_EQUAL;
|
stencilState.m_CompareFunc = STENCILCOMPARISONFUNCTION_NOTEQUAL;
|
||||||
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
stencilState.m_PassOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
stencilState.m_FailOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
stencilState.m_ZFailOp = STENCILOPERATION_KEEP;
|
||||||
stencilState.SetStencilState( pRenderContext );
|
stencilState.SetStencilState(pRenderContext);
|
||||||
|
|
||||||
|
ITexture* const pRtQuarterSize1 = materials->FindTexture("_rt_SmallFB1", TEXTURE_GROUP_RENDER_TARGET);
|
||||||
|
IMaterial* const pMatHaloAddToScreen = materials->FindMaterial("dev/halo_add_to_screen", TEXTURE_GROUP_OTHER, true);
|
||||||
|
|
||||||
|
// Write to alpha
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(true, true);
|
||||||
|
|
||||||
|
const int nSrcWidth = pSetup->width;
|
||||||
|
const int nSrcHeight = pSetup->height;
|
||||||
|
int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
|
||||||
|
pRenderContext->GetViewport(nViewportX, nViewportY, nViewportWidth, nViewportHeight);
|
||||||
|
|
||||||
// Draw quad
|
// Draw quad
|
||||||
pRenderContext->DrawScreenSpaceRectangle( pMatHaloAddToScreen, 0, 0, nViewportWidth, nViewportHeight,
|
pRenderContext->DrawScreenSpaceRectangle(pMatHaloAddToScreen,
|
||||||
0.0f, -0.5f, nSrcWidth / 4 - 1, nSrcHeight / 4 - 1,
|
0, 0, nViewportWidth, nViewportHeight,
|
||||||
|
0, 0, nSrcWidth / 4 - 1, nSrcHeight / 4 - 1,
|
||||||
pRtQuarterSize1->GetActualWidth(),
|
pRtQuarterSize1->GetActualWidth(),
|
||||||
pRtQuarterSize1->GetActualHeight() );
|
pRtQuarterSize1->GetActualHeight());
|
||||||
|
|
||||||
stencilStateDisable.SetStencilState( pRenderContext );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Done with all of our "advanced" 3D rendering.
|
||||||
|
pRenderContext->SetStencilEnable(false);
|
||||||
|
pRenderContext->OverrideColorWriteEnable(false, false);
|
||||||
|
pRenderContext->OverrideAlphaWriteEnable(false, false);
|
||||||
|
pRenderContext->OverrideDepthEnable(false, false);
|
||||||
|
|
||||||
|
pRenderContext->PopRenderTargetAndViewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGlowObjectManager::GlowObjectDefinition_t::DrawModel()
|
void CGlowObjectManager::GlowObjectDefinition_t::DrawModel()
|
||||||
|
@ -117,7 +117,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void RenderGlowModels( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext );
|
|
||||||
void ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h );
|
void ApplyEntityGlowEffects( const CViewSetup *pSetup, int nSplitScreenSlot, CMatRenderContextPtr &pRenderContext, float flBloomScale, int x, int y, int w, int h );
|
||||||
|
|
||||||
struct GlowObjectDefinition_t
|
struct GlowObjectDefinition_t
|
||||||
@ -150,6 +149,10 @@ private:
|
|||||||
static const int ENTRY_IN_USE = -2;
|
static const int ENTRY_IN_USE = -2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DrawGlowVisible(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext);
|
||||||
|
void DrawGlowOccluded(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext);
|
||||||
|
void DrawGlowAlways(int nSplitScreenSlot, CMatRenderContextPtr& pRenderContext);
|
||||||
|
|
||||||
CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
|
CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
|
||||||
int m_nFirstFreeSlot;
|
int m_nFirstFreeSlot;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user