1
0
forked from 0ad/0ad

Sped up minimap rendering by having a separate LOS texture and recomputing only that per frame. To force a recompute of the terrain texture, set g_TerrainModified to true sometime before the render step of each frame (it is set back to false at the end of the frame).

This was SVN commit r2963.
This commit is contained in:
Matei 2005-10-19 03:02:51 +00:00
parent 9ac4ca16ba
commit 2ef8a7b630
4 changed files with 176 additions and 97 deletions

View File

@ -23,6 +23,8 @@
extern float g_MaxZoomHeight, g_YMinOffset;
bool HasClicked=false;
bool g_TerrainModified = false;
static unsigned int ScaleColor(unsigned int color, float x)
{
unsigned int r = uint(float(color & 0xff) * x);
@ -42,8 +44,8 @@ static int RoundUpToPowerOf2(int x)
}
CMiniMap::CMiniMap()
: m_Handle(0), m_Data(NULL), m_MapSize(0), m_Terrain(0),
m_UnitManager(0)
: m_TerrainTexture(0), m_TerrainData(0), m_MapSize(0), m_Terrain(0),
m_LOSTexture(0), m_LOSData(0), m_UnitManager(0)
{
AddSetting(GUIST_CColor, "fov_wedge_color");
AddSetting(GUIST_CStr, "tooltip");
@ -61,23 +63,32 @@ void CMiniMap::Draw()
// happens when the game is started
if(GetGUI() && g_Game && g_Game->IsGameStarted())
{
if(!m_Handle)
GenerateMiniMapTexture();
// Set our globals in case they hadn't been set before
m_Terrain = g_Game->GetWorld()->GetTerrain();
m_UnitManager = g_Game->GetWorld()->GetUnitManager();
m_Width = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top);
m_MapSize = m_Terrain->GetVerticesPerSide();
m_TextureSize = RoundUpToPowerOf2(m_MapSize);
Rebuild();
if(!m_TerrainTexture)
CreateTextures();
g_Renderer.BindTexture(0, m_Handle);
if(g_TerrainModified)
RebuildTerrainTexture();
RebuildLOSTexture();
float texCoordMax = ((float)m_MapSize - 1) / ((float)m_TextureSize);
float z = GetBufferedZ();
// Draw the main textured quad
g_Renderer.BindTexture(0, m_TerrainTexture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
float texCoordMax = ((float)m_MapSize - 1) / ((float)m_TextureSize);
float z = GetBufferedZ();
glBegin(GL_QUADS);
// Draw the main textured quad
glTexCoord2f(0.0f, 0.0f);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.bottom, z);
glTexCoord2f(texCoordMax, 0.0f);
@ -86,14 +97,42 @@ void CMiniMap::Draw()
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.top, z);
glTexCoord2f(0.0f, texCoordMax);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.top, z);
glEnd();
// Draw the LOS quad in black, using alpha values from the LOS texture
g_Renderer.BindTexture(0, m_LOSTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS);
glColor3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.bottom, z);
glTexCoord2f(texCoordMax, 0.0f);
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.bottom, z);
glTexCoord2f(texCoordMax, texCoordMax);
glVertex3f(m_CachedActualSize.right, m_CachedActualSize.top, z);
glTexCoord2f(0.0f, texCoordMax);
glVertex3f(m_CachedActualSize.left, m_CachedActualSize.top, z);
glEnd();
glDisable(GL_BLEND);
// Draw unit points
float x = m_CachedActualSize.left;
float y = m_CachedActualSize.bottom;
const std::vector<CUnit *> &units = m_UnitManager->GetUnits();
std::vector<CUnit *>::const_iterator iter = units.begin();
CUnit *unit = NULL;
CUnit *unit = 0;
CVector2D pos;
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
@ -255,40 +294,39 @@ void CMiniMap::Draw()
}
}
void CMiniMap::GenerateMiniMapTexture()
void CMiniMap::CreateTextures()
{
m_Terrain = g_Game->GetWorld()->GetTerrain();
m_UnitManager = g_Game->GetWorld()->GetUnitManager();
m_Width = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top);
Destroy();
glGenTextures(1, (GLuint *)&m_Handle);
g_Renderer.BindTexture(0, m_Handle);
m_MapSize = m_Terrain->GetVerticesPerSide();
m_TextureSize = RoundUpToPowerOf2(m_MapSize);
// Create terrain texture
glGenTextures(1, (GLuint *)&m_TerrainTexture);
g_Renderer.BindTexture(0, m_TerrainTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_TextureSize, m_TextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0);
m_Data = new u32[(m_MapSize - 1) * (m_MapSize - 1)];
m_TerrainData = new u32[(m_MapSize - 1) * (m_MapSize - 1)];
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
Rebuild();
// Create LOS texture
glGenTextures(1, (GLuint *)&m_LOSTexture);
g_Renderer.BindTexture(0, m_LOSTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
m_LOSData = new u8[(m_MapSize - 1) * (m_MapSize - 1)];
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
// Rebuild and upload both of them
RebuildTerrainTexture();
RebuildLOSTexture();
}
void CMiniMap::Rebuild()
void CMiniMap::RebuildTerrainTexture()
{
PROFILE_START("rebuild minimap");
PROFILE_START("rebuild minimap: terrain");
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
CPlayer* player = g_Game->GetLocalPlayer();
u32 mapSize = m_Terrain->GetVerticesPerSide();
u32 x = 0;
u32 y = 0;
u32 w = m_MapSize - 1;
@ -296,18 +334,9 @@ void CMiniMap::Rebuild()
for(u32 j = 0; j < h; j++)
{
u32 *dataPtr = m_Data + ((y + j) * (mapSize - 1)) + x;
u32 *dataPtr = m_TerrainData + ((y + j) * (m_MapSize - 1)) + x;
for(u32 i = 0; i < w; i++)
{
ELOSStatus status = losMgr->GetStatus((int) i, (int) j, player);
if(status == LOS_UNEXPLORED)
{
*dataPtr++ = 0xff000000;
}
else
{
u32 color = 0;
float avgHeight = ( m_Terrain->getVertexGroundLevel((int)i, (int)j)
+ m_Terrain->getVertexGroundLevel((int)i+1, (int)j)
+ m_Terrain->getVertexGroundLevel((int)i, (int)j+1)
@ -316,13 +345,15 @@ void CMiniMap::Rebuild()
if(avgHeight < g_Renderer.m_WaterHeight)
{
color = 0xff304080;
*dataPtr++ = 0xff304080; // TODO: perhaps use the renderer's water color?
}
else
{
int hmap = ((int)m_Terrain->GetHeightMap()[(y + j) * mapSize + x + i]) >> 8;
int hmap = ((int)m_Terrain->GetHeightMap()[(y + j) * m_MapSize + x + i]) >> 8;
int val = (hmap / 3) + 170;
u32 color = 0;
CMiniPatch *mp = m_Terrain->GetTile(x + i, y + j);
if(mp)
{
@ -334,37 +365,75 @@ void CMiniMap::Rebuild()
color = 0xffffffff;
}
color = ScaleColor(color, float(val) / 255.0f);
*dataPtr++ = ScaleColor(color, float(val) / 255.0f);
}
float losFactor = (status==LOS_VISIBLE ? 1.0f : 0.7f);
*dataPtr++ = ScaleColor(color, losFactor);
}
}
}
UploadTexture();
// Upload the texture
g_Renderer.BindTexture(0, m_TerrainTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize - 1, m_MapSize - 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_TerrainData);
PROFILE_END("rebuild minimap");
PROFILE_END("rebuild minimap: terrain");
}
void CMiniMap::UploadTexture()
void CMiniMap::RebuildLOSTexture()
{
g_Renderer.BindTexture(0, m_Handle);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize - 1, m_MapSize - 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_Data);
PROFILE_START("rebuild minimap: los");
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
CPlayer* player = g_Game->GetLocalPlayer();
u32 x = 0;
u32 y = 0;
u32 w = m_MapSize - 1;
u32 h = m_MapSize - 1;
for(u32 j = 0; j < h; j++)
{
u8 *dataPtr = m_LOSData + ((y + j) * (m_MapSize - 1)) + x;
for(u32 i = 0; i < w; i++)
{
ELOSStatus status = losMgr->GetStatus((int) i, (int) j, player);
if(status == LOS_UNEXPLORED)
{
*dataPtr++ = 0xff;
}
else if(status == LOS_EXPLORED)
{
*dataPtr++ = (u8) (0xff * 0.3f);
}
else {
*dataPtr++ = 0;
}
}
}
// Upload the texture
g_Renderer.BindTexture(0, m_LOSTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize - 1, m_MapSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, m_LOSData);
PROFILE_END("rebuild minimap: los");
}
void CMiniMap::Destroy()
{
if(m_Handle)
glDeleteTextures(1, (GLuint *)&m_Handle);
if(m_TerrainTexture)
glDeleteTextures(1, (GLuint *)&m_TerrainTexture);
if(m_Data)
if(m_LOSTexture)
glDeleteTextures(1, (GLuint *)&m_LOSTexture);
if(m_TerrainData)
{
delete[] m_Data;
m_Data = NULL;
delete[] m_TerrainData;
m_TerrainData = 0;
}
if(m_LOSData)
{
delete[] m_LOSData;
m_LOSData = 0;
}
}

