📄 meshdx8.cpp
字号:
//=========== (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: $
//
// The dx8 implementation of the shader API
//=============================================================================
#include "locald3dtypes.h"
#include "IMeshDX8.h"
#include "ShaderAPIDX8_Global.h"
#include "tier0/vprof.h"
// fixme - stick this in a header file.
#ifdef _DEBUG
// define this if you want to range check all indices when drawing
#define CHECK_INDICES
#endif
#ifdef CHECK_INDICES
#define CHECK_INDICES_MAX_NUM_STREAMS 2
#endif
#include "DynamicIB.h"
#include "DynamicVB.h"
#include "UtlVector.h"
#include "ShaderAPI.h"
#include "IMaterialInternal.h"
#include "ShaderAPIDX8.h"
#include "IShaderUtil.h"
#include "CMaterialSystemStats.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "materialsystem/MaterialSystem_Config.h"
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Uncomment this to test buffered state
//-----------------------------------------------------------------------------
//#define DEBUG_BUFFERED_MESHES 1
//#define DRAW_SELECTION 1
//-----------------------------------------------------------------------------
// Important enumerations
//-----------------------------------------------------------------------------
enum
{
VERTEX_BUFFER_SIZE = 32768,
INDEX_BUFFER_SIZE = 32768,
};
//-----------------------------------------------------------------------------
// Standard vertex formats (must be sorted from smallest to largest)
//-----------------------------------------------------------------------------
static VertexFormat_t s_pStandardFormats[] =
{
// 32 byte formats
// position, color, two tex coordinates (32 bytes)
VERTEX_POSITION | VERTEX_COLOR |
VERTEX_NUM_TEXCOORDS(2) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2),
// position, normal, one tex coordinate (32 bytes)
VERTEX_POSITION | VERTEX_NORMAL |
VERTEX_NUM_TEXCOORDS(1) |
VERTEX_TEXCOORD_SIZE(0, 2),
// 48 byte formats
// position, normal, color, specular, two tex coordinates (48 bytes)
VERTEX_POSITION | VERTEX_COLOR | VERTEX_SPECULAR | VERTEX_NORMAL |
VERTEX_NUM_TEXCOORDS(2) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2),
// position, 2 bones, normal, color, one tex coord (48 bytes)
VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL |
VERTEX_BONEWEIGHT(2) | VERTEX_BONE_INDEX |
VERTEX_NUM_TEXCOORDS(1) | VERTEX_TEXCOORD_SIZE(0, 2),
// 64 byte formats
// position, normal, color, specular, four tex coordinates (64 bytes)
VERTEX_POSITION | VERTEX_COLOR | VERTEX_SPECULAR | VERTEX_NORMAL |
VERTEX_NUM_TEXCOORDS(4) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2) |
VERTEX_TEXCOORD_SIZE(2, 2) | VERTEX_TEXCOORD_SIZE(3, 2),
// position, 1 bone, normal, color, specular, four tex coords (64 bytes)
VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL |
VERTEX_BONEWEIGHT(1) |
VERTEX_NUM_TEXCOORDS(4) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2) |
VERTEX_TEXCOORD_SIZE(2, 2) | VERTEX_TEXCOORD_SIZE(3, 2),
// position, normal, color, four tex coordinates (64 bytes), 3d tex coord in stage 2
VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL |
VERTEX_NUM_TEXCOORDS(4) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2) |
VERTEX_TEXCOORD_SIZE(2, 3) | VERTEX_TEXCOORD_SIZE(3, 2),
// position, color, tangentS, tangentT, three tex coordinates (64 bytes)
VERTEX_POSITION | VERTEX_COLOR | VERTEX_TANGENT_S | VERTEX_TANGENT_T |
VERTEX_NUM_TEXCOORDS(3) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2) |
VERTEX_TEXCOORD_SIZE(2, 2),
// 80 byte formats
// Position, normal, color, specular, tangentS, tangentT, 3 2D tex coordinates (80 bytes)
VERTEX_POSITION | VERTEX_NORMAL | VERTEX_COLOR | VERTEX_SPECULAR | VERTEX_TANGENT_S | VERTEX_TANGENT_T |
VERTEX_NUM_TEXCOORDS(3) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2) |
VERTEX_TEXCOORD_SIZE(2, 2),
// Position, normal, tangentS, tangentT, 4 2D tex coordinates (80 bytes)
VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T |
VERTEX_NUM_TEXCOORDS(4) |
VERTEX_TEXCOORD_SIZE(0, 2) | VERTEX_TEXCOORD_SIZE(1, 2) |
VERTEX_TEXCOORD_SIZE(2, 2) | VERTEX_TEXCOORD_SIZE(3, 2),
// This must be last
0
};
//-----------------------------------------------------------------------------
// Shared mesh methods
//-----------------------------------------------------------------------------
class CBaseMeshDX8 : public IMeshDX8
{
public:
// constructor, destructor
CBaseMeshDX8();
virtual ~CBaseMeshDX8();
// Locks mesh for modifying
void ModifyBegin( int firstVertex, int numVerts, int firstIndex, int numIndices, MeshDesc_t& desc );
void ModifyEnd();
// Sets/gets the vertex format
virtual void SetVertexFormat( VertexFormat_t format );
virtual VertexFormat_t GetVertexFormat() const;
// Sets the material
virtual void SetMaterial( IMaterial* pMaterial );
// Uses pre-defined index buffers
void GenerateSequentialIndexBuffer( unsigned short* pIndexBuffer, int numIndices, int firstVertex );
void GenerateQuadIndexBuffer( unsigned short* pIndexBuffer, int numIndices, int firstVertex );
void GeneratePolygonIndexBuffer( unsigned short* pIndexBuffer, int numIndices, int firstVertex );
void GenerateLineStripIndexBuffer( unsigned short* pIndexMemory, int numIndices, int firstVertex );
void GenerateLineLoopIndexBuffer( unsigned short* pIndexMemory, int numIndices, int firstVertex );
// returns the # of vertices (static meshes only)
int NumVertices() const { return 0; }
void SetColorMesh( IMesh *pColorMesh )
{
Assert( 0 );
}
bool HasColorMesh( ) const { return false; }
// Draws the mesh
void DrawMesh( );
// Begins a pass
void BeginPass( );
// Spews the mesh data
void Spew( int numVerts, int numIndices, MeshDesc_t const& desc );
// Call this in debug mode to make sure our data is good.
virtual void ValidateData( int numVerts, int numIndices, MeshDesc_t const& desc );
void Draw( CPrimList *pLists, int nLists );
// Copy verts and/or indices to a mesh builder. This only works for temp meshes!
virtual void CopyToMeshBuilder(
int iStartVert, // Which vertices to copy.
int nVerts,
int iStartIndex, // Which indices to copy.
int nIndices,
int indexOffset, // This is added to each index.
CMeshBuilder &builder );
// returns the primitive type
virtual MaterialPrimitiveType_t GetPrimitiveType() const = 0;
// Returns the number of indices in a mesh..
virtual int NumIndices( ) const = 0;
// returns a static vertex buffer...
virtual CVertexBuffer* GetVertexBuffer() { return 0; }
virtual CIndexBuffer* GetIndexBuffer() { return 0; }
// Do I need to reset the vertex format?
virtual bool NeedsVertexFormatReset( VertexFormat_t fmt ) const;
// Do I have enough room?
virtual bool HasEnoughRoom( int numVerts, int numIndices ) const;
// Operation to do pre-lock
virtual void PreLock() {}
// Sets the software vertex shader
virtual void SetSoftwareVertexShader( SoftwareVertexShader_t shader ) = 0;
protected:
bool DebugTrace() const;
// The vertex format we're using...
VertexFormat_t m_VertexFormat;
#ifdef _DEBUG
IMaterialInternal* m_pMaterial;
bool m_IsDrawing;
#endif
};
//-----------------------------------------------------------------------------
// Implementation of the mesh
//-----------------------------------------------------------------------------
class CMeshDX8 : public CBaseMeshDX8
{
public:
// constructor
CMeshDX8( );
virtual ~CMeshDX8();
// Locks/unlocks the mesh
void LockMesh( int numVerts, int numIndices, MeshDesc_t& desc );
void UnlockMesh( int numVerts, int numIndices, MeshDesc_t& desc );
// Locks mesh for modifying
void ModifyBegin( int firstVertex, int numVerts, int firstIndex, int numIndices, MeshDesc_t& desc );
void ModifyEnd();
// returns the # of vertices (static meshes only)
int NumVertices() const;
// returns the # of indices
int NumIndices( ) const;
// Sets up the vertex and index buffers
void UseIndexBuffer( CIndexBuffer* pBuffer );
void UseVertexBuffer( CVertexBuffer* pBuffer );
// returns a static vertex buffer...
CVertexBuffer* GetVertexBuffer() { return m_pVertexBuffer; }
CIndexBuffer* GetIndexBuffer() { return m_pIndexBuffer; }
void SetColorMesh( IMesh *pColorMesh );
bool HasColorMesh( ) const;
// Draws the mesh
void Draw( int firstIndex, int numIndices );
void Draw( CPrimList *pLists, int nLists );
// Draws a single pass
void RenderPass();
// Sets the primitive type
void SetPrimitiveType( MaterialPrimitiveType_t type );
MaterialPrimitiveType_t GetPrimitiveType() const;
bool IsStatic() { return true; };
void SetSoftwareVertexShader( SoftwareVertexShader_t shader );
void CallSoftwareVertexShader( CMeshBuilder *pMeshBuilder );
protected:
// Sets the render state.
bool SetRenderState( int firstVertexIdx = 0 );
// Is the vertex format valid?
bool IsValidVertexFormat();
// Locks/ unlocks the vertex buffer
void LockVertexBuffer( int numVerts, MeshDesc_t& desc );
void UnlockVertexBuffer( int numVerts );
// Locks/unlocks the index buffer
// Pass in firstIndex=-1 to lock wherever the index buffer is. Pass in a value
// >= 0 to specify where to lock.
int LockIndexBuffer( int firstIndex, int numIndices, MeshDesc_t& pIndices );
void UnlockIndexBuffer( int numIndices );
// Computes the primitive mode
D3DPRIMITIVETYPE ComputeMode( MaterialPrimitiveType_t mode );
// computes how many primitives we've got
int NumPrimitives( int numVerts, int numIndices ) const;
// Debugging output...
void SpewMaterialVerts( );
// The vertex and index buffers
CVertexBuffer* m_pVertexBuffer;
CIndexBuffer* m_pIndexBuffer;
CMeshDX8 *m_pColorMesh;
// Primitive type
MaterialPrimitiveType_t m_Type;
// Primitive mode
D3DPRIMITIVETYPE m_Mode;
// Number of primitives
unsigned short m_NumVertices;
unsigned short m_NumIndices;
// Is it locked?
bool m_IsVBLocked;
bool m_IsIBLocked;
// Used in rendering sub-parts of the mesh
static CPrimList *s_pPrims;
static int s_nPrims;
static unsigned int s_FirstVertex;
static unsigned int s_NumVertices;
int m_FirstIndex;
#ifdef RECORDING
int m_LockVertexBufferSize;
void* m_LockVertexBuffer;
#endif
#if defined( RECORDING ) || defined( CHECK_INDICES )
void* m_LockIndexBuffer;
int m_LockIndexBufferSize;
#endif
};
//-----------------------------------------------------------------------------
// A little extra stuff for the dynamic version
//-----------------------------------------------------------------------------
class CDynamicMeshDX8 : public CMeshDX8
{
public:
// constructor, destructor
CDynamicMeshDX8();
virtual ~CDynamicMeshDX8();
// Sets the vertex format
void SetVertexFormat( VertexFormat_t format );
// Resets the state in case of a task switch
void Reset();
// Do I have enough room in the buffer?
bool HasEnoughRoom( int numVerts, int numIndices ) const;
// returns the # of indices
int NumIndices( ) const;
// Locks the mesh
void LockMesh( int numVerts, int numIndices, MeshDesc_t& desc );
// Unlocks the mesh
void UnlockMesh( int numVerts, int numIndices, MeshDesc_t& desc );
// Override vertex + index buffer
void OverrideVertexBuffer( CVertexBuffer* pStaticVertexBuffer );
void OverrideIndexBuffer( CIndexBuffer* pStaticIndexBuffer );
// Do I need to reset the vertex format?
bool NeedsVertexFormatReset(VertexFormat_t fmt) const;
// Draws it
void Draw( int firstIndex, int numIndices );
// Simply draws what's been buffered up immediately, without state change
void DrawSinglePassImmediately();
// Operation to do pre-lock
void PreLock();
bool IsStatic() { return false; };
virtual void SetSoftwareVertexShader( SoftwareVertexShader_t shader );
virtual void CallSoftwareVertexShader( CMeshBuilder *pMeshBuilder );
private:
// Resets buffering state
void ResetVertexAndIndexCounts();
// total queued vertices
int m_TotalVertices;
int m_TotalIndices;
// the first vertex and index since the last draw
int m_FirstVertex;
int m_FirstIndex;
// Have we drawn since the last lock?
bool m_HasDrawn;
// Any overrides?
bool m_VertexOverride;
bool m_IndexOverride;
SoftwareVertexShader_t m_SoftwareVertexShader;
};
//-----------------------------------------------------------------------------
// A mesh that stores temporary vertex data in the correct format (for modification)
//-----------------------------------------------------------------------------
class CTempMeshDX8 : public CBaseMeshDX8
{
public:
// constructor, destructor
CTempMeshDX8( bool isDynamic );
virtual ~CTempMeshDX8();
// Sets the material
void SetVertexFormat( VertexFormat_t format );
// Locks/unlocks the mesh
void LockMesh( int numVerts, int numIndices, MeshDesc_t& desc );
void UnlockMesh( int numVerts, int numIndices, MeshDesc_t& desc );
// Locks mesh for modifying
virtual void ModifyBegin( int firstVertex, int numVerts, int firstIndex, int numIndices, MeshDesc_t& desc );
virtual void ModifyEnd();
// Number of indices + vertices
int NumVertices() const;
int NumIndices() const;
// Sets the primitive type
void SetPrimitiveType( MaterialPrimitiveType_t type );
MaterialPrimitiveType_t GetPrimitiveType() const;
// Begins a pass
void BeginPass( );
// Draws a single pass
void RenderPass();
// Draws the entire beast
void Draw( int firstIndex, int numIndices );
virtual void CopyToMeshBuilder(
int iStartVert, // Which vertices to copy.
int nVerts,
int iStartIndex, // Which indices to copy.
int nIndices,
int indexOffset, // This is added to each index.
CMeshBuilder &builder );
virtual void SetSoftwareVertexShader( SoftwareVertexShader_t shader );
virtual void CallSoftwareVertexShader( CMeshBuilder *pMeshBuilder );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -