mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-26 02:03:48 +00:00
Make GridRender use a single draw call instead of expensive grid scanning
This commit is contained in:
parent
70b8e69402
commit
511f064bbe
9 changed files with 244 additions and 93 deletions
104
Aquaria/Game.cpp
104
Aquaria/Game.cpp
|
@ -18,6 +18,9 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include <algorithm>
|
||||||
#include "../BBGE/Gradient.h"
|
#include "../BBGE/Gradient.h"
|
||||||
#include "../BBGE/AfterEffect.h"
|
#include "../BBGE/AfterEffect.h"
|
||||||
#include "../BBGE/MathFunctions.h"
|
#include "../BBGE/MathFunctions.h"
|
||||||
|
@ -31,7 +34,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "ReadXML.h"
|
#include "ReadXML.h"
|
||||||
#include "RenderBase.h"
|
#include "RenderBase.h"
|
||||||
|
|
||||||
#include "Game.h"
|
|
||||||
#include "GridRender.h"
|
#include "GridRender.h"
|
||||||
#include "WaterSurfaceRender.h"
|
#include "WaterSurfaceRender.h"
|
||||||
#include "ScriptedEntity.h"
|
#include "ScriptedEntity.h"
|
||||||
|
@ -328,6 +330,8 @@ void Game::addObsRow(unsigned tx, unsigned ty, unsigned len)
|
||||||
void Game::clearObsRows()
|
void Game::clearObsRows()
|
||||||
{
|
{
|
||||||
obsRows.clear();
|
obsRows.clear();
|
||||||
|
mapGridW = 0;
|
||||||
|
mapGridH = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
|
void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
|
||||||
|
@ -539,6 +543,8 @@ void Game::reconstructEntityGrid()
|
||||||
Entity *e = *i;
|
Entity *e = *i;
|
||||||
e->fillGrid();
|
e->fillGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateGridRender(OT_INVISIBLEENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::reconstructGrid(bool force)
|
void Game::reconstructGrid(bool force)
|
||||||
|
@ -574,6 +580,9 @@ void Game::reconstructGrid(bool force)
|
||||||
}
|
}
|
||||||
|
|
||||||
trimGrid();
|
trimGrid();
|
||||||
|
|
||||||
|
// This does intentionally not update black.
|
||||||
|
updateGridRender(OT_MASK_NOTBLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::trimGrid()
|
void Game::trimGrid()
|
||||||
|
@ -1887,25 +1896,36 @@ void Game::setMusicToPlay(const std::string &m)
|
||||||
stringToLower(musicToPlay);
|
stringToLower(musicToPlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TileVector Game::computeMapSizeFromObs() const
|
||||||
|
{
|
||||||
|
TileVector ret;
|
||||||
|
const size_t N = obsRows.size();
|
||||||
|
for (size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
const ObsRow *r = &obsRows[i];
|
||||||
|
ret.x = std::max<unsigned>(ret.x, r->tx + r->len);
|
||||||
|
ret.y = std::max<unsigned>(ret.y, r->ty);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void Game::findMaxCameraValues()
|
void Game::findMaxCameraValues()
|
||||||
{
|
{
|
||||||
cameraMin.x = 20;
|
cameraMin.x = 20;
|
||||||
cameraMin.y = 20;
|
cameraMin.y = 20;
|
||||||
|
if(obsRows.size())
|
||||||
|
{
|
||||||
|
TileVector wh = computeMapSizeFromObs();
|
||||||
|
mapGridW = wh.x;
|
||||||
|
mapGridH = wh.y;
|
||||||
|
cameraMax = wh.worldVector();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapGridW = 0;
|
||||||
|
mapGridH = 0;
|
||||||
cameraMax.x = -1;
|
cameraMax.x = -1;
|
||||||
cameraMax.y = -1;
|
cameraMax.y = -1;
|
||||||
for (size_t i = 0; i < obsRows.size(); i++)
|
|
||||||
{
|
|
||||||
ObsRow *r = &obsRows[i];
|
|
||||||
TileVector t(r->tx + r->len, r->ty);
|
|
||||||
Vector v = t.worldVector();
|
|
||||||
if (v.x > cameraMax.x)
|
|
||||||
{
|
|
||||||
cameraMax.x = v.x;
|
|
||||||
}
|
|
||||||
if (v.y > cameraMax.y)
|
|
||||||
{
|
|
||||||
cameraMax.y = v.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2679,6 +2699,16 @@ void Game::applyState()
|
||||||
|
|
||||||
bindInput();
|
bindInput();
|
||||||
|
|
||||||
|
// loadScene() calls reconstructGrid(), which requires these to exist
|
||||||
|
blackRender = new GridRender(OT_BLACK);
|
||||||
|
gridRender = new GridRender(OT_INVISIBLE);
|
||||||
|
gridRender2 = new GridRender(OT_HURT);
|
||||||
|
gridRender3 = new GridRender(OT_INVISIBLEIN);
|
||||||
|
edgeRender = new GridRender(OT_BLACKINVIS);
|
||||||
|
gridRenderEnt = new GridRender(OT_INVISIBLEENT);
|
||||||
|
gridRenderUser1 = new GridRender(OT_USER1);
|
||||||
|
gridRenderUser2 = new GridRender(OT_USER2);
|
||||||
|
|
||||||
if (verbose) debugLog("Loading Scene");
|
if (verbose) debugLog("Loading Scene");
|
||||||
if(!loadScene(sceneToLoad))
|
if(!loadScene(sceneToLoad))
|
||||||
{
|
{
|
||||||
|
@ -2686,6 +2716,8 @@ void Game::applyState()
|
||||||
}
|
}
|
||||||
if (verbose) debugLog("...Done");
|
if (verbose) debugLog("...Done");
|
||||||
|
|
||||||
|
// ----------------- SCENE IS LOADED BELOW HERE -------------------
|
||||||
|
|
||||||
dsq->continuity.worldMap.revealMap(sceneName);
|
dsq->continuity.worldMap.revealMap(sceneName);
|
||||||
|
|
||||||
if (verbose) debugLog("Adding Avatar");
|
if (verbose) debugLog("Adding Avatar");
|
||||||
|
@ -2703,37 +2735,31 @@ void Game::applyState()
|
||||||
songLineRender = new SongLineRender();
|
songLineRender = new SongLineRender();
|
||||||
addRenderObject(songLineRender, LR_HUD);
|
addRenderObject(songLineRender, LR_HUD);
|
||||||
|
|
||||||
gridRender = new GridRender(OT_INVISIBLE);
|
|
||||||
gridRender->color = Vector(1, 0, 0);
|
gridRender->color = Vector(1, 0, 0);
|
||||||
addRenderObject(gridRender, LR_DEBUG_TEXT);
|
addRenderObject(gridRender, LR_DEBUG_TEXT);
|
||||||
gridRender->alpha = 0;
|
gridRender->alpha = 0;
|
||||||
|
|
||||||
gridRender2 = new GridRender(OT_HURT);
|
|
||||||
gridRender2->color = Vector(1, 1, 0);
|
gridRender2->color = Vector(1, 1, 0);
|
||||||
addRenderObject(gridRender2, LR_DEBUG_TEXT);
|
addRenderObject(gridRender2, LR_DEBUG_TEXT);
|
||||||
gridRender2->alpha = 0;
|
gridRender2->alpha = 0;
|
||||||
|
|
||||||
gridRender3 = new GridRender(OT_INVISIBLEIN);
|
|
||||||
gridRender3->color = Vector(1, 0.5f, 0);
|
gridRender3->color = Vector(1, 0.5f, 0);
|
||||||
addRenderObject(gridRender3, LR_DEBUG_TEXT);
|
addRenderObject(gridRender3, LR_DEBUG_TEXT);
|
||||||
gridRender3->alpha = 0;
|
gridRender3->alpha = 0;
|
||||||
|
|
||||||
edgeRender = new GridRender(OT_BLACKINVIS);
|
|
||||||
edgeRender->color = Vector(0.3f, 0, 0.6f);
|
edgeRender->color = Vector(0.3f, 0, 0.6f);
|
||||||
addRenderObject(edgeRender, LR_DEBUG_TEXT);
|
addRenderObject(edgeRender, LR_DEBUG_TEXT);
|
||||||
edgeRender->alpha = 0;
|
edgeRender->alpha = 0;
|
||||||
|
|
||||||
gridRenderEnt = new GridRender(OT_INVISIBLEENT);
|
|
||||||
gridRenderEnt->color = Vector(0, 1, 0.5);
|
gridRenderEnt->color = Vector(0, 1, 0.5);
|
||||||
addRenderObject(gridRenderEnt, LR_DEBUG_TEXT);
|
addRenderObject(gridRenderEnt, LR_DEBUG_TEXT);
|
||||||
gridRenderEnt->alpha = 0;
|
gridRenderEnt->alpha = 0;
|
||||||
|
|
||||||
gridRenderUser1 = new GridRender(OT_USER1);
|
|
||||||
addRenderObject(gridRenderUser1, LR_DEBUG_TEXT);
|
addRenderObject(gridRenderUser1, LR_DEBUG_TEXT);
|
||||||
gridRenderUser1->color = Vector(1, 0, 1);
|
gridRenderUser1->color = Vector(1, 0, 1);
|
||||||
gridRenderUser1->alpha = 0;
|
gridRenderUser1->alpha = 0;
|
||||||
|
|
||||||
gridRenderUser2 = new GridRender(OT_USER2);
|
|
||||||
addRenderObject(gridRenderUser2, LR_DEBUG_TEXT);
|
addRenderObject(gridRenderUser2, LR_DEBUG_TEXT);
|
||||||
gridRenderUser2->color = Vector(1, 1, 1);
|
gridRenderUser2->color = Vector(1, 1, 1);
|
||||||
gridRenderUser2->alpha = 0;
|
gridRenderUser2->alpha = 0;
|
||||||
|
@ -2742,11 +2768,11 @@ void Game::applyState()
|
||||||
//waterSurfaceRender->setRenderPass(-1);
|
//waterSurfaceRender->setRenderPass(-1);
|
||||||
addRenderObject(waterSurfaceRender, LR_WATERSURFACE);
|
addRenderObject(waterSurfaceRender, LR_WATERSURFACE);
|
||||||
|
|
||||||
GridRender *blackRender = new GridRender(OT_BLACK);
|
|
||||||
blackRender->color = Vector(0, 0, 0);
|
blackRender->color = Vector(0, 0, 0);
|
||||||
//blackRender->alpha = 0;
|
//blackRender->alpha = 0;
|
||||||
blackRender->setBlendType(BLEND_DISABLED);
|
blackRender->setBlendType(BLEND_DISABLED);
|
||||||
addRenderObject(blackRender, LR_ELEMENTS4);
|
addRenderObject(blackRender, LR_ELEMENTS4);
|
||||||
|
blackRender->rebuildBuffers(this->obsRows);
|
||||||
|
|
||||||
miniMapRender = new MiniMapRender;
|
miniMapRender = new MiniMapRender;
|
||||||
// position is set in minimaprender::onupdate
|
// position is set in minimaprender::onupdate
|
||||||
|
@ -3986,7 +4012,16 @@ void Game::toggleGridRender()
|
||||||
float t = 0;
|
float t = 0;
|
||||||
float a = 0;
|
float a = 0;
|
||||||
if (gridRender->alpha == 0)
|
if (gridRender->alpha == 0)
|
||||||
|
{
|
||||||
a = 0.5f;
|
a = 0.5f;
|
||||||
|
gridRender->rebuildBuffersIfNecessary();
|
||||||
|
gridRender2->rebuildBuffersIfNecessary();
|
||||||
|
gridRender3->rebuildBuffersIfNecessary();
|
||||||
|
edgeRender->rebuildBuffersIfNecessary();
|
||||||
|
gridRenderEnt->rebuildBuffersIfNecessary();
|
||||||
|
gridRenderUser1->rebuildBuffersIfNecessary();
|
||||||
|
gridRenderUser2->rebuildBuffersIfNecessary();
|
||||||
|
}
|
||||||
|
|
||||||
gridRender->alpha.interpolateTo(a, t);
|
gridRender->alpha.interpolateTo(a, t);
|
||||||
gridRender2->alpha.interpolateTo(a, t);
|
gridRender2->alpha.interpolateTo(a, t);
|
||||||
|
@ -3997,6 +4032,30 @@ void Game::toggleGridRender()
|
||||||
gridRenderUser2->alpha.interpolateTo(a, t);
|
gridRenderUser2->alpha.interpolateTo(a, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkgridrender(GridRender *gr, ObsType obs)
|
||||||
|
{
|
||||||
|
if(gr->getObs() & obs)
|
||||||
|
gr->markForRebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::updateGridRender(ObsType obs)
|
||||||
|
{
|
||||||
|
// These are usually not visible. Delay rebuild until they are actually shown.
|
||||||
|
checkgridrender(gridRender, obs);
|
||||||
|
checkgridrender(gridRender2, obs);
|
||||||
|
checkgridrender(gridRender3, obs);
|
||||||
|
checkgridrender(edgeRender, obs);
|
||||||
|
checkgridrender(gridRenderEnt, obs);
|
||||||
|
checkgridrender(gridRenderUser1, obs);
|
||||||
|
checkgridrender(gridRenderUser2, obs);
|
||||||
|
|
||||||
|
// This is normally not necessary, because black is only changed by the editor.
|
||||||
|
// Keeping it here possibly for future mod compat.
|
||||||
|
// It's also always shown, so we can immediately rebuild it
|
||||||
|
if(obs & OT_BLACK)
|
||||||
|
blackRender->rebuildBuffers(this->obsRows);
|
||||||
|
}
|
||||||
|
|
||||||
Vector Game::getCameraPositionFor(const Vector &pos)
|
Vector Game::getCameraPositionFor(const Vector &pos)
|
||||||
{
|
{
|
||||||
return Vector(pos.x - 400 * core->invGlobalScale, pos.y - 300 * core->invGlobalScale, 0);
|
return Vector(pos.x - 400 * core->invGlobalScale, pos.y - 300 * core->invGlobalScale, 0);
|
||||||
|
@ -4721,6 +4780,7 @@ void Game::removeState()
|
||||||
controlHint_text = 0;
|
controlHint_text = 0;
|
||||||
|
|
||||||
miniMapRender = 0;
|
miniMapRender = 0;
|
||||||
|
blackRender = 0;
|
||||||
gridRender = 0;
|
gridRender = 0;
|
||||||
gridRender2 = 0;
|
gridRender2 = 0;
|
||||||
gridRender3 = 0;
|
gridRender3 = 0;
|
||||||
|
|
|
@ -85,22 +85,6 @@ struct MinimapIcon
|
||||||
|
|
||||||
typedef std::list<Ingredient*> Ingredients;
|
typedef std::list<Ingredient*> Ingredients;
|
||||||
|
|
||||||
class ObsRow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline ObsRow(unsigned tx, unsigned ty, unsigned len)
|
|
||||||
: tx(tx), ty(ty), len(len) {}
|
|
||||||
inline ObsRow(const ObsRow& o)
|
|
||||||
: tx(o.tx), ty(o.ty), len(o.len) {}
|
|
||||||
const unsigned tx, ty, len;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FlagCheckType
|
|
||||||
{
|
|
||||||
NO_TYPE =-1,
|
|
||||||
AND =0,
|
|
||||||
OR =1
|
|
||||||
};
|
|
||||||
|
|
||||||
class EntityClass
|
class EntityClass
|
||||||
{
|
{
|
||||||
|
@ -136,6 +120,7 @@ public:
|
||||||
Avatar *avatar;
|
Avatar *avatar;
|
||||||
Entity *li;
|
Entity *li;
|
||||||
|
|
||||||
|
TileVector getGridSize() const; // available after calling findMaxCameraValues()
|
||||||
ObsType getGrid(const TileVector &tile) const;
|
ObsType getGrid(const TileVector &tile) const;
|
||||||
ObsType getGridRaw(const TileVector &tile) const;
|
ObsType getGridRaw(const TileVector &tile) const;
|
||||||
unsigned char *getGridColumn(int tileX);
|
unsigned char *getGridColumn(int tileX);
|
||||||
|
@ -381,8 +366,9 @@ public:
|
||||||
void createGradient();
|
void createGradient();
|
||||||
|
|
||||||
std::string saveMusic;
|
std::string saveMusic;
|
||||||
GridRender *gridRender, *gridRender2, *gridRender3, *edgeRender, *gridRenderEnt, *gridRenderUser1, *gridRenderUser2;
|
GridRender *blackRender, *gridRender, *gridRender2, *gridRender3, *edgeRender, *gridRenderEnt, *gridRenderUser1, *gridRenderUser2;
|
||||||
void toggleGridRender();
|
void toggleGridRender();
|
||||||
|
void updateGridRender(ObsType obs);
|
||||||
|
|
||||||
bool invinciblity;
|
bool invinciblity;
|
||||||
|
|
||||||
|
@ -457,7 +443,9 @@ protected:
|
||||||
void createLi();
|
void createLi();
|
||||||
void createPets();
|
void createPets();
|
||||||
void findMaxCameraValues();
|
void findMaxCameraValues();
|
||||||
|
TileVector computeMapSizeFromObs() const;
|
||||||
std::vector<ObsRow> obsRows;
|
std::vector<ObsRow> obsRows;
|
||||||
|
size_t mapGridW, mapGridH;
|
||||||
|
|
||||||
|
|
||||||
std::string musicToPlay;
|
std::string musicToPlay;
|
||||||
|
@ -503,6 +491,11 @@ ObsType Game::getGridRaw(const TileVector &tile) const
|
||||||
: OT_OUTOFBOUNDS;
|
: OT_OUTOFBOUNDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline TileVector Game::getGridSize() const
|
||||||
|
{
|
||||||
|
return TileVector(int(this->mapGridW), int(this->mapGridH));
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
ObsType Game::getGrid(const TileVector &tile) const
|
ObsType Game::getGrid(const TileVector &tile) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@ enum ObsType
|
||||||
OT_BLACK = 0x01,
|
OT_BLACK = 0x01,
|
||||||
OT_BLACKINVIS = 0x02, // same as OT_BLACK, but not drawn
|
OT_BLACKINVIS = 0x02, // same as OT_BLACK, but not drawn
|
||||||
OT_MASK_BLACK = OT_BLACK | OT_BLACKINVIS,
|
OT_MASK_BLACK = OT_BLACK | OT_BLACKINVIS,
|
||||||
|
OT_MASK_NOTBLACK = ~OT_MASK_BLACK,
|
||||||
|
|
||||||
// set by tiles
|
// set by tiles
|
||||||
OT_INVISIBLE = 0x04,
|
OT_INVISIBLE = 0x04,
|
||||||
|
@ -31,7 +32,7 @@ enum ObsType
|
||||||
OT_USER2 = 0x80,
|
OT_USER2 = 0x80,
|
||||||
OT_USER_MASK = OT_USER1 | OT_USER2,
|
OT_USER_MASK = OT_USER1 | OT_USER2,
|
||||||
|
|
||||||
OT_OUTOFBOUNDS = 0xff
|
OT_OUTOFBOUNDS = 0xff, // all bits set
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -186,5 +186,15 @@ struct UnderWaterResult
|
||||||
Path *waterbubble;
|
Path *waterbubble;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ObsRow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline ObsRow(unsigned tx, unsigned ty, unsigned len)
|
||||||
|
: tx(tx), ty(ty), len(len) {}
|
||||||
|
inline ObsRow(const ObsRow& o)
|
||||||
|
: tx(o.tx), ty(o.ty), len(o.len) {}
|
||||||
|
const unsigned tx, ty, len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,39 +22,142 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "RenderBase.h"
|
#include "RenderBase.h"
|
||||||
|
|
||||||
GridRender::GridRender(ObsType obsType) : RenderObject()
|
|
||||||
|
static void collectRows(std::vector<ObsRow>& rows, ObsType obs)
|
||||||
|
{
|
||||||
|
const TileVector gs = game->getGridSize();
|
||||||
|
const size_t endX = std::min(gs.x, MAX_GRID);
|
||||||
|
const size_t endY = std::min(gs.y, MAX_GRID);
|
||||||
|
|
||||||
|
for(size_t y = 0; y < endY; ++y)
|
||||||
|
{
|
||||||
|
bool on = game->getGridRaw(TileVector(0, y)) == obs;
|
||||||
|
size_t startx = 0;
|
||||||
|
for(size_t x = 1; x < endX; ++x)
|
||||||
|
{
|
||||||
|
const ObsType ot = game->getGridRaw(TileVector(x, y));
|
||||||
|
if(ot == obs)
|
||||||
|
{
|
||||||
|
if(!on)
|
||||||
|
{
|
||||||
|
startx = x;
|
||||||
|
on = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(on)
|
||||||
|
{
|
||||||
|
// previous tile is the last one, so -1
|
||||||
|
rows.push_back(ObsRow(startx, y, x - startx));
|
||||||
|
on = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(on)
|
||||||
|
rows.push_back(ObsRow(startx, y, endX - startx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GridRender::GridRender(ObsType obsType)
|
||||||
|
: RenderObject()
|
||||||
|
, vbo(GPUBUF_VERTEXBUF | GPUBUF_STATIC)
|
||||||
|
, primsToDraw(0)
|
||||||
|
, obsType(obsType)
|
||||||
|
//, ibo(GPUBUF_INDEXBUF | GPUBUF_STATIC)
|
||||||
|
, markedForRebuild(true)
|
||||||
{
|
{
|
||||||
color = Vector(1, 0, 0);
|
color = Vector(1, 0, 0);
|
||||||
|
|
||||||
position.z = 5;
|
position.z = 5;
|
||||||
cull = false;
|
cull = false;
|
||||||
alpha = 0.5f;
|
alpha = 0.5f;
|
||||||
this->obsType = obsType;
|
this->scale.x = TILE_SIZE;
|
||||||
|
this->scale.y = TILE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridRender::onUpdate(float dt)
|
void GridRender::rebuildBuffers()
|
||||||
{
|
{
|
||||||
RenderObject::onUpdate(dt);
|
std::vector<ObsRow> rows;
|
||||||
|
collectRows(rows, obsType);
|
||||||
|
rebuildBuffers(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void doRenderGrid(int x, int startCol, int endCol)
|
void GridRender::rebuildBuffers(const std::vector<ObsRow>& rows)
|
||||||
{
|
{
|
||||||
const int drawx1 = x*TILE_SIZE;
|
markedForRebuild = false;
|
||||||
const int drawx2 = (x+1)*TILE_SIZE;
|
|
||||||
const int drawy1 = startCol*TILE_SIZE;
|
|
||||||
const int drawy2 = (endCol+1)*TILE_SIZE;
|
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
const size_t N = rows.size();
|
||||||
glVertex3i(drawx1, drawy2, 0.0f);
|
primsToDraw = N * 6;
|
||||||
glVertex3i(drawx2, drawy2, 0.0f);
|
if(!N)
|
||||||
glVertex3i(drawx2, drawy1, 0.0f);
|
return;
|
||||||
glVertex3i(drawx1, drawy1, 0.0f);
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
|
// 2 tris = 6 verts per ObsRow, each vertex is 2x uint16, makes 24b per quad.
|
||||||
|
// We could use indexed rendering and use 2 verts less (16b),
|
||||||
|
// but the 6 indices would cost another 12b so it's definitely cheaper to send
|
||||||
|
// triangle soup to the gpu in this case, since each vertex is only 4 bytes.
|
||||||
|
const size_t szv = N * 6 * 2 * sizeof(unsigned short);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
unsigned short *pxy = (unsigned short*)vbo.beginWrite(GPUBUFTYPE_UVEC2, szv, GPUACCESS_DEFAULT);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
const ObsRow& row = rows[i];
|
||||||
|
|
||||||
|
// Don't bother to transform to float. The GPU can do that better.
|
||||||
|
// The scale factor of a GridRender is set to TILE_SIZE, that pre-bakes the
|
||||||
|
// required scaling multiplication into the object scale so we can get away
|
||||||
|
// with using raw, unscaled values here
|
||||||
|
|
||||||
|
const unsigned short x0 = row.tx;
|
||||||
|
const unsigned short x1 = row.tx + row.len;
|
||||||
|
const unsigned short y0 = row.ty;
|
||||||
|
const unsigned short y1 = row.ty + 1;
|
||||||
|
|
||||||
|
// top left triangle
|
||||||
|
*pxy++ = x0;
|
||||||
|
*pxy++ = y0;
|
||||||
|
|
||||||
|
*pxy++ = x1;
|
||||||
|
*pxy++ = y0;
|
||||||
|
|
||||||
|
*pxy++ = x0;
|
||||||
|
*pxy++ = y1;
|
||||||
|
|
||||||
|
// bottom right triangle
|
||||||
|
*pxy++ = x1;
|
||||||
|
*pxy++ = y0;
|
||||||
|
|
||||||
|
*pxy++ = x1;
|
||||||
|
*pxy++ = y1;
|
||||||
|
|
||||||
|
*pxy++ = x0;
|
||||||
|
*pxy++ = y1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!vbo.commitWrite());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridRender::rebuildBuffersIfNecessary()
|
||||||
|
{
|
||||||
|
if(markedForRebuild)
|
||||||
|
rebuildBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridRender::rebuildBuffersIfNecessary(const std::vector<ObsRow>& rows)
|
||||||
|
{
|
||||||
|
if(markedForRebuild)
|
||||||
|
rebuildBuffers(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridRender::onRender(const RenderState& rs) const
|
void GridRender::onRender(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
|
if(!primsToDraw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
const signed char obsType = this->obsType;
|
const signed char obsType = this->obsType;
|
||||||
Vector camPos = core->cameraPos;
|
Vector camPos = core->cameraPos;
|
||||||
camPos.x -= core->getVirtualOffX() * (core->invGlobalScale);
|
camPos.x -= core->getVirtualOffX() * (core->invGlobalScale);
|
||||||
|
@ -75,41 +178,13 @@ void GridRender::onRender(const RenderState& rs) const
|
||||||
endY = MAX_GRID-1;
|
endY = MAX_GRID-1;
|
||||||
if (startY > endY)
|
if (startY > endY)
|
||||||
return;
|
return;
|
||||||
for (int x = startX; x <= endX; ++x)
|
*/
|
||||||
{
|
|
||||||
const unsigned char *gridColumn = game->getGridColumn(x);
|
|
||||||
int startCol = -1, y;
|
|
||||||
|
|
||||||
// fast-forward to next drawable byte
|
// TODO: keep track of prim index at which a row starts
|
||||||
if(const unsigned char *next = (const unsigned char*)memchr(gridColumn + startY, obsType, endY - startY + 1)) // find next byte with correct obs type
|
// then horizontally span only as much prims as are necessary?
|
||||||
{
|
|
||||||
y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol
|
|
||||||
startCol = y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
continue; // nothing do draw in this column
|
|
||||||
|
|
||||||
for ( ; y < endY; ++y)
|
vbo.apply();
|
||||||
{
|
glDrawArrays(GL_TRIANGLES, 0, primsToDraw);
|
||||||
if (gridColumn[y] != obsType)
|
|
||||||
{
|
|
||||||
doRenderGrid(x, startCol, y - 1);
|
|
||||||
|
|
||||||
// fast-forward to next drawable byte
|
|
||||||
if(const unsigned char *next = (const unsigned char*)memchr(gridColumn + y, obsType, endY - y)) // find next byte with correct obs type
|
|
||||||
{
|
|
||||||
y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol
|
|
||||||
startCol = y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (y == endY)
|
|
||||||
{
|
|
||||||
doRenderGrid(x, startCol, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongLineRender::SongLineRender()
|
SongLineRender::SongLineRender()
|
||||||
|
|
|
@ -22,8 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define GRIDRENDER_H
|
#define GRIDRENDER_H
|
||||||
|
|
||||||
#include "GameEnums.h"
|
#include "GameEnums.h"
|
||||||
|
#include "GameStructs.h"
|
||||||
#include "../BBGE/Quad.h"
|
#include "../BBGE/Quad.h"
|
||||||
#include "ActionMapper.h"
|
#include "ActionMapper.h"
|
||||||
|
#include "VertexBuffer.h"
|
||||||
|
|
||||||
class GemMover;
|
class GemMover;
|
||||||
struct MinimapIcon;
|
struct MinimapIcon;
|
||||||
|
@ -36,9 +38,18 @@ class GridRender : public RenderObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GridRender(ObsType obsType);
|
GridRender(ObsType obsType);
|
||||||
|
void rebuildBuffers();
|
||||||
|
void rebuildBuffers(const std::vector<ObsRow>& rows);
|
||||||
|
void rebuildBuffersIfNecessary();
|
||||||
|
void rebuildBuffersIfNecessary(const std::vector<ObsRow>& rows);
|
||||||
|
void markForRebuild() { markedForRebuild = true; }
|
||||||
|
ObsType getObs() const { return obsType; }
|
||||||
protected:
|
protected:
|
||||||
ObsType obsType;
|
DynamicGPUBuffer vbo;
|
||||||
void onUpdate(float dt) OVERRIDE;
|
size_t primsToDraw;
|
||||||
|
const ObsType obsType;
|
||||||
|
bool markedForRebuild;
|
||||||
|
|
||||||
void onRender(const RenderState& rs) const OVERRIDE;
|
void onRender(const RenderState& rs) const OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1622,6 +1622,7 @@ void SceneEditor::generateLevel()
|
||||||
}
|
}
|
||||||
|
|
||||||
game->reconstructGrid(true);
|
game->reconstructGrid(true);
|
||||||
|
game->updateGridRender(OT_MASK_BLACK);
|
||||||
|
|
||||||
maxX--;
|
maxX--;
|
||||||
maxY--;
|
maxY--;
|
||||||
|
|
|
@ -87,7 +87,6 @@ GL_FUNC(void,glTexCoord2f,(GLfloat s, GLfloat t),(s,t),)
|
||||||
//GL_FUNC(void,glTexCoord2d,(GLdouble s, GLdouble t),(s,t),)
|
//GL_FUNC(void,glTexCoord2d,(GLdouble s, GLdouble t),(s,t),)
|
||||||
GL_FUNC(void,glVertex2f,(GLfloat x, GLfloat y),(x,y),)
|
GL_FUNC(void,glVertex2f,(GLfloat x, GLfloat y),(x,y),)
|
||||||
GL_FUNC(void,glVertex3f,(GLfloat x, GLfloat y, GLfloat z),(x,y,z),)
|
GL_FUNC(void,glVertex3f,(GLfloat x, GLfloat y, GLfloat z),(x,y,z),)
|
||||||
GL_FUNC(void,glVertex3i,(GLint x, GLint y, GLint z),(x,y,z),)
|
|
||||||
|
|
||||||
// stuff GLU needs...
|
// stuff GLU needs...
|
||||||
GL_FUNC(void,glGetIntegerv,(GLenum pname, GLint *params),(pname,params),)
|
GL_FUNC(void,glGetIntegerv,(GLenum pname, GLint *params),(pname,params),)
|
||||||
|
|
|
@ -29,7 +29,8 @@ enum BufDataType
|
||||||
GPUBUFTYPE_VEC2_TC = 0x00081021, // xyuv xyuv xyuv
|
GPUBUFTYPE_VEC2_TC = 0x00081021, // xyuv xyuv xyuv
|
||||||
GPUBUFTYPE_VEC2_TC_RGBA = 0x10082021, // xyuvrgba xyuvrgba xyuvrgba
|
GPUBUFTYPE_VEC2_TC_RGBA = 0x10082021, // xyuvrgba xyuvrgba xyuvrgba
|
||||||
// ccoossnt
|
// ccoossnt
|
||||||
GPUBUFTYPE_VEC2_TC_RGBA_BUT_NO_COLOR = GPUBUFTYPE_VEC2_TC_RGBA & 0xffffff
|
GPUBUFTYPE_VEC2_TC_RGBA_BUT_NO_COLOR = GPUBUFTYPE_VEC2_TC_RGBA & 0xffffff,
|
||||||
|
GPUBUFTYPE_UVEC2 = 0x00000420
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AccessFlags
|
enum AccessFlags
|
||||||
|
|
Loading…
Reference in a new issue