⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transitiontable.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
// Apply shader state (stuff that doesn't lie in the transition table)
//-----------------------------------------------------------------------------
void CTransitionTable::ApplyShaderState( const ShadowState_t &shadowState, const ShadowShaderState_t &shaderState )
{
	// Don't bother testing against the current state because there
	// could well be dynamic state modifiers affecting this too....
	if (!shadowState.m_UsingFixedFunction)
	{
		// FIXME: Improve early-binding of vertex shader index
		ShaderManager()->SetVertexShader( shaderState.m_VertexShader, shaderState.m_nStaticVshIndex );
		ShaderManager()->SetPixelShader( shaderState.m_PixelShader, shaderState.m_nStaticPshIndex );

#ifdef DEBUG_BOARD_STATE
		BoardShaderState().m_VertexShader = shaderState.m_VertexShader;
		BoardShaderState().m_PixelShader = shaderState.m_PixelShader;
		BoardShaderState().m_nStaticVshIndex = shaderState.m_nStaticVshIndex;
		BoardShaderState().m_nStaticPshIndex = shaderState.m_nStaticPshIndex;
#endif
	}
	else
	{
		ShaderManager()->SetVertexShader( INVALID_VERTEX_SHADER );
		ShaderManager()->SetPixelShader( INVALID_PIXEL_SHADER );

#ifdef DEBUG_BOARD_STATE
		BoardShaderState().m_VertexShader = INVALID_VERTEX_SHADER;
		BoardShaderState().m_PixelShader = INVALID_PIXEL_SHADER;
		BoardShaderState().m_nStaticVshIndex = 0;
		BoardShaderState().m_nStaticPshIndex = 0;
#endif
	}
}


//-----------------------------------------------------------------------------
// Makes the board state match the snapshot
//-----------------------------------------------------------------------------
void CTransitionTable::UseSnapshot( StateSnapshot_t snapshotId )
{
	ShadowStateId_t id = m_SnapshotList[snapshotId].m_ShadowStateId;
	if (m_CurrentSnapshotId != snapshotId)
	{
		// First apply things that are in the transition table
		if ( m_CurrentShadowId != id )
		{
			TransitionList_t& transition = m_TransitionTable[id][m_CurrentShadowId];
			ApplyTransition( transition, id );
		}

		// NOTE: There is an opportunity here to set non-dynamic state that we don't
		// store in the transition list if we ever need it.

		m_CurrentSnapshotId = snapshotId;
	}

	// NOTE: This occurs regardless of whether the snapshot changed because it depends
	// on dynamic state (namely, the dynamic vertex + pixel shader index)
	// Followed by things that are not
	ApplyShaderState( m_ShadowStateList[id], m_SnapshotList[snapshotId].m_ShaderState );

#ifdef _DEBUG
	// NOTE: We can't ship with this active because mod makers may well violate this rule
	// We don't want no stinking fixed-function on hardware that has vertex and pixel shaders. . 
	// This could cause a serious perf hit. 
	if( HardwareConfig()->SupportsVertexAndPixelShaders() )
	{
//		Assert( !CurrentShadowState().m_UsingFixedFunction );
	}
#endif
}


//-----------------------------------------------------------------------------
// Cause the board to match the default state snapshot
//-----------------------------------------------------------------------------
void CTransitionTable::UseDefaultState( )
{
	// Need to blat these out because they are tested during transitions
	m_CurrentState.m_AlphaBlendEnable = false;
	m_CurrentState.m_SrcBlend = D3DBLEND_ONE;
	m_CurrentState.m_DestBlend = D3DBLEND_ZERO;
	SetRenderState( D3DRS_ALPHABLENDENABLE, m_CurrentState.m_AlphaBlendEnable );
	SetRenderState( D3DRS_SRCBLEND, m_CurrentState.m_SrcBlend );
	SetRenderState( D3DRS_DESTBLEND, m_CurrentState.m_DestBlend );

	// GR
	m_CurrentState.m_SeparateAlphaBlendEnable = false;
	m_CurrentState.m_SrcBlendAlpha = D3DBLEND_ONE;
	m_CurrentState.m_DestBlendAlpha = D3DBLEND_ZERO;
	SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, m_CurrentState.m_SeparateAlphaBlendEnable );
	SetRenderState( D3DRS_SRCBLENDALPHA, m_CurrentState.m_SrcBlendAlpha );
	SetRenderState( D3DRS_DESTBLENDALPHA, m_CurrentState.m_DestBlendAlpha );

	int nTextureUnits = ShaderAPI()->GetActualNumTextureUnits();
	for ( int i = 0; i < nTextureUnits; ++i)
	{
		TextureStage(i).m_ColorOp = D3DTOP_DISABLE;
		TextureStage(i).m_ColorArg1 = D3DTA_TEXTURE;
		TextureStage(i).m_ColorArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT;
		TextureStage(i).m_AlphaOp = D3DTOP_DISABLE;
		TextureStage(i).m_AlphaArg1 = D3DTA_TEXTURE;
		TextureStage(i).m_AlphaArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT;

		SetTextureStageState( i, D3DTSS_COLOROP,	TextureStage(i).m_ColorOp );
		SetTextureStageState( i, D3DTSS_COLORARG1,	TextureStage(i).m_ColorArg1 );
		SetTextureStageState( i, D3DTSS_COLORARG2,	TextureStage(i).m_ColorArg2 );
		SetTextureStageState( i, D3DTSS_ALPHAOP,	TextureStage(i).m_AlphaOp );
		SetTextureStageState( i, D3DTSS_ALPHAARG1,	TextureStage(i).m_AlphaArg1 );
		SetTextureStageState( i, D3DTSS_ALPHAARG2,	TextureStage(i).m_AlphaArg2 );
	}

	// Disable z overrides...
	m_CurrentState.m_bOverrideDepthEnable = false;
	m_CurrentState.m_ForceDepthFuncEquals = false;

	ApplyTransition( m_DefaultTransition, m_DefaultStateSnapshot );

	ShaderManager()->SetVertexShader( INVALID_VERTEX_SHADER );
	ShaderManager()->SetPixelShader( INVALID_PIXEL_SHADER );
}