View File

@ -7,6 +7,8 @@
class CTerrain;
class CUnitManager;
extern bool g_TerrainModified;
class CMiniMap : public IGUIObject
{
GUI_OBJECT(CMiniMap)
@ -16,14 +18,14 @@ public:
protected:
virtual void Draw();
// generate the mini-map texture
void GenerateMiniMapTexture();
// create the minimap textures
void CreateTextures();
// rebuild the texture map
void Rebuild();
// rebuild the terrain texture map
void RebuildTerrainTexture();
// upload the minimap texture
void UploadTexture();
// rebuild the LOS map
void RebuildLOSTexture();
// destroy and free any memory and textures
void Destroy();
@ -39,11 +41,13 @@ protected:
// the unit manager with unit positions
CUnitManager *m_UnitManager;
// minimap texture handle
u32 m_Handle;
// minimap texture handles
u32 m_TerrainTexture;
u32 m_LOSTexture;
// texture data
u32 *m_Data;
u32 *m_TerrainData;
u8 *m_LOSData;
// width
u32 m_Width;

View File

@ -39,6 +39,7 @@ that of Atlas depending on commandline parameters.
#define LOG_CATEGORY "main"
extern bool g_TerrainModified;
void kill_mainloop();
@ -239,6 +240,9 @@ static void Frame()
if(g_FixedFrameTiming && frameCount==100)
kill_mainloop();
// clear terrain modified flag
g_TerrainModified = false;
}

View File

@ -41,6 +41,7 @@
#endif
extern CConsole* g_Console;
extern bool g_TerrainModified;
// rationale: the function table is now at the end of the source file to
@ -786,6 +787,7 @@ JSBool setWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc,
return( JS_FALSE );
}
g_Renderer.m_WaterHeight = newHeight;
g_TerrainModified = true;
*rval = JSVAL_VOID;
return( JS_TRUE );
}