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

📄 vertexshaderdx8.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Code for dealing with vertex shaders
//=============================================================================

#include <windows.h>
#include "VertexShaderDx8.h"
#include "UtlSymbol.h"
#include "UtlVector.h"
#include "UtlDict.h"
#include "locald3dtypes.h"
#include "ShaderAPIDX8_Global.h"
#include "recording.h"
#include "CMaterialSystemStats.h"
#include "tier0/vprof.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "shaderapidx8.h"
#include "materialsystem/ishader.h"
#include "utllinkedlist.h"
#include "materialsystem/ishadersystem.h"


// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"


//#define NO_AMBIENT_CUBE
#define MAX_BONES 3
#define MAX_LIGHTS 2


//-----------------------------------------------------------------------------
// Inserts the lighting block into the code
//-----------------------------------------------------------------------------

// If you change the number of lighting combinations, change this enum
enum
{
	LIGHTING_COMBINATION_COUNT = 22
};

// NOTE: These should match g_lightType* in vsh_prep.pl!
static int g_LightCombinations[][MAX_LIGHTS+2] = 
{
	// static		ambient				local1				local2

	// This is a special case for no lighting at all.
	{ LIGHT_NONE,	LIGHT_NONE,			LIGHT_NONE,			LIGHT_NONE },			

	// This is a special case so that we don't have to do the ambient cube
	// when we only have static lighting
	{ LIGHT_STATIC,	LIGHT_NONE,			LIGHT_NONE,			LIGHT_NONE },			

	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_NONE,			LIGHT_NONE },			
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_NONE },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_POINT,		LIGHT_NONE },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_DIRECTIONAL,	LIGHT_NONE },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_SPOT },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_POINT, },			
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_DIRECTIONAL, },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_POINT,		LIGHT_POINT, },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_POINT,		LIGHT_DIRECTIONAL, },
	{ LIGHT_NONE,	LIGHT_AMBIENTCUBE,	LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL, },

	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_NONE,			LIGHT_NONE },			
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_NONE },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_POINT,		LIGHT_NONE },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_DIRECTIONAL,	LIGHT_NONE },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_SPOT },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_POINT, },			
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_SPOT,			LIGHT_DIRECTIONAL, },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_POINT,		LIGHT_POINT, },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_POINT,		LIGHT_DIRECTIONAL, },
	{ LIGHT_STATIC,	LIGHT_AMBIENTCUBE,	LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL, },
	
/*
	{ LIGHT_NONE,			LIGHT_NONE },			// 0
	{ LIGHT_SPOT,			LIGHT_NONE },
	{ LIGHT_POINT,			LIGHT_NONE },
	{ LIGHT_DIRECTIONAL,	LIGHT_NONE },
	{ LIGHT_SPOT,			LIGHT_SPOT },

	{ LIGHT_SPOT,			LIGHT_POINT, },			// 5
	{ LIGHT_SPOT,			LIGHT_DIRECTIONAL, },
	{ LIGHT_POINT,			LIGHT_POINT, },
	{ LIGHT_POINT,			LIGHT_DIRECTIONAL, },
	{ LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL, },

	{ LIGHT_STATIC,			LIGHT_NONE },			// 10
*/

/*
	{ LIGHT_SPOT,			LIGHT_SPOT,			LIGHT_SPOT },			// 10
	{ LIGHT_SPOT,			LIGHT_SPOT,			LIGHT_POINT },
	{ LIGHT_SPOT,			LIGHT_SPOT,			LIGHT_DIRECTIONAL },
	{ LIGHT_SPOT,			LIGHT_POINT,		LIGHT_POINT },
	{ LIGHT_SPOT,			LIGHT_POINT,		LIGHT_DIRECTIONAL },

	{ LIGHT_SPOT,			LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL },	// 15
	{ LIGHT_POINT,			LIGHT_POINT,		LIGHT_POINT },
	{ LIGHT_POINT,			LIGHT_POINT,		LIGHT_DIRECTIONAL },
	{ LIGHT_POINT,			LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL },
	{ LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL,	LIGHT_DIRECTIONAL },
*/
};

static const char *GetLightTypeName( VertexShaderLightTypes_t type )
{
	static const char *s_VertexShaderLightTypeNames[] = 
	{
		"LIGHT_NONE",
		"LIGHT_SPOT",
		"LIGHT_POINT",
		"LIGHT_DIRECTIONAL",
		"LIGHT_STATIC",
		"LIGHT_AMBIENTCUBE",
	};
	return s_VertexShaderLightTypeNames[type+1];
}


