Files
FC1/RenderDll/Common/RendElements/CRETriMeshShadow.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

247 lines
7.3 KiB
C++

#include "RenderPCH.h"
#include "RendElement.h"
#include "CRETriMeshShadow.h"
#include "I3DEngine.h"
// shadow volumes rendering modified by vlad
// shadow volumes statistics
int CRETriMeshShadow::m_nCRETriMeshShadowRebuildsPerFrrame = 0;
int CRETriMeshShadow::m_nCRETriMeshShadowShadowsPerFrrame = 0;
int CRETriMeshShadow::m_nCRETriMeshShadowAloocatedShadows = 0;
//////////////////////////////////////////////////////////////////////
void CRETriMeshShadow::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
//////////////////////////////////////////////////////////////////////
void *CRETriMeshShadow::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
{
switch (ePT)
{
case eSrcPointer_Vert:
{
if(m_nCurrInst<0)
{
// Warning( 0,0,"Error: CRETriMeshShadow::mfGetPointer: m_nCurrInst<0");
return NULL;
}
*Stride = m_VertexSize[m_arrLBuffers[m_nCurrInst].pVB->m_pVertexBuffer->m_vertexformat];
if(m_arrLBuffers[m_nCurrInst].pVB->m_pVertexBuffer)
return m_arrLBuffers[m_nCurrInst].pVB->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
else
Warning( 0,0,"Error: CRETriMeshShadow::mfGetPointer: m_pBuffer->m_pVertexBuffer == 0");
}
break;
}
return NULL;
}
int CRETriMeshShadow::GetAndResetRebuildsPerFrrameCounter()
{
int n = m_nCRETriMeshShadowRebuildsPerFrrame;
m_nCRETriMeshShadowRebuildsPerFrrame = 0;
return n;
}
int CRETriMeshShadow::GetAndResetShadowVolumesPerFrrameCounter()
{
int n = m_nCRETriMeshShadowShadowsPerFrrame;
m_nCRETriMeshShadowShadowsPerFrrame = 0;
return n;
}
int CRETriMeshShadow::GetShadowVolumesAllocatedCounter()
{
return m_nCRETriMeshShadowAloocatedShadows;
}
bool CRETriMeshShadow::mfCheckUpdate(int nVertFormat, int Flags)
{
if(m_bAnimatedObject)
{ // character animation: everything already calculated, always use slot 0
m_nCurrInst = 0; // will be used during drawing
ShadVolInstanceInfo * pSVInfo = &m_arrLBuffers[0];
if (pSVInfo->pVB->m_pMats && pSVInfo->pVB->m_pMats->Count() && pSVInfo->pVB->m_pMats->Get(0)->pRE)
return pSVInfo->pVB->m_pMats->Get(0)->pRE->mfCheckUpdate(nVertFormat, Flags);
return false;
}
m_nCRETriMeshShadowShadowsPerFrrame++;
assert(m_nCurrInst == -1);
// find light of this shadow
CDLight * pDLight = NULL;
if (gRenDev->m_RP.m_DynLMask)
{
for (int n=0; n<gRenDev->m_RP.m_DLights[SRendItem::m_RecurseLevel].Num(); n++)
{
if (gRenDev->m_RP.m_DynLMask & (1<<n))
{
pDLight = gRenDev->m_RP.m_DLights[SRendItem::m_RecurseLevel][n];
break;
}
}
}
if (!pDLight)
return true;
CDLight fakeLight;
fakeLight = *pDLight; // do not copy
// get obj space light pos
CCObject *pObj = gRenDev->m_RP.m_pCurObject;
Matrix44& tInvRot = pObj->GetInvMatrix();
fakeLight.m_vObjectSpacePos = tInvRot.TransformPointOLD(fakeLight.m_Origin);
// assert(m_nCurrInst==-1);
// todo: take radius into account
//assert(pObj->m_CustomData);
// find buffer for this case
ShadVolInstanceInfo * pSVInfo = 0;
for(int i=0; i<MAX_SV_INSTANCES; i++) // find static volume by light objspace position
if(m_arrLBuffers[i].pVB && IsEquivalent(m_arrLBuffers[i].vObjSpaceLightPos, fakeLight.m_vObjectSpacePos, 0.001f))
{
pSVInfo = &m_arrLBuffers[i];
pSVInfo->nFrameId = gRenDev->GetFrameID();
m_nCurrInst = i;
break;
}
if(!pSVInfo) // if not found - select new slot
{
// now find same combination of light and shadow caster
// but only if slot was not used in prev frame -
// outomagic double buffering of dynamic shadows
for(int i=0; i<MAX_SV_INSTANCES; i++)
if( m_arrLBuffers[i].pVB &&
m_arrLBuffers[i].pLightOwner == fakeLight.m_pOwner &&
m_arrLBuffers[i].pShadowCaster == pObj->m_CustomData &&
m_arrLBuffers[i].nFrameId+1 < gRenDev->GetFrameID())
{
pSVInfo = &m_arrLBuffers[i];
m_nCurrInst = i;
break;
}
if(!pSVInfo) // if still not found
{ // find empty slot or slot with smallest frame id
int nSmalestFrameId = gRenDev->GetFrameID()+1;
for(int i=0; i<MAX_SV_INSTANCES; i++)
{
if(!m_arrLBuffers[i].pVB)
{ // search for free slot
pSVInfo = &m_arrLBuffers[i];
m_nCurrInst = i;
nSmalestFrameId=0;
break;
}
if(m_arrLBuffers[i].nFrameId<nSmalestFrameId)
{ // search for oldest slot at the same time
nSmalestFrameId = m_arrLBuffers[i].nFrameId;
pSVInfo = &m_arrLBuffers[i];
m_nCurrInst = i;
}
}
}
if(pSVInfo)
{
pSVInfo->nFrameId = gRenDev->GetFrameID();
pSVInfo->vObjSpaceLightPos = fakeLight.m_vObjectSpacePos;
pSVInfo->pLightOwner = fakeLight.m_pOwner;
pSVInfo->pShadowCaster = (IEntityRender*)pObj->m_CustomData;
}
if(!pSVInfo->pVB)
m_nCRETriMeshShadowAloocatedShadows++; // will be created now
// pSVInfo will be used in RebuildDynamicShadowVolumeBuffer
m_pSvObj->RebuildShadowVolumeBuffer(fakeLight, pObj->m_TempVars[0]);
m_nCRETriMeshShadowRebuildsPerFrrame++;
// if(!pSVInfo->pVB)
// iLog->Log("Warning: CRETriMeshShadow::mfCheckUpdate: !pSVInfo->pVB");
/*
ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3 && pSVInfo->pVB)
iLog->Log("CRETriMeshShadow: Static shadow volume created: %d faces", pSVInfo->pVB->GetIndices().Count()/3);*/
}
if (pSVInfo->pVB &&
pSVInfo->pVB->m_pMats &&
pSVInfo->pVB->m_pMats->Count() &&
pSVInfo->pVB->m_pMats->Get(0)->pRE)
pSVInfo->pVB->m_pMats->Get(0)->pRE->mfCheckUpdate(nVertFormat, Flags);
else
m_nCurrInst = -1;
fakeLight.m_vObjectSpacePos = Vec3d(0,0,0);
#ifdef DIRECT3D8
assert(0); // not tested, what this line do?
gRenDev->m_RP.m_CurD3DVFormat = pSVInfo->pVB->m_pSecVertBuffer->m_vertexformat + 16;
#endif
return true;
}
CRETriMeshShadow::~CRETriMeshShadow()
{
for(int i=0; i<MAX_SV_INSTANCES; i++)
{
gRenDev->DeleteLeafBuffer(m_arrLBuffers[i].pVB);
m_arrLBuffers[i].pVB=0;
}
}
bool CRETriMeshShadow::mfCheckUnload()
{ // remove all not used leafbuffers
for(int i=0; i<MAX_SV_INSTANCES; i++)
if(m_arrLBuffers[i].pVB)
{
if(m_arrLBuffers[i].nFrameId < gRenDev->GetFrameID()-100)
{
gRenDev->DeleteLeafBuffer(m_arrLBuffers[i].pVB);
m_arrLBuffers[i].pVB=0;
m_arrLBuffers[i].nFrameId=0;
m_nCRETriMeshShadowAloocatedShadows--;
}
}
/*
if(nLastCRETriMeshShadowLogFrame != gRenDev->GetFrameID())
{
int nRebNum = GetRETriMeshShadowRebuildsPerFrrame()/32;;
int nShadNum = GetRETriMeshShadowShadowsPerFrrame()/32;
ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3)
iLog->Log("CRETriMeshShadow: Allocated: %d, Used: %d, Updated: %d",
nCRETriMeshShadowAloocatedShadows, nShadNum, nRebNum);
nLastCRETriMeshShadowLogFrame = gRenDev->GetFrameID();
}*/
return true;
}
void CRETriMeshShadow::PrintStats()
{
gRenDev->TextToScreenColor(8,20, 0,2,0,1, "Shadow volumes stats: Rebuild: %d, Used: %d, Allocated: %d",
CRETriMeshShadow::GetAndResetRebuildsPerFrrameCounter(),
CRETriMeshShadow::GetAndResetShadowVolumesPerFrrameCounter(),
CRETriMeshShadow::GetShadowVolumesAllocatedCounter());
}