Files
GTASource/game/renderer/PlantsGrassRenderer.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

1175 lines
33 KiB
C++

//
// PlantsGrassRenderer - constains lowlevel rendering classes for CPlantMgr: CGrassRenderer & CPPTriPlantBuffer;
//
// 30/06/2005 - Andrzej: - initial port from SA to Rage;
//
//
//
//
//
#ifndef __CPLANTGRASSRENDERER_H__
#define __CPLANTGRASSRENDERER_H__
struct CellGcmContextData;
#include "renderer\PlantsMgr.h"
#include "renderer\PlantsGrassRendererSwitches.h"
//
//
//
//
#define PPTRIPLANT_MODELS_TAB_SIZE (4)
//
//
//
//
#if PSN_PLANTSMGR_SPU_RENDER
#define PPTRIPLANT_BUFFER_SIZE (36) // 36*112=4032 (fits into 4KB buffer)
#else
#define PPTRIPLANT_BUFFER_SIZE (64)
#endif
//
//
//
//
struct PPTriPlant
{
public:
Vector4 V1, V2, V3; // 3 vertices
// V1.w = wind_bend_scale; // wind bending scale
// V2.w = wind_bend_var; // wind bending variation
Float16Vec4 packedScale; // x = SxSy, y = Sz, z = scale_var_xy, w = scale_var_z
Float16Vec4 um_param;
Float16Vec2 scaleRangeXYZ_Z; // x=scaleXYZ, y=scaleZ
// 64
u16 num_plants; // num plants to generate
atFixedBitSet16 flags; // ProcPlantFlags: bitmask for enabled LODs and misc flags
#if PSN_PLANTSMGR_SPU_RENDER
u8 texture_id; // number of texture to use
u8 textureLOD1_id; // number of LOD1 texture to use
u8 intensity; // scale value for the colour
u8 intensity_var; // variation of intensity value
#else
grcTexture *texture_ptr; // ptr to texture to use
grcTexture *textureLOD1_ptr; // ptr to textureLOD1 to use
u8 intensity; // scale value for the colour
u8 intensity_var; // variation of intensity value
u8 ambient_scl;
u8 __pad00;
#endif
Color32 color; // color of the model
u32 seed; // seed starting value for this triangle;
Float16Vec2 coll_params; // collision params: [radiusSqr | invRadiusSqr]
// 92
Color32 groundColorV1, groundColorV2, groundColorV3;
Float16Vec4 skewAxisAngle; // ground skewing: xyz=skew axis, w=skew angle (if 0, then no skewing)
s8 loctri_normal[3]; // packed loctri normal: x,y,z
u8 model_id; // model_id used to calculate offset address for model in VU mem
#if CPLANT_CLIP_EDGE_VERT
bool m_ClipEdge_01 :1;
bool m_ClipEdge_12 :1;
bool m_ClipEdge_20 :1;
bool m_ClipVert_0 :1;
bool m_ClipVert_1 :1;
bool m_ClipVert_2 :1;
u8 __pad02 :2;
#endif
#if PSN_PLANTSMGR_SPU_RENDER
#define PSN_SIZEOF_PPTRIPLANT (112) // SPU: size of this struct must be dma'able
#endif
public:
static inline void GenPointInTriangle(Vector3 *pRes, const Vector3 *V1, const Vector3 *V2, const Vector3 *V3, float s, float t);
static inline void GenPointInTriangle(Vector4 *pRes, const Vector4 *V1, const Vector4 *V2, const Vector4 *V3, float s, float t);
static inline void ApplyGroundDensity(float& s, float& t, float densityS, float densityT);
};
//
//
// translated from Andrez's VU code...
//
// Based on Turk's algorithm:
//
// s = rand[0; 1]
// t = rand[0; 1]
//
inline
void PPTriPlant::GenPointInTriangle(Vector3 *pRes, const Vector3 *V1, const Vector3 *V2, const Vector3 *V3, float s, float t)
{
if((s+t) > 1.0f)
{
s = 1.0f - s;
t = 1.0f - t;
}
const float a = s;
const float b = t;
const float c = 1.0f - s - t;
pRes->x = a*V1->x + b*V2->x + c*V3->x;
pRes->y = a*V1->y + b*V2->y + c*V3->y;
pRes->z = a*V1->z + b*V2->z + c*V3->z;
}
inline
void PPTriPlant::GenPointInTriangle(Vector4 *pRes, const Vector4 *V1, const Vector4 *V2, const Vector4 *V3, float s, float t)
{
if((s+t) > 1.0f)
{
s = 1.0f - s;
t = 1.0f - t;
}
const float a = s;
const float b = t;
const float c = 1.0f - s - t;
pRes->x = a*V1->x + b*V2->x + c*V3->x;
pRes->y = a*V1->y + b*V2->y + c*V3->y;
pRes->z = a*V1->z + b*V2->z + c*V3->z;
pRes->w = a*V1->w + b*V2->w + c*V3->w;
}
//
//
// note: denistyS and densityT must be 2 smallest densities:
//
inline
void PPTriPlant::ApplyGroundDensity(float& s, float& t, float densityS, float densityT)
{
if((s+t) > 1.0f)
{
s = 1.0f - s;
t = 1.0f - t;
}
s *= densityS;
t *= densityT;
}
#if !__SPU
class CPPTriPlantBuffer; // forward definition
enum CGrassRenderer_PlantLod
{
PLANTLOD_LOW=0,
PLANTLOD_MEDIUM,
PLANTLOD_HIGH,
PLANTLOD_COUNT
};
class CGrassShadowParams
{
public:
CGrassShadowParams()
{
fadeNear = 10.0f;
fadeFar = 30.0f;
}
~CGrassShadowParams()
{
}
public:
float fadeNear;
float fadeFar;
PAR_SIMPLE_PARSABLE;
};
class CGrassShadowParams_AllLODs
{
public:
CGrassShadowParams_AllLODs()
{
}
~CGrassShadowParams_AllLODs()
{
}
public:
CGrassShadowParams m_AllLods[PLANTLOD_COUNT];
PAR_SIMPLE_PARSABLE;
};
class CGrassScalingParams
{
public:
CGrassScalingParams()
{
distanceMultiplier = 1.0f;
densityMultiplier = 1.0f;
}
~CGrassScalingParams()
{
}
public:
float distanceMultiplier;
float densityMultiplier;
PAR_SIMPLE_PARSABLE;
};
class CGrassScalingParams_AllLODs
{
public:
CGrassScalingParams_AllLODs()
{
}
~CGrassScalingParams_AllLODs()
{
}
public:
CGrassScalingParams m_AllLods[PLANTLOD_COUNT];
PAR_SIMPLE_PARSABLE;
};
//
//
//
//
class CGrassRenderer
{
friend class CPlantMgr;
friend class CPPTriPlantBuffer;
private:
struct instGrassDataDrawStruct
{
Matrix44 m_WorldMatrix;
Color32 m_PlantColor32;
Color32 m_GroundColorAmbient32;
};
public:
#if GRASS_INSTANCING
#if PLANTSMGR_MULTI_RENDER
#define CGRASS_RENDERER_LOD_BUCKET_SIZE (24)
#else
#define CGRASS_RENDERER_LOD_BUCKET_SIZE (16)
#endif
class InstanceBucket
{
public:
InstanceBucket();
virtual ~InstanceBucket();
public:
void Init(grmShader *pShader, grcEffectVar textureVar);
void ShutDown();
public:
#if PLANTSMGR_MULTI_RENDER
void Reset(u8 rti, grcEffectTechnique techId);
bool AddInstance(u8 rti, bool bMainRT, grmGeometry *pGeometry, grcTexture *pTexture, struct instGrassDataDrawStruct *pInstance, const Vec4V &umParams, const Vec2V &collParams);
virtual void Flush(u8 rti);
bool IsFull(u8 rti) { return(m_PerThreadData0[rti].m_noOfInstances == GRASS_INSTANCING_BUCKET_SIZE); }
static float PackColour(Vector4 &c);
grmGeometry* GetGeometry(u8 rti) { return m_PerThreadData0[rti].m_pCurrentGeometry; }
grcTexture* GetTexture(u8 rti) { return m_PerThreadData0[rti].m_pCurrentTexture; }
u32 GetCount(u8 rti) { return m_PerThreadData0[rti].m_noOfInstances; }
#else //PLANTSMGR_MULTI_RENDER...
void Reset(grcEffectTechnique techId);
void AddInstance(grmGeometry *pGeometry, grcTexture *pTexture, struct instGrassDataDrawStruct *pInstance, const Vec4V &umParams, const Vec2V &collParams);
__forceinline void BeginInstance(grmGeometry *pGeometry, grcTexture *pTexture)
{
// Have we reached capacity or is the geometry/texture different ?
if(IsFull() || (pGeometry != m_PerThreadData[g_RenderThreadIndex].m_pCurrentGeometry) || (pTexture != m_PerThreadData[g_RenderThreadIndex].m_pCurrentTexture))
{
// Send all instances.
Flush();
// Record texture/geometry.
m_PerThreadData[g_RenderThreadIndex].m_pCurrentTexture = pTexture;
m_PerThreadData[g_RenderThreadIndex].m_pCurrentGeometry = pGeometry;
}
}
__forceinline void LockTexture()
{
if(!m_PerThreadData[g_RenderThreadIndex].m_isInstanceTextureLocked)
{
if (LockTransport())
m_PerThreadData[g_RenderThreadIndex].m_isInstanceTextureLocked = true;
}
}
__forceinline void AddInstanceDirect(struct instGrassDataDrawStruct *pInstance, const Vec4V &umParams, const Vec2V &collParams)
{
if(IsFull())
{
Flush();
LockTexture();
}
Vector4 *pDest = GetDataPtr();
// Pack the instance data.
Vector4 C0 = pInstance->m_WorldMatrix.a;
Vector4 C1 = pInstance->m_WorldMatrix.b;
Vector4 C2 = pInstance->m_WorldMatrix.c;
Vector4 C3 = pInstance->m_WorldMatrix.d;
*((Color32*)(&C0.w)) = pInstance->m_PlantColor32; // pack directly as u32
*((Color32*)(&C1.w)) = pInstance->m_GroundColorAmbient32; // pack directly as u32
C2.w = collParams.GetXf();
C3.w = collParams.GetYf();
pDest[0] = C0;
pDest[1] = C1;
pDest[2] = C2;
pDest[3] = C3;
pDest[4] = VEC4V_TO_VECTOR4(umParams);
// Increment the count.
m_PerThreadData[g_RenderThreadIndex].m_noOfInstances++;
}
virtual void Flush();
bool IsFull() { return(m_PerThreadData[g_RenderThreadIndex].m_noOfInstances == GRASS_INSTANCING_BUCKET_SIZE); }
static float PackColour(Vector4 &c);
grmGeometry *GetGeometry() { return m_PerThreadData[g_RenderThreadIndex].m_pCurrentGeometry; }
grcTexture *GetTexture() { return m_PerThreadData[g_RenderThreadIndex].m_pCurrentTexture; }
u32 GetCount() { return m_PerThreadData[g_RenderThreadIndex].m_noOfInstances; }
#endif //PLANTSMGR_MULTI_RENDER...
protected:
#if PLANTSMGR_MULTI_RENDER
void InitialiseTransport();
void CleanUpTransport();
#if GRASS_INSTANCING_TRANSPORT_CONSTANT_BUFFERS
bool LockTransport(u8) {};
void UnlockTransport() {};
Vector4* GetDataPtr(u8 rti)
{
Vector4 *pDest = &m_pLockBase0[rti][ m_PerThreadData0[rti].m_noOfInstances*GRASS_INSTANCING_INSTANCE_SIZE ];
return pDest;
}
#else
bool LockTransport(u8 rti);
void UnlockTransport();
Vector4 *GetDataPtr(u8 rti);
#endif
void BindTransport(u8 rti);
#else //PLANTSMGR_MULTI_RENDER...
void InitialiseTransport();
void CleanUpTransport();
#if GRASS_INSTANCING_TRANSPORT_CONSTANT_BUFFERS
bool LockTransport() { return true; };
void UnlockTransport() {};
__forceinline Vector4* GetDataPtr()
{
Vector4 *pDest = &m_pLockBase[g_RenderThreadIndex][m_PerThreadData[g_RenderThreadIndex].m_noOfInstances*GRASS_INSTANCING_INSTANCE_SIZE];
return pDest;
}
#else
bool LockTransport();
void UnlockTransport();
Vector4* GetDataPtr();
#endif
void BindTransport();
#endif //PLANTSMGR_MULTI_RENDER...
#if GRASS_INSTANCING_TRANSPORT_CONSTANT_BUFFERS
void UnbindTransport()
{
#if RSG_PC && __D3D11
GRCDEVICE.SetVertexShaderConstantBufferOverrides(0, NULL, 0);
#endif
}
#else
void UnbindTransport();
#endif
protected:
grmShader *m_pShader;
grcEffectVar m_textureVar;
struct PER_THREAD_DATA
{
grcEffectTechnique m_techId;
u32 m_noOfInstances;
bool m_isInstanceTextureLocked;
grmGeometry *m_pCurrentGeometry;
grcTexture *m_pCurrentTexture;
};
#if PLANTSMGR_MULTI_RENDER
PER_THREAD_DATA m_PerThreadData0[NUMBER_OF_RENDER_THREADS];
#else
PER_THREAD_DATA m_PerThreadData[NUMBER_OF_RENDER_THREADS];
#endif
#if GRASS_INSTANCING_TRANSPORT_TEXTURE
grcEffectVar m_instanceTextureVar;
grcTexture *m_pInstanceTexture;
grcTextureLock m_instanceTextureLock[NUMBER_OF_RENDER_THREADS];
#endif // GRASS_INSTANCING_TRANSPORT_TEXTURE
#if GRASS_INSTANCING_TRANSPORT_CONSTANT_BUFFERS
u32 m_VertexShaderRegister;
grcCBuffer *m_pCBuffer;
#if PLANTSMGR_MULTI_RENDER
Vector4 *m_pLockBase0[NUMBER_OF_RENDER_THREADS];
#else
Vector4 *m_pLockBase[NUMBER_OF_RENDER_THREADS];
#endif
#endif // GRASS_INSTANCING_TRANSPORT_CONSTANT_BUFFERS
};
class InstanceBucket_LOD2 : public InstanceBucket
{
public:
InstanceBucket_LOD2();
virtual ~InstanceBucket_LOD2();
public:
#if PLANTSMGR_MULTI_RENDER
void Flush(u8 rti);
#else
void Flush();
#endif
};
template <u32 N>
class LODBucket
{
public:
LODBucket()
{
u32 i;
for(i=0; i<N; i++)
{
m_pInstanceBuckets[i] = NULL;
}
}
~LODBucket()
{
}
public:
void SetBucket(u32 idx, InstanceBucket *pBucket)
{
Assert(idx < N);
m_pInstanceBuckets[idx] = pBucket;
}
#if PLANTSMGR_MULTI_RENDER
void Reset(u8 rti, grcEffectTechnique techId)
{
for(s32 i=0; i<N; i++)
{
m_pInstanceBuckets[i]->Reset(rti, techId);
}
}
void Flush(u8 rti)
{
for(s32 i=0; i<N; i++)
{
m_pInstanceBuckets[i]->Flush(rti);
}
}
void FlushAlmostFull(u8 rti)
{
u32 maxAmount = 0;
s32 maxIdx = -1;
u32 minAmount = 0xffffffff;
s32 minIdx = -1;
bool bFlushed = false;
for(s32 i=0; i<N; i++)
{
//if(m_pInstanceBuckets[i]->IsFull(rti))
if(m_pInstanceBuckets[i]->GetCount(rti) >= u32(GRASS_INSTANCING_BUCKET_SIZE*0.80f)) // flush if 80% full
{
m_pInstanceBuckets[i]->Flush(rti);
bFlushed = true;
}
const u32 bucketCount = m_pInstanceBuckets[i]->GetCount(rti);
if(bucketCount > maxAmount)
{
maxAmount = bucketCount;
maxIdx = i;
}
if(bucketCount < minAmount)
{
minAmount = bucketCount;
minIdx = i;
}
}
// flush the one with most instances if nobody got flushed and no more empty buckets:
if((!bFlushed) && (maxIdx!=-1) && (minAmount!=0))
{
m_pInstanceBuckets[maxIdx]->Flush(rti);
}
}
bool AddInstance(u8 rti, bool bMainRT, grmGeometry *pGeometry, grcTexture *pTexture, struct instGrassDataDrawStruct *pInstance, const Vec4V &umParams, const Vec2V &collParams)
{
for(u32 i=0; i<N; i++)
{
// Do we have a bucket for the geometry/texture combination ongoing ?
if((m_pInstanceBuckets[i]->GetGeometry(rti) == pGeometry) && (m_pInstanceBuckets[i]->GetTexture(rti) == pTexture))
{
if(bMainRT)
{ // MainRT: Use it.
return m_pInstanceBuckets[i]->AddInstance(rti, bMainRT, pGeometry, pTexture, pInstance, umParams, collParams);
}
else
{
// subtask: find another not full
if(!m_pInstanceBuckets[i]->IsFull(rti))
{
return m_pInstanceBuckets[i]->AddInstance(rti, bMainRT, pGeometry, pTexture, pInstance, umParams, collParams);
}
}
}
}
u32 minCount = 0xffffffff;
u32 minCountIdx = 0;
u32 maxCount = 0;
u32 maxCountIdx = 0;
// Find a new bucket to use.
for(u32 i=0; i<N; i++)
{
if(m_pInstanceBuckets[i]->GetCount(rti) < minCount)
{
minCount = m_pInstanceBuckets[i]->GetCount(rti);
minCountIdx = i;
}
if(m_pInstanceBuckets[i]->GetCount(rti) > maxCount)
{
maxCount = m_pInstanceBuckets[i]->GetCount(rti);
maxCountIdx = i;
}
}
if(minCount == 0)
{
// Start a new bucket.
return m_pInstanceBuckets[minCountIdx]->AddInstance(rti, bMainRT, pGeometry, pTexture, pInstance, umParams, collParams);
}
else
{
if(bMainRT)
{ // only MainRT: "Evict" the most full bucket.
return m_pInstanceBuckets[maxCountIdx]->AddInstance(rti, bMainRT, pGeometry, pTexture, pInstance, umParams, collParams);
}
else
{
// subtask fails:
return(false);
}
}
}
#else //PLANTSMGR_MULTI_RENDER...
void Reset(grcEffectTechnique techId)
{
u32 i;
for(i=0; i<N; i++)
{
m_pInstanceBuckets[i]->Reset(techId);
}
}
void Flush()
{
u32 i;
for(i=0; i<N; i++)
{
m_pInstanceBuckets[i]->Flush();
}
}
void AddInstance(grmGeometry *pGeometry, grcTexture *pTexture, struct instGrassDataDrawStruct *pInstance, const Vec4V &umParams, const Vec2V &collParams)
{
u32 i;
u32 minCount = 0xffffffff;
u32 minCountIdx = 0;
u32 maxCount = 0;
u32 maxCountIdx = 0;
for(i=0; i<N; i++)
{
// Do we have a bucket for the geometry/texture combination ongoing ?
if((m_pInstanceBuckets[i]->GetGeometry() == pGeometry) && (m_pInstanceBuckets[i]->GetTexture() == pTexture))
{
// Use it.
m_pInstanceBuckets[i]->AddInstance(pGeometry, pTexture, pInstance, umParams, collParams);
return;
}
}
// Find a new bucket to use.
for(i=0; i<N; i++)
{
if(m_pInstanceBuckets[i]->GetCount() < minCount)
{
minCount = m_pInstanceBuckets[i]->GetCount();
minCountIdx = i;
}
if(m_pInstanceBuckets[i]->GetCount() > maxCount)
{
maxCount = m_pInstanceBuckets[i]->GetCount();
maxCountIdx = i;
}
}
if(minCount == 0)
{
// Start a new bucket.
m_pInstanceBuckets[minCountIdx]->AddInstance(pGeometry, pTexture, pInstance, umParams, collParams);
}
else
{
// "Evict" the most full bucket.
m_pInstanceBuckets[maxCountIdx]->AddInstance(pGeometry, pTexture, pInstance, umParams, collParams);
}
}
// NEW_STORE_OPT:
InstanceBucket* FindBucket(grmGeometry *pGeometry, grcTexture *pTexture)
{
for(u32 i=0; i<N; i++)
{
// Do we have a bucket for the geometry/texture combination ongoing ?
if((m_pInstanceBuckets[i]->GetGeometry() == pGeometry) && (m_pInstanceBuckets[i]->GetTexture() == pTexture))
{
// Use it.
m_pInstanceBuckets[i]->LockTexture();
return m_pInstanceBuckets[i];
}
}
u32 minCount = 0xffffffff;
u32 minCountIdx = 0;
u32 maxCount = 0;
u32 maxCountIdx = 0;
// Find a new bucket to use.
for(u32 i=0; i<N; i++)
{
const u32 count = m_pInstanceBuckets[i]->GetCount();
if(count < minCount)
{
minCount = count;
minCountIdx = i;
}
if(count > maxCount)
{
maxCount = count;
maxCountIdx = i;
}
}
if(minCount == 0)
{
// Start a new bucket.
m_pInstanceBuckets[minCountIdx]->BeginInstance(pGeometry, pTexture);
m_pInstanceBuckets[minCountIdx]->LockTexture();
return m_pInstanceBuckets[minCountIdx];
}
else
{
// "Evict" the most full bucket.
m_pInstanceBuckets[maxCountIdx]->BeginInstance(pGeometry, pTexture);
m_pInstanceBuckets[maxCountIdx]->LockTexture();
return m_pInstanceBuckets[maxCountIdx];
}
}
#endif //PLANTSMGR_MULTI_RENDER...
private:
InstanceBucket *m_pInstanceBuckets[N];
};
#endif // GRASS_INSTANCING
public:
enum { NUM_COL_VEH = 4 }; // support up to 4 vehicles deforming grass
public:
CGrassRenderer();
~CGrassRenderer();
public:
static bool Initialise();
static void Shutdown();
static bool UpdateStr();
#if PSN_PLANTSMGR_SPU_RENDER
static bool SpuInitialisePerRenderFrame();
static bool SpuFinalisePerRenderFrame();
static bool SpuUpdateStrStats(spuGrassParamsStructMaster *p);
static bool SpuRecordGrassTexture(u32 texIndex, grcTexture *pTexture);
static bool SpuRecordGeometries();
static u32 SpuRecordGeometry(CellGcmContextData *con1, grmGeometry *pGeometry, u32 *dstCmd, u32 maxCmdSize);
static u32 SpuRecordGeometry(CellGcmContextData *con1, grcVertexBuffer* pVertexBuffer, grcVertexDeclaration* pVertexDeclaration, u32 *dstCmd, u32 maxCmdSize);
static bool SpuRecordShaders(u32 bufID);
static u32 SpuRecordShaderBind(CellGcmContextData *con1, grcEffectTechnique forcedTech, u32 *dstCmd, u32 maxCmdSize);
static u32 SpuRecordShaderUnBind(CellGcmContextData *con1);
static u32 SpuGetAmountOfJobs() { return sm_nNumGrassJobsAddedTotal;}
static u32 SpuGetAmountOfAllocatedJobs() { return spuTriPlantBlockTabCount; }
static u32 SpuGetBigHeapAllocatedSize() { return(sm_BigHeapAllocatedSize[sm_BigHeapID]); }
static u32 SpuGetBigHeapConsumed() { return(sm_BigHeapConsumed[sm_BigHeapID]); }
static u32 SpuGetBigHeapBiggestConsumed() { return(sm_BigHeapBiggestConsumed[sm_BigHeapID]); }
static u32 SpuGetBigHeapOverfilled() { return(sm_BigHeapOverfilled[sm_BigHeapID]); }
#else
static bool SpuInitialisePerRenderFrame() { return(TRUE); }
static bool SpuFinalisePerRenderFrame() { return(TRUE); }
static bool SpuRecordGrassTexture(u32,grcTexture*) { return(TRUE); }
static bool SpuRecordGeometries() { return(TRUE); }
static u32 SpuRecordGeometry(void*,grmGeometry*,u32*,u32) { return(TRUE); }
static u32 SpuRecordGeometry(void*,grcVertexBuffer*,grcVertexDeclaration*,u32*,u32) { return(TRUE); }
static bool SpuRecordShaders(u32) { return(TRUE); }
static u32 SpuRecordShaderBind(void*, grcEffectTechnique, u32*, u32) { return(TRUE); }
static u32 SpuRecordShaderUnBind(void*) { return(TRUE); }
static u32 SpuGetAmountOfJobs() { return(0); }
static u32 SpuGetAmountOfAllocatedJobs() { return(0); }
static u32 SpuGetBigHeapAllocatedSize() { return(0); }
static u32 SpuGetBigHeapConsumed() { return(0); }
static u32 SpuGetBigHeapBiggestConsumed() { return(0); }
static u32 SpuGetBigHeapOverfilled() { return(0); }
#endif
public:
static void AddTriPlant(PPTriPlant *pPlant, u32 ePlantModelSet);
static void FlushTriPlantBuffer();
#if !PSN_PLANTSMGR_SPU_RENDER
static void BeginUseNormalTechniques(spdTransposedPlaneSet8 &cullFrustum);
static void EndUseNormalTechniques();
#endif
#if PLANTS_CAST_SHADOWS
#if !PSN_PLANTSMGR_SPU_RENDER
static void BeginUseShadowTechniques(spdTransposedPlaneSet8 &cullFrustum);
static void EndUseShadowTechniques();
#endif
#endif //PLANTS_CAST_SHADOWS
private:
#if PSN_PLANTSMGR_SPU_RENDER
static bool DrawTriPlantsSPU(PPTriPlant *triPlants, const u32 numTriPlants, u32 slotID);
#else
static bool DrawTriPlants(PPTriPlant *triPlants, const u32 numTriPlants, grassModel* plantModelsTab);
#if PLANTSMGR_MULTI_RENDER
public:
struct CParamsDrawTriPlantsMulti
{
Vector3 m_CameraPos;
Vector3 m_PlayerPos;
Vector3 m_SunDir;
Vector2 m_WindBending;
float m_NaturalAmbient;
float m_LOD0FarDist2;
float m_LOD1CloseDist2;
float m_LOD1FarDist2;
float m_LOD2CloseDist2;
float m_LOD2FarDist2;
};
static bool DrawTriPlantsMulti(const u8 rti, const bool bMainRT, PPTriPlant *triPlants, const u32 numTriPlants, grassModel* plantModelsTab,
CParamsDrawTriPlantsMulti *pParamsDrawMulti);
private:
#endif //PLANTSMGR_MULTI_RENDER...
#endif //PSN_PLANTSMGR_SPU_RENDER...
static void BindPlantShader(grcEffectTechnique forcedTech);
static void UnBindPlantShader();
public:
static bool SetPlantModelsTab(u32 index, grassModel *plantModels);
static grassModel* GetPlantModelsTab(u32 index);
public:
static void SetGlobalCameraPos(const Vector3& camPos);
static const Vector3& GetGlobalCameraPos();
static void SetGlobalCameraFront(const Vector3& camPos);
static const Vector3& GetGlobalCameraFront();
static void SetGlobalCameraFppEnabled(bool b);
static bool GetGlobalCameraFppEnabled();
static void SetGlobalCameraUnderwater(bool b);
static bool GetGlobalCameraUnderwater();
static void SetGlobalForceHDGrassGeometry(bool b);
static bool GetGlobalForceHDGrassGeometry();
static void SetGlobalPlayerPos(const Vector3& playerPos);
static const Vector3& GetGlobalPlayerPos();
static void SetGlobalPlayerCollisionRSqr(float radSqr);
static float GetGlobalPlayerCollisionRSqr();
static void SetGlobalCullFrustum(const spdTransposedPlaneSet8& frustum);
static void GetGlobalCullFrustum(spdTransposedPlaneSet8 *frustum);
static void SetGlobalInteriorCullAll(bool intCullAll);
static bool GetGlobalInteriorCullAll();
static void SetGlobalVehCollisionParams(u32 n, bool bEnable, const Vector3& vecB, const Vector3& vecM, float radius, float groundZ);
static void GetGlobalVehCollisionParams(u32 n, bool *bEnable, Vector4 *vecB, Vector4 *vecM, Vector4 *vecR);
static void SetGlobalWindBending(const Vector2& bending);
static void GetGlobalWindBending(Vector2 &outBending);
static void GetGlobalWindBendingUT(Vector2 &outBending);
static void SetFakeGrassNormal(const Vector3& n);
static const Vector3& GetFakeGrassNormal();
#if __BANK
static void SetDebugModeEnable(bool enable);
static bool GetDebugModeEnable();
#endif
#if FURGRASS_TEST_V4
static void SetGlobalPlayerFeetPos(const Vector4& LFootPos, const Vector4& RFootPos);
static const Vector4& GetGlobalPlayerLFootPos();
static const Vector4& GetGlobalPlayerRFootPos();
#endif //FURGRASS_TEST_V4...
#if __BANK
static void InitWidgets(bkBank& bank);
#endif
#if PLANTS_USE_LOD_SETTINGS
static float GetDistanceMultiplier();
static void SetDistanceMultiplier( float d ){ ms_currentScalingParams.distanceMultiplier = d; }
static float GetDensityMultiplier();
static void SetPlantLODToUse(CGrassRenderer_PlantLod plantLOD);
#if __BANK
static void OnComboBox_LODToEdit(void);
static void SaveParams(void);
static void LoadParams(void);
#endif
#endif //PLANTS_USE_LOD_SETTINGS
#if PLANTS_CAST_SHADOWS
static void SetDepthBiasOn();
static void SetDepthBiasOff();
static float GetShadowFadeNearRadius();
static float GetShadowFadeFarRadius();
#endif //PLANTS_CAST_SHADOWS
public:
static void SetGeometryLOD2(grcVertexBuffer *vb, grcVertexDeclaration *decl);
static grmShaderGroup* GetGrassShaderGroup();
static grmShader* GetGrassShader();
static grcEffectTechnique GetFakedGBufTechniqueID();
static grcEffectVar GetGBuf0TextureID();
private:
static Vector3 ms_vecCameraPos[2];
static Vector3 ms_vecCameraFront[2];
static Vector3 ms_vecPlayerPos[2];
static float ms_fPlayerCollRSqr[2];
static bool ms_cameraFppEnabled[2];
static bool ms_cameraUnderwater[2];
static bool ms_forceHdGrassGeom[2];
static spdTransposedPlaneSet8 ms_cullFrustum[2];
static bool ms_interiorCullAll[2];
static bool ms_bVehCollisionEnabled[2][NUMBER_OF_RENDER_THREADS][NUM_COL_VEH];
static Vector4 ms_vecVehCollisionB[2][NUMBER_OF_RENDER_THREADS][NUM_COL_VEH];
static Vector4 ms_vecVehCollisionM[2][NUMBER_OF_RENDER_THREADS][NUM_COL_VEH];
static Vector4 ms_vecVehCollisionR[2][NUMBER_OF_RENDER_THREADS][NUM_COL_VEH];
static Vector2 ms_windBending[2];
static Vector3 ms_fakeGrassNormal[2];
#if __BANK
static bool ms_enableDebugDraw[2];
#endif
#if FURGRASS_TEST_V4
static Vector4 ms_vecPlayerLFootPos[2];
static Vector4 ms_vecPlayerRFootPos[2];
#endif
// LOD2 vertex buffer:
static grcVertexBuffer *ms_plantLOD2VertexBuffer;
static grcVertexDeclaration *ms_plantLOD2VertexDecl;
static grmShaderGroup *ms_ShaderGroup;
static grmShader *ms_Shader;
static grcEffectVar ms_shdTextureID;
static grcEffectVar ms_shdGBuf0TextureID;
#if PSN_PLANTSMGR_SPU_RENDER
static u32 ms_shdTextureTexUnit;
#endif
static grcEffectVar ms_grassRegTransform;
static grcEffectVar ms_grassRegPlantCol;
static grcEffectVar ms_grassRegGroundCol;
static grcEffectVar ms_shdCameraPosID;
static grcEffectVar ms_shdPlayerPosID;
static grcEffectGlobalVar ms_shdVehCollisionEnabledID[NUM_COL_VEH];
static grcEffectVar ms_shdVehCollisionBID[NUM_COL_VEH];
static grcEffectVar ms_shdVehCollisionMID[NUM_COL_VEH];
static grcEffectVar ms_shdVehCollisionRID[NUM_COL_VEH];
static grcEffectVar ms_shdFadeAlphaDistUmTimerID;
static grcEffectVar ms_shdFadeAlphaLOD1DistID;
static grcEffectVar ms_shdFadeAlphaLOD2DistID;
static grcEffectVar ms_shdFadeAlphaLOD2DistFarID;
#if !PSN_PLANTSMGR_SPU_RENDER
static grcEffectVar ms_shdPlantColorID;
static grcEffectVar ms_shdUMovementParamsID;
static grcEffectVar ms_shdDimensionLOD2ID;
static grcEffectVar ms_shdCollParamsID;
#endif
static grcEffectVar ms_shdFakedGrassNormal;
#if CPLANT_WRITE_GRASS_NORMAL
static grcEffectVar ms_shdTerrainNormal;
#endif
#if 0 && __DEV && __PPU
static grcEffectVar ms_shdGBuf0AlphaScaleID;
#endif
#if DEVICE_MSAA
static grcEffectVar ms_shdAlphaToCoverageScale;
#endif
static grcEffectTechnique ms_shdDeferredLOD0TechniqueID;
static grcEffectTechnique ms_shdDeferredLOD1TechniqueID;
static grcEffectTechnique ms_shdDeferredLOD2TechniqueID;
#if __BANK
static grcEffectTechnique ms_shdDeferredLOD0DbgTechniqueID;
static grcEffectTechnique ms_shdDeferredLOD1DbgTechniqueID;
static grcEffectTechnique ms_shdDeferredLOD2DbgTechniqueID;
#endif
static grcEffectTechnique ms_shdBlitFakedGBufID;
#if !PSN_PLANTSMGR_SPU_RENDER
static DECLARE_MTR_THREAD grcEffectTechnique ms_shdDeferredLOD0TechniqueID_ToUse;
static DECLARE_MTR_THREAD grcEffectTechnique ms_shdDeferredLOD1TechniqueID_ToUse;
static DECLARE_MTR_THREAD grcEffectTechnique ms_shdDeferredLOD2TechniqueID_ToUse;
static spdTransposedPlaneSet8 ms_cullingFrustum[NUMBER_OF_RENDER_THREADS];
#endif
#if GRASS_INSTANCING
static InstanceBucket ms_instanceBucketsLOD0[CGRASS_RENDERER_LOD_BUCKET_SIZE];
static InstanceBucket ms_instanceBucketsLOD1[CGRASS_RENDERER_LOD_BUCKET_SIZE];
static InstanceBucket_LOD2 ms_instanceBucketsLOD2[CGRASS_RENDERER_LOD_BUCKET_SIZE];
static LODBucket < CGRASS_RENDERER_LOD_BUCKET_SIZE > ms_LOD0Bucket;
static LODBucket < CGRASS_RENDERER_LOD_BUCKET_SIZE > ms_LOD1Bucket;
static LODBucket < CGRASS_RENDERER_LOD_BUCKET_SIZE > ms_LOD2Bucket;
#endif // GRASS_INSTANCING
#if PLANTS_CAST_SHADOWS
#if __BANK
static bool ms_drawShadows;
#endif
static grcEffectGlobalVar ms_depthValueBias;
static grcEffectTechnique ms_shdDeferredLOD0ShadowTechniqueID;
static grcEffectTechnique ms_shdDeferredLOD1ShadowTechniqueID;
static grcEffectTechnique ms_shdDeferredLOD2ShadowTechniqueID;
static CGrassShadowParams ms_currentShadowEnvelope;
#if PLANTS_USE_LOD_SETTINGS
static CGrassShadowParams_AllLODs ms_shadowEnvelope_AllLods;
#endif
#endif //PLANTS_CAST_SHADOWS
#if PLANTS_USE_LOD_SETTINGS
static CGrassScalingParams ms_currentScalingParams;
static CGrassScalingParams_AllLODs ms_scalingParams_AllLods;
static int ms_LODToInitialiseWith;
static bool ms_isInitialized;
#if __BANK
static int ms_LODBeingEdited;
static int ms_LODNextToEdit;
#endif
#endif
#if PSN_PLANTSMGR_SPU_RENDER
static u32 sm_nNumGrassJobsAdded;
static u32 sm_nNumGrassJobsAddedTotal;
static sysTaskHandle sm_GrassTaskHandle;
static u32 sm_BigHeapID;
#if PLANTSMGR_BIG_HEAP_IN_BLOCKS
static grassHeapBlock sm_BigHeapBlockArray[2][PLANTSMGR_BIG_HEAP_BLK_ARRAY_SIZE] ALIGNED(128); // 64*8 = 512 bytes
static s16 sm_BigHeapBlockArrayCount[2]; // how many valid block allocated
static bool BigHeapBlockArrayContainsOffset(u32 heapID, u32 blockSize, u32 offset);
#else
static u32* sm_BigHeap[2];
static u32 sm_BigHeapOffset[2];
static u32 sm_BigHeapSize[2];
#endif
static u32 sm_BigHeapAllocatedSize[2], sm_BigHeapConsumed[2], sm_BigHeapBiggestConsumed[2], sm_BigHeapOverfilled[2];
#if SPU_GCM_FIFO
static u32* sm_StartupHeapPtr[2];
static u32 sm_StartupHeapOffset[2];
#endif
static u32* gpShaderLOD0Cmd0[2];
static u32* gpShaderLOD1Cmd0[2];
static u32* gpShaderLOD2Cmd0[2];
static u32 gpShaderLOD0Offset[2];
static u32 gpShaderLOD1Offset[2];
static u32 gpShaderLOD2Offset[2];
static u32* gpPlantLOD2GeometryCmd0;
static u32 gpPlantLOD2GeometryOffset;
static u32 rsxLabel5Index;
static volatile u32* rsxLabel5Ptr;
static u32 rsxLabel5_CurrentTaskID;
#if PLANTSMGR_TRIPLANTTAB_IN_BLOCKS
static PPTriPlant* spuTriPlantBlockTab[PLANTSMGR_MAX_NUM_OF_RENDER_JOBS];
static s32 spuTriPlantBlockTabCount;
#else
static PPTriPlant spuTriPlantTab[PLANTSMGR_MAX_NUM_OF_RENDER_JOBS][PPTRIPLANT_BUFFER_SIZE] ALIGNED(128);
#endif
static spuGrassParamsStruct inSpuGrassStructTab[PLANTSMGR_MAX_NUM_OF_RENDER_JOBS] ALIGNED(128);
#endif //PSN_PLANTSMGR_SPU_RENDER...
};
//
//
//
//
enum
{
PPPLANTBUF_MODEL_SET0 = 0,
PPPLANTBUF_MODEL_SET1 = 1,
PPPLANTBUF_MODEL_SET2 = 2,
PPPLANTBUF_MODEL_SET3 = 3
};
//
//
//
//
class CPPTriPlantBuffer
{
public:
CPPTriPlantBuffer();
~CPPTriPlantBuffer();
public:
void Flush();
PPTriPlant* GetPPTriPlantPtr(s32 amountToAdd=1);
void ChangeCurrentPlantModelsSet(s32 newSet);
void IncreaseBufferIndex(s32 pipeMode, s32 amount=1);
public:
//
// current plant models set:
//
void SetPlantModelsSet(s32 set) { this->m_PerThreadData[g_RenderThreadIndex].m_plantModelsSet=set; }
s32 GetPlantModelsSet() { return(this->m_PerThreadData[g_RenderThreadIndex].m_plantModelsSet); }
grassModel* GetPlantModels(u32 i) { Assert(i<PPTRIPLANT_MODELS_TAB_SIZE); return m_pPlantModelsTab[i]; }
public:
//
// access to m_pPlantModelsTab[]:
//
bool SetPlantModelsTab(u32 index, grassModel* pPlantModels);
grassModel* GetPlantModelsTab(u32 index);
#if PSN_PLANTSMGR_SPU_RENDER
bool AllocateTextureBuffers();
void DestroyTextureBuffers();
bool SetPlantTexturesCmd(u32 slotid, u32 index, u32 *cmd);
u32* GetPlantTexturesCmd(u32 slotid, u32 index);
u32 GetPlantTexturesCmdOffset(u32 slotid, u32 index);
bool AllocateModelsBuffers();
void DestroyModelsBuffers();
bool SetPlantModelsCmd(u32 slotid, u32 index, u32 *cmd);
u32* GetPlantModelsCmd(u32 slotid, u32 index);
u32 GetPlantModelsCmdOffset(u32 slotid, u32 index);
#endif //PSN_PLANTSMGR_SPU_RENDER...
private:
struct PER_THREAD_DATA
{
u32 m_currentIndex;
PPTriPlant m_Buffer[PPTRIPLANT_BUFFER_SIZE];
s32 m_plantModelsSet;
};
PER_THREAD_DATA m_PerThreadData[NUMBER_OF_RENDER_THREADS];
#if PSN_PLANTSMGR_SPU_RENDER
u32 *m_pPlantsTexturesCmd0;
u32 *m_pPlantsTexturesCmd1;
u32 *m_pPlantsTexturesCmd2;
u32 *m_pPlantsTexturesCmd3;
u32 *m_pPlantsTexturesCmdTab[PPTRIPLANT_MODELS_TAB_SIZE];
u32 m_pPlantsTexturesCmdOffset0;
u32 m_pPlantsTexturesCmdOffset1;
u32 m_pPlantsTexturesCmdOffset2;
u32 m_pPlantsTexturesCmdOffset3;
u32 m_pPlantsTexturesCmdOffsetTab[PPTRIPLANT_MODELS_TAB_SIZE];
u32 *m_pPlantsModelsCmd0;
u32 *m_pPlantsModelsCmd1;
u32 *m_pPlantsModelsCmd2;
u32 *m_pPlantsModelsCmd3;
u32 *m_pPlantsModelsCmdTab[PPTRIPLANT_MODELS_TAB_SIZE];
u32 m_pPlantsModelsCmdOffset0;
u32 m_pPlantsModelsCmdOffset1;
u32 m_pPlantsModelsCmdOffset2;
u32 m_pPlantsModelsCmdOffset3;
u32 m_pPlantsModelsCmdOffsetTab[PPTRIPLANT_MODELS_TAB_SIZE];
#endif //PSN_PLANTSMGR_SPU_RENDER...
grassModel* m_pPlantModelsTab[PPTRIPLANT_MODELS_TAB_SIZE];
};
#endif //!__SPU...
#endif//__CPLANTGRASSRENDERER_H__...