//-----------------------------------------------------------------------------
// Computes the lighting type from the light types...
//-----------------------------------------------------------------------------
int ComputeLightIndex( int numLights, const VertexShaderLightTypes_t *pLightType, 
					  bool bUseAmbientCube, bool bHasColorMesh )
{
	COMPILE_TIME_ASSERT( LIGHTING_COMBINATION_COUNT == 
		sizeof( g_LightCombinations ) / sizeof( g_LightCombinations[0] ) );
	
	Assert( numLights <= MAX_LIGHTS );

	if( numLights == 0 && !bUseAmbientCube )
	{
		if( bHasColorMesh )
		{
			// special case for static lighting only
			return 1;
		}
		else
		{
			// special case for no lighting at all.
			return 0;
		}
	}
	
	int i;
	// hack - skip the first two for now since we don't know if the ambient cube is needed or not.
	for( i = 2; i < LIGHTING_COMBINATION_COUNT; ++i )
	{
		int j;
		for( j = 0; j < numLights; ++j )
		{
			if( pLightType[j] != g_LightCombinations[i][j+2] )
				break;
		}
		if( j == numLights )
		{
			while( j < MAX_LIGHTS )
			{
				if (g_LightCombinations[i][j+2] != LIGHT_NONE)
					break;
				++j;
			}
			if( j == MAX_LIGHTS )
			{
				if( bHasColorMesh )
				{
					return i + 10;
				}
				else
				{
					return i;
				}
			}
		}
	}

	// should never get here!
	Assert(0);
	return 0;
}


