1
0
forked from 0ad/0ad

Sped up LOS rendering.

This was SVN commit r2880.
This commit is contained in:
Matei 2005-10-09 08:14:42 +00:00
parent 57cfc7c6ac
commit c468eedbbb
5 changed files with 121 additions and 47 deletions

View File

@ -172,16 +172,19 @@ void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjec
if (frustum.IsBoxVisible(CVector3D(0,0,0), units[i]->GetModel()->GetBounds())
&& status != UNIT_HIDDEN)
{
CColor color;
if(status == UNIT_VISIBLE)
if(units[i] != g_BuildingPlacer.m_actor)
{
color = CColor(1.0f, 1.0f, 1.0f, 1.0f);
CColor color;
if(status == UNIT_VISIBLE)
{
color = CColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else // status == UNIT_REMEMBERED
{
color = CColor(0.7f, 0.7f, 0.7f, 1.0f);
}
units[i]->GetModel()->SetShadingColor(color);
}
else // status == UNIT_REMEMBERED
{
color = CColor(0.7f, 0.7f, 0.7f, 1.0f);
}
units[i]->GetModel()->SetShadingColor(color);
PROFILE( "submit models" );
SubmitModelRecursive(units[i]->GetModel());

View File

@ -47,7 +47,7 @@ static SColor4ub ConvertColor(const RGBColor& src)
///////////////////////////////////////////////////////////////////
// CPatchRData constructor
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_VBBase(0), m_VBBlends(0), m_Vertices(0)
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_VBBase(0), m_VBBlends(0), m_Vertices(0), m_LightingColors(0)
{
debug_assert(patch);
Build();
@ -59,6 +59,7 @@ CPatchRData::~CPatchRData()
{
// delete copy of vertex data
delete[] m_Vertices;
delete[] m_LightingColors;
// release vertex buffer chunks
if (m_VBBase) g_VBMan.Release(m_VBBase);
if (m_VBBlends) g_VBMan.Release(m_VBBlends);
@ -213,6 +214,7 @@ void CPatchRData::BuildBlends()
dst.m_Color=vtx0.m_Color;
dst.m_Position=vtx0.m_Position;
m_BlendVertices.push_back(dst);
m_BlendVertexIndices.push_back((j*vsize)+i);
const SBaseVertex& vtx1=m_Vertices[(j*vsize)+i+1];
dst.m_UVs[0]=(i+1)*0.125f;
@ -222,6 +224,7 @@ void CPatchRData::BuildBlends()
dst.m_Color=vtx1.m_Color;
dst.m_Position=vtx1.m_Position;
m_BlendVertices.push_back(dst);
m_BlendVertexIndices.push_back((j*vsize)+i+1);
const SBaseVertex& vtx2=m_Vertices[((j+1)*vsize)+i+1];
dst.m_UVs[0]=(i+1)*0.125f;
@ -231,6 +234,7 @@ void CPatchRData::BuildBlends()
dst.m_Color=vtx2.m_Color;
dst.m_Position=vtx2.m_Position;
m_BlendVertices.push_back(dst);
m_BlendVertexIndices.push_back(((j+1)*vsize)+i+1);
const SBaseVertex& vtx3=m_Vertices[((j+1)*vsize)+i];
dst.m_UVs[0]=i*0.125f;
@ -240,6 +244,7 @@ void CPatchRData::BuildBlends()
dst.m_Color=vtx3.m_Color;
dst.m_Position=vtx3.m_Position;
m_BlendVertices.push_back(dst);
m_BlendVertexIndices.push_back(((j+1)*vsize)+i);
// build a splat for this quad
STmpSplat splat;
@ -360,14 +365,17 @@ void CPatchRData::BuildIndices()
void CPatchRData::BuildVertices()
{
// create both vertices and lighting colors
CVector3D normal;
RGBColor c;
SColor4ub black = ConvertColor(RGBColor(0,0,0));
// number of vertices in each direction in each patch
int vsize=PATCH_SIZE+1;
if (!m_Vertices) {
m_Vertices=new SBaseVertex[vsize*vsize];
m_LightingColors=new RGBColor[vsize*vsize];
}
SBaseVertex* vertices=m_Vertices;
@ -377,9 +385,6 @@ void CPatchRData::BuildVertices()
u32 pz=m_Patch->m_Z;
CTerrain* terrain=m_Patch->m_Parent;
int mapSize=terrain->GetVerticesPerSide();
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
// build vertices
for (int j=0;j<vsize;j++) {
@ -388,37 +393,20 @@ void CPatchRData::BuildVertices()
int iz=pz*PATCH_SIZE+j;
int v=(j*vsize)+i;
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
terrain->CalcNormal(ix,iz,normal);
const int DX[] = {1,1,0,0};
const int DZ[] = {0,1,1,0};
float losMod = 1.0f;
for(int k=0; k<4; k++)
{
int tx = ix - DX[k];
int tz = iz - DZ[k];
if(tx >= 0 && tz >= 0 && tx <= mapSize-2 && tz <= mapSize-2)
{
ELOSStatus s = losMgr->GetStatus(tx, tz, g_Game->GetLocalPlayer());
if(s==LOS_EXPLORED && losMod > 0.7f)
losMod = 0.7f;
else if(s==LOS_UNEXPLORED && losMod > 0.0f)
losMod = 0.0f;
}
}
RGBColor losModColor(losMod, losMod, losMod);
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal, c, losModColor);
vertices[v].m_Color=ConvertColor(c);
// calculate vertex data
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
vertices[v].m_Color=black; // will be set to the proper value in Update()
vertices[v].m_UVs[0]=i*0.125f;
vertices[v].m_UVs[1]=j*0.125f;
// calculate lighting into the separate m_LightingColors array, which will
// be used to set the vertex colors in Update()
terrain->CalcNormal(ix,iz,normal);
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal, m_LightingColors[v]);
}
}
// upload to vertex buffer
if (!m_VBBase) {
m_VBBase=g_VBMan.Allocate(sizeof(SBaseVertex),vsize*vsize,false);
}
@ -438,16 +426,69 @@ void CPatchRData::Update()
// TODO,RC 11/04/04 - need to only rebuild necessary bits of renderdata rather
// than everything; it's complicated slightly because the blends are dependent
// on both vertex and index data
//BuildVertices();
BuildVertices();
BuildIndices();
///BuildBlends();
BuildBlends();
m_UpdateFlags=0;
}
// Always build vertices (due to LOS)
BuildVertices();
BuildBlends();
// Update vertex colors, which are affected by LOS
u32 px=m_Patch->m_X;
u32 pz=m_Patch->m_Z;
CTerrain* terrain=m_Patch->m_Parent;
int mapSize=terrain->GetVerticesPerSide();
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
int vsize=PATCH_SIZE+1;
// this is very similar to BuildVertices(), but just for color
for (int j=0;j<vsize;j++) {
for (int i=0;i<vsize;i++) {
int ix=px*PATCH_SIZE+i;
int iz=pz*PATCH_SIZE+j;
int v=(j*vsize)+i;
const int DX[] = {1,1,0,0};
const int DZ[] = {0,1,1,0};
float losMod = 1.0f;
for(int k=0; k<4; k++)
{
int tx = ix - DX[k];
int tz = iz - DZ[k];
if(tx >= 0 && tz >= 0 && tx <= mapSize-2 && tz <= mapSize-2)
{
ELOSStatus s = losMgr->GetStatus(tx, tz, g_Game->GetLocalPlayer());
if(s==LOS_EXPLORED && losMod > 0.7f)
losMod = 0.7f;
else if(s==LOS_UNEXPLORED && losMod > 0.0f)
losMod = 0.0f;
}
}
RGBColor c = m_LightingColors[v];
c *= losMod;
m_Vertices[v].m_Color=ConvertColor(c);
}
}
// upload base vertices into their vertex buffer
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
// update blend colors by copying them from vertex colors
for(uint i=0; i<m_BlendVertices.size(); i++)
{
m_BlendVertices[i].m_Color = m_Vertices[m_BlendVertexIndices[i]].m_Color;
}
// upload blend vertices into their vertex buffer too
if(m_BlendVertices.size())
{
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends,&m_BlendVertices[0]);
}
}
void CPatchRData::RenderBase()

