csgo-2018-source/engine/brushbatchrender.h
2021-07-24 21:11:47 -07:00

204 lines
7.5 KiB
C++

//===== Copyright 1996-2007, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef BRUSHBATCHRENDER_H
#define BRUSHBATCHRENDER_H
#ifdef _WIN32
#pragma once
#endif
// UNDONE: These are really guesses. Do we ever exceed these limits?
const int MAX_TRANS_NODES = 256;
const int MAX_TRANS_DECALS = 256;
const int MAX_TRANS_BATCHES = 1024;
const int MAX_TRANS_SURFACES = 1024;
class CBrushBatchRender
{
public:
// These are the compact structs produced by the brush render cache. The goal is to have a compact
// list of drawing instructions for drawing an opaque brush model in the most optimal order.
// These structs contain ONLY the opaque surfaces of a brush model.
struct brushrendersurface_t
{
short surfaceIndex;
short planeIndex;
};
// a batch is a list of surfaces with the same material - they can be drawn with one call to the materialsystem
struct brushrenderbatch_t
{
short firstSurface;
short surfaceCount;
IMaterial *pMaterial;
int sortID;
int indexCount;
};
// a mesh is a list of batches with the same vertex format.
struct brushrendermesh_t
{
short firstBatch;
short batchCount;
};
// This is the top-level struct containing all data necessary to render an opaque brush model in optimal order
struct brushrender_t
{
// UNDONE: Compact these arrays into a single allocation
// UNDONE: Compact entire struct to a single allocation? Store brushrender_t * in the linked list?
~brushrender_t()
{
delete[] pPlanes;
delete[] pMeshes;
delete[] pBatches;
delete[] pSurfaces;
pPlanes = NULL;
pMeshes = NULL;
pBatches = NULL;
pSurfaces = NULL;
}
cplane_t **pPlanes;
brushrendermesh_t *pMeshes;
brushrenderbatch_t *pBatches;
brushrendersurface_t *pSurfaces;
short planeCount;
short meshCount;
short batchCount;
short surfaceCount;
short totalIndexCount;
short totalVertexCount;
};
// Surfaces are stored in a list like this temporarily for sorting purposes only. The compact structs do not store these.
struct surfacelist_t
{
SurfaceHandle_t surfID;
short surfaceIndex;
short planeIndex;
};
// Builds a transrender_t, then executes it's drawing commands
void DrawTranslucentBrushModel( IMatRenderContext *pRenderContext, model_t *model, IClientEntity *baseentity );
void LevelInit();
brushrender_t *FindOrCreateRenderBatch( model_t *pModel );
void DrawOpaqueBrushModel( IMatRenderContext *pRenderContext, IClientEntity *baseentity, model_t *model, ERenderDepthMode_t DepthMode );
void DrawTranslucentBrushModel( IMatRenderContext *pRenderContext, IClientEntity *baseentity, model_t *model, ERenderDepthMode_t DepthMode, bool bDrawOpaque, bool bDrawTranslucent );
void DrawBrushModelShadow( IMatRenderContext *pRenderContext, model_t *model, IClientRenderable *pRenderable );
void DrawBrushModelArray( IMatRenderContext* pRenderContext, int nCount, const BrushArrayInstanceData_t *pInstanceData );
void DrawBrushModelShadowArray( IMatRenderContext* pRenderContext, int nCount, const BrushArrayInstanceData_t *pInstanceData, int nModelTypeFlags );
private:
struct BrushBatchRenderData_t
{
const BrushArrayInstanceData_t *m_pInstanceData;
IMaterial *m_pMaterial;
brushrender_t *m_pBrushRender;
uint16 m_nBatchIndex : 15;
uint16 m_nHasPaintedSurfaces : 1;
int16 m_nLightmapPage : 15;
uint16 m_nIsAlphaTested : 1;
};
// These are the compact structs produced for translucent brush models. These structs contain
// only the translucent surfaces of a brush model.
// a batch is a list of surfaces with the same material - they can be drawn with one call to the materialsystem
struct transbatch_t
{
short firstSurface;
short surfaceCount;
IMaterial *pMaterial;
int sortID;
int indexCount;
};
// This is a list of surfaces that have decals.
struct transdecal_t
{
short firstSurface;
short surfaceCount;
};
// A node is the list of batches that can be drawn without sorting errors. When no decals are present, surfaces
// from the next node may be appended to this one to improve performance without causing sorting errors.
struct transnode_t
{
short firstBatch;
short batchCount;
short firstDecalSurface;
short decalSurfaceCount;
};
// This is the top-level struct containing all data necessary to render a translucent brush model in optimal order.
// NOTE: Unlike the opaque struct, the order of the batches is view-dependent, so caching this is pointless since
// the view usually changes.
struct transrender_t
{
transnode_t nodes[MAX_TRANS_NODES];
SurfaceHandle_t surfaces[MAX_TRANS_SURFACES];
SurfaceHandle_t decalSurfaces[MAX_TRANS_DECALS];
transbatch_t batches[MAX_TRANS_BATCHES];
transbatch_t *pLastBatch; // These are used to append surfaces to existing batches across nodes.
transnode_t *pLastNode; // This improves performance.
short nodeCount;
short batchCount;
short surfaceCount;
short decalSurfaceCount;
};
struct BrushInstanceGroup_t
{
BrushBatchRenderData_t *m_pRenderData;
IMaterial *m_pActualMaterial;
IMaterial *m_pMaterial;
uint16 m_nCount : 15;
uint16 m_nHasPaintedSurfaces : 1;
uint16 m_nIndexCount;
};
private:
// build node lists
void BuildTransLists_r( transrender_t &render, model_t *model, mnode_t *node );
void DrawTransLists( IMatRenderContext *pRenderContext, transrender_t &render, void *pProxyData );
void AddSurfaceToBatch( transrender_t &render, transnode_t *pNode, transbatch_t *pBatch, SurfaceHandle_t surfID );
void AddTransNode( transrender_t &render );
void AddTransBatch( transrender_t &render, SurfaceHandle_t surfID );
void BuildBatchListToDraw( int nCount, const BrushArrayInstanceData_t *pInstanceData,
CUtlVectorFixedGrowable< BrushBatchRenderData_t, 1024 > &batchesToRender, brushrender_t **ppBrushRender );
bool DrawSortedBatchList( IMatRenderContext* pRenderContext, int nCount, BrushInstanceGroup_t *pInstanceGroup, int nMaxInstanceCount );
void DrawPaintForBatches( IMatRenderContext* pRenderContext, int nCount, const BrushInstanceGroup_t *pInstanceGroup, int nMaxInstanceCount );
void ComputeLightmapPages( int nCount, BrushBatchRenderData_t *pRenderData );
void ClearRenderHandles();
int ComputeInstanceGroups( IMatRenderContext *pRenderContext, int nCount, BrushBatchRenderData_t *pRenderData, CUtlVectorFixedGrowable< BrushInstanceGroup_t, 512 > &instanceGroups );
void DrawArrayDebugInformation( IMatRenderContext *pRenderContext, int nCount, const BrushBatchRenderData_t *pRenderData );
void DrawDecalsForBatches( IMatRenderContext *pRenderContext, int nCount, const BrushArrayInstanceData_t *pInstanceData, brushrender_t **ppBrushRender );
void BuildShadowBatchListToDraw( int nCount, const BrushArrayInstanceData_t *pInstanceData,
CUtlVectorFixedGrowable< BrushBatchRenderData_t, 1024 > &batchesToRender, int nModelTypeFlags );
void DrawShadowBatchList( IMatRenderContext* pRenderContext, int nCount, BrushInstanceGroup_t *pInstanceGroup, int nMaxInstanceCount );
static int __cdecl SurfaceCmp(const surfacelist_t *s0, const surfacelist_t *s1 );
static bool __cdecl BatchSortLessFunc( const BrushBatchRenderData_t &left, const BrushBatchRenderData_t &right );
static bool __cdecl ShadowSortLessFunc( const BrushBatchRenderData_t &left, const BrushBatchRenderData_t &right );
CThreadFastMutex m_Mutex;
CUtlLinkedList<brushrender_t*> m_renderList;
};
#if !defined( DEDICATED )
extern CBrushBatchRender g_BrushBatchRenderer;
#endif
#endif // BRUSHBATCHRENDER_H