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

📄 transitiontable.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	ADD_RENDER_STATE_TRANSITION( AlphaFunc )
	ADD_RENDER_STATE_TRANSITION( AlphaRef )
	ADD_RENDER_STATE_TRANSITION( FillMode )
	ADD_RENDER_STATE_TRANSITION( Lighting )
	ADD_RENDER_STATE_TRANSITION( SpecularEnable )
	ADD_RENDER_STATE_TRANSITION( SRGBWriteEnable )

	// Some code for the non-trivial transitions
	if (m_bUsingStateBlocks)
	{
		numOps += CreateStateBlockTransitions( fromState, toState, bForce );
	}
	else
	{
		numOps += CreateNormalTransitions( fromState, toState, bForce );
	}

	int nOpsBeforeDynamicState = numOps;

	// NOTE: From here on down are transitions that depend on dynamic state
	// and which can therefore not appear in the state block
	ADD_RENDER_STATE_TRANSITION( ZBias )
	ADD_RENDER_STATE_TRANSITION( CullEnable )
	ADD_RENDER_STATE_TRANSITION( VertexBlendEnable )
	ADD_RENDER_STATE_TRANSITION( VertexShaderOverbright )

	int nStageCount = HardwareConfig()->GetNumTextureStages();
	for ( int i = 0; i < nStageCount; ++i )
	{
		ADD_TEXTURE_STAGE_STATE_TRANSITION( i, TextureEnable );
	}

	// Look for identical transition lists, and use those instead...
	TransitionList_t& transition = (from >= 0) ? 
							m_TransitionTable[to][from] : m_DefaultTransition;
	Assert( numOps <= 255 );
	transition.m_NumOperations = numOps;
	transition.m_nOpCountInStateBlock = nOpsBeforeDynamicState;
	transition.m_pStateBlock = NULL;

	// This condition can happen, and is valid. It occurs when we snapshot
	// state but do not generate a transition function for that state
	if (numOps == 0)
	{
		transition.m_FirstOperation = INVALID_TRANSITION_OP;
		return;
	}

	unsigned short identicalListFirstElem = FindIdenticalTransitionList( firstElem, numOps ); 
	if (identicalListFirstElem == INVALID_TRANSITION_OP)
	{
		transition.m_FirstOperation = firstElem;
		Assert( (int)firstElem + (int)numOps < 65535 );

		if( (int)firstElem + (int)numOps >= 65535 )
		{
			Warning("**** WARNING: Transition table overflow. Grab Brian\n");
		}
	}
	else
	{
		// Remove the transitions ops we made; use the duplicate copy
		transition.m_FirstOperation = identicalListFirstElem;
		m_TransitionOps.RemoveMultiple( firstElem, numOps );
	}

	if ( m_bUsingStateBlocks && transition.m_nOpCountInStateBlock != 0 )
	{
		// Find a transition list that matches *exactly* to share its state block 
		IDirect3DStateBlock9 *pStateBlock = (from >= 0) ? FindIdenticalStateBlock( &transition, to ) : NULL;
		if (pStateBlock)
		{
			transition.m_pStateBlock = pStateBlock;
			transition.m_pStateBlock->AddRef();
		}
		else
		{
			transition.m_pStateBlock = CreateStateBlock( transition, to );
		}
	}
}


//-----------------------------------------------------------------------------
// Tests a snapshot to see if it can be used
//-----------------------------------------------------------------------------

#define PERFORM_RENDER_STATE_TRANSITION( _state, _func )	\
	::Apply ## _func( _state, 0 );
#define PERFORM_TEXTURE_STAGE_STATE_TRANSITION( _state, _stage, _func )	\
	::Apply ## _func( _state, _stage );

