|
|
//===== 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
|