View File

@ -87,7 +87,6 @@ private:
Handle m_Handle;
int m_Priority;
};
// build this renderdata object
void Build();
@ -98,26 +97,46 @@ private:
// owner patch
CPatch* m_Patch;
// vertex buffer handle for base vertices
CVertexBuffer::VBChunk* m_VBBase;
// vertex buffer handle for blend vertices
CVertexBuffer::VBChunk* m_VBBlends;
// patch render vertices
SBaseVertex* m_Vertices;
// precomputed lighting colors at each vertex; these are the multiplied by a LOS modifier
// (black for shroud of darkness, half-darkened for fog of war), to compute the colors in
// m_Vertices, which are passed to the graphics card
RGBColor* m_LightingColors;
// indices into base vertices for the base splats
std::vector<unsigned short> m_Indices;
// indices into base vertices for the shadow map pass
std::vector<unsigned short> m_ShadowMapIndices;
// list of base splats to apply to this patch
std::vector<SSplat> m_Splats;
// vertices to use for blending transition texture passes
std::vector<SBlendVertex> m_BlendVertices;
// remembers the index in the m_Vertices array of each blend vertex, so that we can
// properly update its color for fog of war and shroud of darkness
std::vector<uint> m_BlendVertexIndices;
// indices into blend vertices for the blend splats
std::vector<unsigned short> m_BlendIndices;
// splats used in blend pass
std::vector<SSplat> m_BlendSplats;
// index of the next blend splat to render
u32 m_NextBlendSplat;
// list of all submitted patches
static std::vector<CPatch*> m_Patches;
};

View File

@ -151,9 +151,15 @@ EUnitLOSStatus CLOSManager::GetUnitStatus(CUnit* unit, CPlayer* player)
}
else if(status == LOS_EXPLORED)
{
if(unit->GetEntity() != 0 && unit->GetEntity()->m_permanent)
if(unit->GetEntity() == 0 || unit->GetEntity()->m_permanent)
{
// both actors (which are usually for decoration) and units with the
// permanent flag should be remembered
return UNIT_REMEMBERED;
// TODO: the unit status system will have to be replaced with a "ghost actor"
// system so that we can't remember units that we haven't seen and so we can
// see permanent units that have died but that we haven't been near lately
}
else
{

View File

@ -5,7 +5,12 @@
// Maintains and updates line of sight data (including Shroud of Darkness
// and Fog of War).
//
// Usage: Doesn't do anything useful right now.
// Usage:
// - Initialize() is called when the game is started to allocate the visibility arrays
// - Update() is called each frame by CSimulation::Update() to update the visibility arrays
// - m_MapRevealed can be set to true to reveal the entire map (remove both LOS and FOW)
// - GetStatus can be used to obtain the LOS status of a tile or a world-space point
// - GetUnitStatus returns the LOS status of an entity or actor
#ifndef LOS_MANAGER_INCLUDED