bool CTransitionTable::TestShadowState( const ShadowState_t& state, const ShadowShaderState_t &shaderState )
{
	PERFORM_RENDER_STATE_TRANSITION( state, ZFunc )
	PERFORM_RENDER_STATE_TRANSITION( state, ZWriteEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, ZEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, ZBias )
	PERFORM_RENDER_STATE_TRANSITION( state, ColorWriteEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, AlphaBlend )
	PERFORM_RENDER_STATE_TRANSITION( state, AlphaTestEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, AlphaFunc )
	PERFORM_RENDER_STATE_TRANSITION( state, AlphaRef )
	PERFORM_RENDER_STATE_TRANSITION( state, FillMode )
	PERFORM_RENDER_STATE_TRANSITION( state, CullEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, Lighting )
	PERFORM_RENDER_STATE_TRANSITION( state, SpecularEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, SRGBWriteEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, VertexBlendEnable )
	PERFORM_RENDER_STATE_TRANSITION( state, VertexShaderOverbright )

	int i;
	int nStageCount = HardwareConfig()->GetNumTextureStages();
	for ( i = 0; i < nStageCount; ++i )
	{
		PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, ColorTextureStage );
		PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, AlphaTextureStage );
		PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, TexCoordIndex );
		PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, TextureEnable );
	}

	// Just make sure we've got a good snapshot
	RECORD_COMMAND( DX8_VALIDATE_DEVICE, 0 );

	DWORD numPasses;
	HRESULT hr = D3DDevice()->ValidateDevice( &numPasses );
	bool ok = !FAILED(hr);

	// Now set the board state to match the default state
	ApplyTransition( m_DefaultTransition, m_DefaultStateSnapshot );

	ShaderManager()->SetVertexShader( shaderState.m_VertexShader, shaderState.m_nStaticVshIndex );
	ShaderManager()->SetPixelShader( shaderState.m_PixelShader, shaderState.m_nStaticPshIndex );

	return ok;
}


//-----------------------------------------------------------------------------
// Finds identical transition lists and shares them 
//-----------------------------------------------------------------------------
unsigned short CTransitionTable::FindIdenticalTransitionList( unsigned short firstElem, 
														   unsigned short numOps ) const
{
	// Look for a common list
	const TransitionOp_t &op = m_TransitionOps[firstElem];
	int maxTest = firstElem - numOps;
	for (int i = 0; i < maxTest;  )
	{
		// Fast out...
		if ( (m_TransitionOps[i].m_Op != op.m_Op) ||
			 (m_TransitionOps[i].m_Argument != op.m_Argument) )
		{
			++i;
			continue;
		}

		unsigned short potentialMatch = (unsigned short )i;
		int matchCount = 1;
		++i;

		while( matchCount < numOps )
		{
			if ( (m_TransitionOps[i].m_Op != m_TransitionOps[firstElem+matchCount].m_Op) ||
				 (m_TransitionOps[i].m_Argument != m_TransitionOps[firstElem+matchCount].m_Argument) )
			{
				break;
			}

			++i;
			++matchCount;
		}

		if (matchCount == numOps)
			return potentialMatch;
	}

	return INVALID_TRANSITION_OP;
}


//-----------------------------------------------------------------------------
// Create startup snapshot
//-----------------------------------------------------------------------------
void CTransitionTable::TakeDefaultStateSnapshot( )
{
	if (m_DefaultStateSnapshot == -1)
	{
		m_DefaultStateSnapshot = TakeSnapshot();

		// This will create a transition which sets *all* shadowed state
		CreateTransitionTableEntry( m_DefaultStateSnapshot, -1 );
	}
}


//-----------------------------------------------------------------------------
// Applies the transition list
//-----------------------------------------------------------------------------
void CTransitionTable::ApplyTransitionList( int snapshot, int nFirstOp, int nOpCount )
{
	// Don't bother if there's nothing to do
	if (nOpCount > 0)
	{
		// Trying to avoid function overhead here
		ShadowState_t& shadowState = m_ShadowStateList[snapshot];
		TransitionOp_t* pTransitionOp = &m_TransitionOps[nFirstOp];

		for (int i = 0; i < nOpCount; ++i )
		{
			// invoke the transition method
			(*pTransitionOp->m_Op)(shadowState, pTransitionOp->m_Argument);
			++pTransitionOp;
			MaterialSystemStats()->IncrementCountedStat( MATERIAL_SYSTEM_STATS_SHADOW_STATE, 1 );
		}
	}
}