//-----------------------------------------------------------------------------
// Snapshotted state overrides
//-----------------------------------------------------------------------------
void CTransitionTable::ForceDepthFuncEquals( bool bEnable )
{
	if( bEnable != m_CurrentState.m_ForceDepthFuncEquals )
	{
		// Do this so that we can call this from within the rendering code
		// See OverrideDepthEnable + PerformShadowStateOverrides for a version
		// that isn't expected to be called from within rendering code
		if( !ShaderAPI()->IsRenderingMesh() )
		{
			ShaderAPI()->FlushBufferedPrimitives();
		}

		m_CurrentState.m_ForceDepthFuncEquals = bEnable;

		if( bEnable )
		{
			SetRenderState( D3DRS_ZFUNC, D3DCMP_EQUAL );
		}
		else
		{
			SetRenderState( D3DRS_ZFUNC, CurrentShadowState().m_ZFunc );
		}
	}
}

void CTransitionTable::OverrideDepthEnable( bool bEnable, bool bDepthEnable )
{
	if ( bEnable != m_CurrentState.m_bOverrideDepthEnable )
	{
		ShaderAPI()->FlushBufferedPrimitives();
		m_CurrentState.m_bOverrideDepthEnable = bEnable;
		m_CurrentState.m_OverrideZWriteEnable = bDepthEnable ? D3DZB_TRUE : D3DZB_FALSE;

		if ( m_CurrentState.m_bOverrideDepthEnable )
		{
			SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
			SetRenderState( D3DRS_ZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable );
		}
		else
		{
			SetRenderState( D3DRS_ZENABLE, CurrentShadowState().m_ZEnable );
			SetRenderState( D3DRS_ZWRITEENABLE, CurrentShadowState().m_ZFunc );
		}
	}
}


//-----------------------------------------------------------------------------
// Perform state block overrides
//-----------------------------------------------------------------------------
void CTransitionTable::PerformShadowStateOverrides( )
{
	// Deal with funky overrides here, because the state blocks can't...
	if ( m_CurrentState.m_ForceDepthFuncEquals )
	{
		SetRenderState( D3DRS_ZFUNC, D3DCMP_EQUAL );
	}

	if ( m_CurrentState.m_bOverrideDepthEnable )
	{
		SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
		SetRenderState( D3DRS_ZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable );
	}
}