//-----------------------------------------------------------------------------
// Gets the vertex shader index given a number of bones, lights...
// FIXME: Let's try to remove this and make the shaders set the index
//-----------------------------------------------------------------------------
static int ComputeVertexShader( int nBoneCount, int nLightCombo, int nFogType, int fShaderFlags ) 
{
	Assert( nBoneCount <= MAX_BONES );

	// uses some combination of skinning, lighting, and fogging
	int nLightComboCount = LIGHTING_COMBINATION_COUNT;
	if ( ( fShaderFlags & SHADER_USES_LIGHTING ) == 0 )
	{
		nLightComboCount = 1;
		nLightCombo = 0;
	}

	bool bUsesHeightFog = ( nFogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
	int nFogComboCount = 1;
	int nFogCombo = 0;
	if ( fShaderFlags & SHADER_USES_HEIGHT_FOG )
	{
		nFogComboCount = 2;
		nFogCombo = bUsesHeightFog ? 1 : 0;
	}

#ifdef _DEBUG
	if ( bUsesHeightFog && !( fShaderFlags & SHADER_USES_HEIGHT_FOG ) )
	{
		// Doh!  Trying to use height fog with a vertex shader that doesn't support it!
		Assert( 0 );
	}
#endif

	int nSkinningComboCount = 1;
	if ( fShaderFlags & SHADER_USES_SKINNING )
	{
		nSkinningComboCount = MAX_BONES + 1; // + 1 since we have a combo for 0 bones.
	}

	int offset = ( ( ( nBoneCount * nLightComboCount ) + nLightCombo ) * nFogComboCount ) + nFogCombo;
	return offset;
}


//-----------------------------------------------------------------------------
// Shader dictionary
//-----------------------------------------------------------------------------
class CShaderDictionary
{
public:
	// Static methods
	static void CreateErrorPS();
	static void DestroyErrorPS();

	// Adds precompiled shader dictionaries
	void AddShaderDictionary( IPrecompiledShaderDictionary *pDict, bool bPreloadShaders );

	// Creates vertex + pixel shaders
	VertexShader_t CreateVertexShader( const char *pVertexShaderFile, int nStaticVshIndex = 0 );
	PixelShader_t CreatePixelShader( const char *pPixelShaderFile, int nStaticPshIndex = 0 );

	// Destroys vertex shaders
	void DestroyVertexShader( VertexShader_t shader );
	void DestroyAllVertexShaders();

	// Destroys pixel shaders
	void DestroyPixelShader( PixelShader_t shader );
	void DestroyAllPixelShaders();

	// Gets the hardware vertex shader
	HardwareVertexShader_t GetHardwareVertexShader( VertexShader_t shader, int vshIndex );
	HardwarePixelShader_t GetHardwarePixelShader( PixelShader_t shader, int pshIndex );

private:
	// Information associated with each VertexShader_t + PixelShader_t
	struct VertexShaderInfo_t
	{
		HardwareVertexShader_t *m_HardwareShaders;
		unsigned short	m_nRefCount;
		unsigned short	m_nShaderCount;
		unsigned char	m_Flags;
	};
	
	struct PixelShaderInfo_t
	{
		// GR - for binding shader list with pre-compiled DX shaders
		// for later shader creation
		const PrecompiledShader_t *m_pPrecompiledDXShader;
		HardwarePixelShader_t *m_HardwareShaders;
		unsigned short	m_nRefCount;
		unsigned short	m_nShaderCount;
	};

private:
	// Finds a precompiled shader
	const PrecompiledShader_t *LookupPrecompiledShader( PrecompiledShaderType_t type, const char *pShaderName );

	// Name-based lookup of vertex shaders
	int  FindVertexShader( char const* pFileName ) const;

	// Initializes vertex shaders
	bool InitializeVertexShaders( char const* pFileName, VertexShaderInfo_t& info );

	// The low-level dx call to set the vertex shader state
	void SetVertexShaderState( HardwareVertexShader_t shader );


	// Name-based lookup of pixel shaders
	int  FindPixelShader( char const* pFileName ) const;

	// Initializes pixel shaders
	bool InitializePixelShader( const char *pFileName, PixelShaderInfo_t &info );

	// The low-level dx call to set the pixel shader state
	void SetPixelShaderState( HardwarePixelShader_t shader );

private:
	// Precompiled shader dictionary
	CUtlDict< const PrecompiledShader_t*, unsigned short > m_PrecompiledShaders[PRECOMPILED_SHADER_TYPE_COUNT];

	// Used to lookup vertex shaders
	CUtlDict< VertexShaderInfo_t, unsigned short > m_VertexShaders;
	CUtlDict< PixelShaderInfo_t, unsigned short > m_PixelShaders;

	// GR - hack for illegal materials
	static HardwarePixelShader_t s_pIllegalMaterialPS;
};


//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
HardwarePixelShader_t CShaderDictionary::s_pIllegalMaterialPS = INVALID_HARDWARE_PIXEL_SHADER;


//-----------------------------------------------------------------------------
// Static methods
//-----------------------------------------------------------------------------
void CShaderDictionary::CreateErrorPS()
{
	// GR - illegal material hack
	if( HardwareConfig()->SupportsVertexAndPixelShaders() )
	{
		// GR - hack for illegal materials
		const DWORD psIllegalMaterial[] =
		{
			0xffff0101, 0x00000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 
			0x3f800000, 0x00000001, 0x800f0000, 0xa0e40000, 0x0000ffff
		};

		// create default shader
		D3DDevice()->CreatePixelShader( psIllegalMaterial, &s_pIllegalMaterialPS );
	}
}

void CShaderDictionary::DestroyErrorPS()
{
	// GR - invalid material hack
	// destroy internal shader
	if( s_pIllegalMaterialPS != INVALID_HARDWARE_PIXEL_SHADER )
	{
		s_pIllegalMaterialPS->Release();
		s_pIllegalMaterialPS = INVALID_HARDWARE_PIXEL_SHADER;
	}
}


//-----------------------------------------------------------------------------
// Adds precompiled shader dictionaries
//-----------------------------------------------------------------------------
void CShaderDictionary::AddShaderDictionary( IPrecompiledShaderDictionary *pDict, bool bPreloadShaders )
{
	int nCount = pDict->ShaderCount();
	
	for ( int i = 0; i < nCount; ++i )
	{
		const PrecompiledShader_t *pShader = pDict->GetShader(i);
		m_PrecompiledShaders[pDict->GetType()].Insert( pShader->m_pName, pShader );
	}

	// Create these up front in dx9 since we don't care about the vertex format.
	if ( bPreloadShaders )
	{
		VPROF( "PreloadVertexAndPixelShaders" );

		// Preload shaders
		switch ( pDict->GetType() )
		{
		case PRECOMPILED_VERTEX_SHADER:
			{
				for ( int i = 0; i < nCount; ++i )
				{
					CreateVertexShader( pDict->GetShader(i)->m_pName );
				}
			}
			break;

		case PRECOMPILED_PIXEL_SHADER:
			{
				for ( int i = 0; i < nCount; ++i )

⌨️ 快捷键说明

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