//-----------------------------------------------------------------------------
// Apply startup snapshot
//-----------------------------------------------------------------------------
#pragma warning( disable : 4189 )

void CTransitionTable::ApplyTransition( TransitionList_t& list, int snapshot )
{
	if ( ShaderAPI()->IsDeactivated() )
		return;

	// Transition lists when using state blocks have 2 parts: the first
	// is the stateblock part, which is states that are not related to
	// dynamic state at all; followed by states that *are* affected by dynamic state
	int nFirstOp = list.m_FirstOperation;
	int nOpCount = list.m_NumOperations;

	if ( m_bUsingStateBlocks )
	{
		if ( list.m_pStateBlock )
		{
			HRESULT hr = list.m_pStateBlock->Apply();
			Assert( !FAILED(hr) );
		}

		nFirstOp += list.m_nOpCountInStateBlock;
		nOpCount -= list.m_nOpCountInStateBlock;
	}

	ApplyTransitionList( snapshot, nFirstOp, nOpCount );

	// Semi-hacky code to override what the transitions are doing
	PerformShadowStateOverrides();

	// Set the current snapshot id
	m_CurrentShadowId = snapshot;

#ifdef DEBUG_BOARD_STATE
	// Copy over the board states that aren't explicitly in the transition table
	// so the assertion works...
	int nStageCount = HardwareConfig()->GetNumTextureStages();
	for (int i = 0; i < nStageCount; ++i)
	{
		m_BoardState.m_TextureStage[i].m_GenerateSphericalCoords = 
			CurrentShadowState().m_TextureStage[i].m_GenerateSphericalCoords;
	}
	m_BoardState.m_AmbientCubeOnStage0 = CurrentShadowState().m_AmbientCubeOnStage0;
	m_BoardState.m_ModulateConstantColor = CurrentShadowState().m_ModulateConstantColor;
	m_BoardState.m_VertexUsage = CurrentShadowState().m_VertexUsage;
	m_BoardState.m_UsingFixedFunction = CurrentShadowState().m_UsingFixedFunction;

	// State blocks bypass the code that sets the board state
	if ( !m_bUsingStateBlocks )
	{
		Assert( !memcmp( &m_BoardState, &CurrentShadowState(), sizeof(m_BoardState) ) );
	}
#endif
}

#pragma warning( default : 4189 )


//-----------------------------------------------------------------------------
// Takes a snapshot, hooks it into the material
//-----------------------------------------------------------------------------
StateSnapshot_t CTransitionTable::TakeSnapshot( )
{
	// Do any final computation of the shadow state
	ShaderShadow()->ComputeAggregateShadowState();

	// Get the current snapshot
	const ShadowState_t& currentState = ShaderShadow()->GetShadowState();

	// Create a new snapshot
	ShadowStateId_t shadowStateId = FindShadowState( currentState );
	if (shadowStateId == -1)
	{
		// Create entry in state transition table
		shadowStateId = CreateShadowState();

		// Copy our snapshot into the list
		memcpy( &m_ShadowStateList[shadowStateId], &currentState, sizeof(ShadowState_t) );

		// Now create new transition entries
		for (int to = 0; to < shadowStateId; ++to)
		{
			CreateTransitionTableEntry( to, shadowStateId );
		}

		for (int from = 0; from < shadowStateId; ++from)
		{
			CreateTransitionTableEntry( shadowStateId, from );
		}
	}

	const ShadowShaderState_t& currentShaderState = ShaderShadow()->GetShadowShaderState();
 	StateSnapshot_t snapshotId = FindStateSnapshot( shadowStateId, currentShaderState );
	if (snapshotId == -1)
	{
		// Create entry in state transition table
		snapshotId = CreateStateSnapshot();

		// Copy our snapshot into the list
		m_SnapshotList[snapshotId].m_ShadowStateId = shadowStateId;
		memcpy( &m_SnapshotList[snapshotId].m_ShaderState, &currentShaderState, sizeof(ShadowShaderState_t) );
	}

	return snapshotId;
}


⌨️ 快捷键说明

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