//-----------------------------------------------------------------------------
// Finds identical transition lists and shares them 
//-----------------------------------------------------------------------------
#define TEST_RENDER_STATEBLOCK_VALUE( _state )	\
	if( pOp->m_Op == ::Apply ## _state )					\
	{														\
		if ( state1.m_ ## _state == state2.m_ ## _state )	\
			continue;										\
		return false;										\
	}

#define TEST_TEXTURE_STATEBLOCK_VALUE( _state, _stage )		\
	if( pOp->m_Op == ::Apply ## _state )					\
	{														\
		if ( state1.m_TextureStage[_stage].m_ ## _state == state2.m_TextureStage[_stage].m_ ## _state )	\
			continue;										\
		return false;										\
	}

bool CTransitionTable::DoStateBlocksMatch( const TransitionList_t *pTransition, int nToSnapshot1, int nToSnapshot2 ) const
{
	// We know they are the same if the dest snapshot is identical
	if ( nToSnapshot1 == nToSnapshot2 )
		return true;

	// FIXME: This is gross!!
	// Otherwise we gotta check the values associated with each state-setting method
	const TransitionOp_t *pOp = &m_TransitionOps[pTransition->m_FirstOperation];
	const ShadowState_t &state1 = m_ShadowStateList[nToSnapshot1];
	const ShadowState_t &state2 = m_ShadowStateList[nToSnapshot2];

	for ( int k = 0; k < pTransition->m_nOpCountInStateBlock; ++k, ++pOp )
	{
		TEST_RENDER_STATEBLOCK_VALUE( ZFunc );
		TEST_RENDER_STATEBLOCK_VALUE( ZEnable );
		TEST_RENDER_STATEBLOCK_VALUE( ZWriteEnable );
		TEST_RENDER_STATEBLOCK_VALUE( ColorWriteEnable );
		TEST_RENDER_STATEBLOCK_VALUE( AlphaTestEnable );
		TEST_RENDER_STATEBLOCK_VALUE( AlphaFunc );
		TEST_RENDER_STATEBLOCK_VALUE( AlphaRef );
		TEST_RENDER_STATEBLOCK_VALUE( FillMode );
		TEST_RENDER_STATEBLOCK_VALUE( Lighting );
		TEST_RENDER_STATEBLOCK_VALUE( SpecularEnable );
		TEST_RENDER_STATEBLOCK_VALUE( SRGBWriteEnable );
		TEST_RENDER_STATEBLOCK_VALUE( AlphaBlendEnable );
		TEST_RENDER_STATEBLOCK_VALUE( SrcBlend );
		TEST_RENDER_STATEBLOCK_VALUE( DestBlend );

		TEST_TEXTURE_STATEBLOCK_VALUE( TexCoordIndex, pOp->m_Argument );
		TEST_TEXTURE_STATEBLOCK_VALUE( ColorOp, pOp->m_Argument );
		TEST_TEXTURE_STATEBLOCK_VALUE( ColorArg1, pOp->m_Argument );
		TEST_TEXTURE_STATEBLOCK_VALUE( ColorArg2, pOp->m_Argument );
		TEST_TEXTURE_STATEBLOCK_VALUE( AlphaOp, pOp->m_Argument );
		TEST_TEXTURE_STATEBLOCK_VALUE( AlphaArg1, pOp->m_Argument );
		TEST_TEXTURE_STATEBLOCK_VALUE( AlphaArg2, pOp->m_Argument );

		// Should never get here!
		Assert( 0 );
	}

	return true;
}


//-----------------------------------------------------------------------------
// Finds identical transition lists and shares them 
//-----------------------------------------------------------------------------
IDirect3DStateBlock9 *CTransitionTable::FindIdenticalStateBlock( TransitionList_t *pTransition, int toSnapshot ) const
{
	Assert( pTransition );

	// FIXME: Could we bake this into the identical transition list test?
	for ( int to = m_TransitionTable.Count(); --to >= 0; )
	{
		for ( int from = m_TransitionTable[to].Count(); --from >= 0; )
		{
			const TransitionList_t *pTest = &m_TransitionTable[to][from];

			// Ignore the transition we're currently working on
			if ( pTransition == pTest )
				continue;

			// Not only do the ops need to match, but so do the values the ops use in the snapshots
			if ( pTest->m_nOpCountInStateBlock != pTransition->m_nOpCountInStateBlock )
				continue;

			bool bFoundOpMatch = true;
			if ( pTest->m_FirstOperation != pTransition->m_FirstOperation )
			{
				const TransitionOp_t *pOp1 = &m_TransitionOps[pTest->m_FirstOperation];
				const TransitionOp_t *pOp2 = &m_TransitionOps[pTransition->m_FirstOperation];

				for ( int k = 0; k < pTransition->m_nOpCountInStateBlock; ++k )
				{
					if ( (pOp1->m_Op != pOp2->m_Op) || (pOp1->m_Argument != pOp2->m_Argument) )
					{
						bFoundOpMatch = false;
						break;
					}
					++pOp1, ++pOp2;
				}
			}

			if ( !bFoundOpMatch )
				continue;

			// Now we gotta check that the set values are the same.
			if ( !DoStateBlocksMatch( pTest, to, toSnapshot ) )
				continue;

			return pTest->m_pStateBlock;
		}
	}

	return NULL;
}

IDirect3DStateBlock9 *CTransitionTable::CreateStateBlock( TransitionList_t& list, int snapshot )
{
	Assert( list.m_NumOperations > 0 );
	
	HRESULT hr = D3DDevice()->BeginStateBlock( );
	Assert( !FAILED(hr) );

	// Necessary to set the bools so that the state blocks always have the info in them
	ApplyTransitionList( snapshot, list.m_FirstOperation, list.m_nOpCountInStateBlock );

	IDirect3DStateBlock9 *pStateBlock;
	hr = D3DDevice()->EndStateBlock( &pStateBlock );
	Assert( !FAILED(hr) );

	return pStateBlock;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -