mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-05-10 19:13:44 +00:00
Changes to rendering logic, incl water surface flicker fix, plus other fixes.
This commit changes a bunch of internal rendering logic to use FBOs in a way that doesn't violate the GL spec. The water surface FBO's output texture was bound for reading while at the same time rendering the water surface back into the same FBO! Depending on the card/driver/load/zoom factor/moon phase, this could lead to water surface flickering, chessboard effects, and other visual glitches. In order to fix this an extra FBO is needed. In theory this is a simple fix but in practice this is the Aquaria codebase and everything is more complicated than it has any right to be. Couple other things: - FBOs no longer have a depth renderbuffer. Aquaria never uses the depth buffer for anything, so this can go to save some memory. Also remove renderbuffer GL function pointers. - Make FBOs multi-"paged". This is supposedly more efficient on desktop GL, if glDrawBuffer() supports GL_COLOR_ATTACHMENTn. This is currently checked via the presence of glDrawBuffersARB(). - Main core FBO now has 2 pages becaus it's needed for the water surface. The same 2 pages are later used by the after effect manager to ping-pong postprocessing shaders. Remove private after effect FBO. TODO: - There's still a bug in the one-fbo-multiple-binding-points code path. -> for now glDrawBuffersARB must be NULL to work properly.
This commit is contained in:
parent
dd7ab0448f
commit
09edbf49fd
19 changed files with 608 additions and 390 deletions
|
@ -201,7 +201,6 @@ DSQ::DSQ(const std::string& fileSystem, const std::string& extraDataDir)
|
||||||
console = 0;
|
console = 0;
|
||||||
cmDebug = 0;
|
cmDebug = 0;
|
||||||
saveSlotMode = SSM_NONE;
|
saveSlotMode = SSM_NONE;
|
||||||
afterEffectManagerLayer = LR_AFTER_EFFECTS; // LR_AFTER_EFFECTS
|
|
||||||
renderObjectLayers.resize(LR_MAX);
|
renderObjectLayers.resize(LR_MAX);
|
||||||
|
|
||||||
entities.resize(64, 0);
|
entities.resize(64, 0);
|
||||||
|
@ -585,7 +584,7 @@ static void loadBit(int index, float perc = 1)
|
||||||
|
|
||||||
loading->setWidthHeight(loadingProgress*600, 23);
|
loading->setWidthHeight(loadingProgress*600, 23);
|
||||||
|
|
||||||
dsq->render();
|
dsq->renderExternal();
|
||||||
dsq->showBuffer();
|
dsq->showBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,6 +687,45 @@ static bool sdlVideoModeOK(int disp, const int w, const int h, const int bpp)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool preRenderDarkLayer(const RenderState& rs)
|
||||||
|
{
|
||||||
|
if(core->darkLayer.isUsed())
|
||||||
|
core->darkLayer.beginCapture();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void postRenderDarkLayer(const RenderState& rs)
|
||||||
|
{
|
||||||
|
if(core->darkLayer.isUsed())
|
||||||
|
{
|
||||||
|
core->darkLayer.endCapture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool beginAfterEffectCapture(const RenderState& rs)
|
||||||
|
{
|
||||||
|
if (core->afterEffectManager)
|
||||||
|
core->afterEffectManager->beginCapture();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool preRenderAfterEffectLayer(const RenderState& rs)
|
||||||
|
{
|
||||||
|
if(core->darkLayer.isUsed())
|
||||||
|
core->darkLayer.render(rs);
|
||||||
|
|
||||||
|
if(core->afterEffectManager)
|
||||||
|
{
|
||||||
|
unsigned page = core->frameBuffer.popCapture();
|
||||||
|
core->afterEffectManager->render(rs, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DSQ::init()
|
void DSQ::init()
|
||||||
{
|
{
|
||||||
#define PSIZEOF(x) { std::ostringstream os_; os_ << ("sizeof(" #x ") = ") << sizeof(x); debugLog(os_.str()); }
|
#define PSIZEOF(x) { std::ostringstream os_; os_ << ("sizeof(" #x ") = ") << sizeof(x); debugLog(os_.str()); }
|
||||||
|
@ -911,12 +949,6 @@ void DSQ::init()
|
||||||
precacher.clear();
|
precacher.clear();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render();
|
|
||||||
showBuffer();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loadBit(LOAD_INITIAL);
|
loadBit(LOAD_INITIAL);
|
||||||
|
|
||||||
debugLog("Loading Particle Bank...");
|
debugLog("Loading Particle Bank...");
|
||||||
|
@ -968,7 +1000,6 @@ void DSQ::init()
|
||||||
|
|
||||||
user.video.darkbuffersize = MAX(user.video.darkbuffersize,128);
|
user.video.darkbuffersize = MAX(user.video.darkbuffersize,128);
|
||||||
|
|
||||||
darkLayer.setLayers(LR_ELEMENTS13, LR_AFTER_EFFECTS);
|
|
||||||
debugLog("dark layer init");
|
debugLog("dark layer init");
|
||||||
darkLayer.init(user.video.darkbuffersize, user.video.darkfbuffer);
|
darkLayer.init(user.video.darkbuffersize, user.video.darkfbuffer);
|
||||||
debugLog("dark layer togle...");
|
debugLog("dark layer togle...");
|
||||||
|
@ -1270,6 +1301,14 @@ void DSQ::init()
|
||||||
renderObjectLayerOrder[LR_ENTITIES_MINUS3] = -1;
|
renderObjectLayerOrder[LR_ENTITIES_MINUS3] = -1;
|
||||||
renderObjectLayerOrder[LR_ENTITIES_MINUS2] = -1;
|
renderObjectLayerOrder[LR_ENTITIES_MINUS2] = -1;
|
||||||
|
|
||||||
|
renderObjectLayers[LR_ZERO].preRender = beginAfterEffectCapture;
|
||||||
|
renderObjectLayers[LR_AFTER_EFFECTS].preRender = preRenderAfterEffectLayer;
|
||||||
|
|
||||||
|
renderObjectLayers[LR_ELEMENTS13].preRender = preRenderDarkLayer;
|
||||||
|
renderObjectLayers[LR_ELEMENTS13].postRender = postRenderDarkLayer;
|
||||||
|
darkLayer.beginLayer = LR_ELEMENTS13;
|
||||||
|
darkLayer.lastLayer = LR_ELEMENTS13;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setMousePosition(center);
|
setMousePosition(center);
|
||||||
|
@ -2717,8 +2756,8 @@ void DSQ::doSaveSlotMenu(SaveSlotMode ssm, const Vector &position)
|
||||||
|
|
||||||
glPushAttrib(GL_VIEWPORT_BIT);
|
glPushAttrib(GL_VIEWPORT_BIT);
|
||||||
glViewport(0, 0, renderWidth, renderHeight);
|
glViewport(0, 0, renderWidth, renderHeight);
|
||||||
clearBuffers();
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
render();
|
renderExternal();
|
||||||
scrShotData = grabScreenshot(x, y, scrShotWidth, scrShotHeight);
|
scrShotData = grabScreenshot(x, y, scrShotWidth, scrShotHeight);
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
showBuffer();
|
showBuffer();
|
||||||
|
@ -3315,6 +3354,11 @@ void DSQ::prepScreen(bool screenshot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DSQ::onPrepareRender()
|
||||||
|
{
|
||||||
|
game->onPrepareRender();
|
||||||
|
}
|
||||||
|
|
||||||
void DSQ::onRender()
|
void DSQ::onRender()
|
||||||
{
|
{
|
||||||
if (cursor)
|
if (cursor)
|
||||||
|
@ -3661,7 +3705,7 @@ void DSQ::onUpdate(float dt)
|
||||||
pollEvents(sec);
|
pollEvents(sec);
|
||||||
ActionMapper::onUpdate(sec);
|
ActionMapper::onUpdate(sec);
|
||||||
SDL_Delay(int(sec*1000));
|
SDL_Delay(int(sec*1000));
|
||||||
render();
|
renderExternal();
|
||||||
showBuffer();
|
showBuffer();
|
||||||
resetTimer();
|
resetTimer();
|
||||||
|
|
||||||
|
@ -4162,17 +4206,18 @@ void AquariaScreenTransition::capture()
|
||||||
InterpolatedVector oldAlpha = dsq->cursor->alpha;
|
InterpolatedVector oldAlpha = dsq->cursor->alpha;
|
||||||
dsq->cursor->alpha.x = 0;
|
dsq->cursor->alpha.x = 0;
|
||||||
int width=0, height=0;
|
int width=0, height=0;
|
||||||
dsq->render();
|
dsq->renderExternal();
|
||||||
|
|
||||||
width = dsq->getWindowWidth();
|
width = dsq->getWindowWidth();
|
||||||
height = dsq->getWindowHeight();
|
height = dsq->getWindowHeight();
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
||||||
|
glReadBuffer(GL_BACK);
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
|
||||||
|
|
||||||
|
|
||||||
dsq->cursor->alpha = oldAlpha;
|
dsq->cursor->alpha = oldAlpha;
|
||||||
dsq->render();
|
dsq->renderExternal();
|
||||||
dsq->showBuffer();
|
dsq->showBuffer();
|
||||||
|
|
||||||
this->alpha = 1;
|
this->alpha = 1;
|
||||||
|
|
|
@ -444,8 +444,9 @@ protected:
|
||||||
float shakeCameraTimer;
|
float shakeCameraTimer;
|
||||||
float shakeCameraMag;
|
float shakeCameraMag;
|
||||||
|
|
||||||
void onUpdate(float dt);
|
void onUpdate(float dt) OVERRIDE;
|
||||||
void onRender();
|
void onRender() OVERRIDE;
|
||||||
|
void onPrepareRender() OVERRIDE;
|
||||||
|
|
||||||
void modifyDt(float &dt);
|
void modifyDt(float &dt);
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,7 @@ Game::Game() : StateObject()
|
||||||
noSceneTransitionFadeout = false;
|
noSceneTransitionFadeout = false;
|
||||||
fullTilesetReload = false;
|
fullTilesetReload = false;
|
||||||
highestLoadedEntityID = 0;
|
highestLoadedEntityID = 0;
|
||||||
|
waterSurfaceRender = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game()
|
Game::~Game()
|
||||||
|
@ -2032,7 +2033,7 @@ bool Game::saveScene(std::string scene)
|
||||||
saveFile.InsertEndChild(pathXml);
|
saveFile.InsertEndChild(pathXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t lr = 0; lr < MAX_TILE_LAYERS; ++lr)
|
for(unsigned lr = 0; lr < MAX_TILE_LAYERS; ++lr)
|
||||||
{
|
{
|
||||||
const TileStorage& ts = dsq->tilemgr.tilestore[lr];
|
const TileStorage& ts = dsq->tilemgr.tilestore[lr];
|
||||||
std::ostringstream simpleElements;
|
std::ostringstream simpleElements;
|
||||||
|
@ -2084,7 +2085,7 @@ bool Game::saveScene(std::string scene)
|
||||||
{
|
{
|
||||||
XMLElement *simpleElementsXML = saveFile.NewElement("SE");
|
XMLElement *simpleElementsXML = saveFile.NewElement("SE");
|
||||||
simpleElementsXML->SetAttribute("k", s.c_str());
|
simpleElementsXML->SetAttribute("k", s.c_str());
|
||||||
simpleElementsXML->SetAttribute("l", (unsigned)lr);
|
simpleElementsXML->SetAttribute("l", lr);
|
||||||
std::string str = simpleElements_repeatScale.str();
|
std::string str = simpleElements_repeatScale.str();
|
||||||
if(!str.empty())
|
if(!str.empty())
|
||||||
simpleElementsXML->SetAttribute("repeatScale", str.c_str());
|
simpleElementsXML->SetAttribute("repeatScale", str.c_str());
|
||||||
|
@ -2436,6 +2437,7 @@ void Game::applyState()
|
||||||
inHelpScreen = false;
|
inHelpScreen = false;
|
||||||
helpBG = 0;
|
helpBG = 0;
|
||||||
helpBG2 = 0;
|
helpBG2 = 0;
|
||||||
|
waterSurfaceRender = NULL;
|
||||||
|
|
||||||
dsq->returnToScene = "";
|
dsq->returnToScene = "";
|
||||||
|
|
||||||
|
@ -4788,6 +4790,7 @@ void Game::removeState()
|
||||||
gridRenderUser1 = 0;
|
gridRenderUser1 = 0;
|
||||||
gridRenderUser2 = 0;
|
gridRenderUser2 = 0;
|
||||||
worldMapRender = 0;
|
worldMapRender = 0;
|
||||||
|
waterSurfaceRender = 0;
|
||||||
|
|
||||||
clearObsRows();
|
clearObsRows();
|
||||||
|
|
||||||
|
@ -4987,3 +4990,9 @@ void Game::onContinuityReset()
|
||||||
{
|
{
|
||||||
themenu->onContinuityReset();
|
themenu->onContinuityReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Game::onPrepareRender()
|
||||||
|
{
|
||||||
|
if(waterSurfaceRender)
|
||||||
|
waterSurfaceRender->prepareRender();
|
||||||
|
}
|
||||||
|
|
|
@ -398,6 +398,7 @@ public:
|
||||||
bool isIgnoreAction(AquariaActions ac) const;
|
bool isIgnoreAction(AquariaActions ac) const;
|
||||||
|
|
||||||
void onContinuityReset();
|
void onContinuityReset();
|
||||||
|
void onPrepareRender();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned highestLoadedEntityID;
|
unsigned highestLoadedEntityID;
|
||||||
|
|
|
@ -6,30 +6,26 @@
|
||||||
#include "RenderBase.h"
|
#include "RenderBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WaterSurfaceRender::WaterSurfaceRender() : Quad()
|
WaterSurfaceRender::WaterSurfaceRender() : Quad()
|
||||||
{
|
{
|
||||||
cull = false;
|
cull = false;
|
||||||
this->texcoordOverride = true;
|
this->texcoordOverride = true;
|
||||||
|
|
||||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
if (dsq->useFrameBuffer)
|
||||||
{
|
{
|
||||||
setSegs(4, 32, 0.5f, 0.5f, -0.005f, 0, 5, 1);
|
setSegs(4, 32, 0.5f, 0.5f, -0.005f, 0, 5, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->renderBorder = false;
|
||||||
|
this->renderCenter = false;
|
||||||
|
this->borderAlpha = 1;
|
||||||
|
|
||||||
qLine = new Quad("water/water-line", Vector(0,0));
|
qLine = new Quad("water/water-line", Vector(0,0));
|
||||||
qLine->repeatTextureToFill(1);
|
qLine->repeatTextureToFill(1);
|
||||||
qLine->cull = false;
|
qLine->cull = false;
|
||||||
game->addRenderObject(qLine, LR_WATERSURFACE2);
|
game->addRenderObject(qLine, LR_WATERSURFACE2);
|
||||||
|
|
||||||
qLine2 = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
qSurface = new Quad("missingimage", Vector(0,0));
|
qSurface = new Quad("missingimage", Vector(0,0));
|
||||||
|
|
||||||
qSurface->cull = false;
|
qSurface->cull = false;
|
||||||
qSurface->repeatTextureToFill(1);
|
qSurface->repeatTextureToFill(1);
|
||||||
game->addRenderObject(qSurface, LR_WATERSURFACE2);
|
game->addRenderObject(qSurface, LR_WATERSURFACE2);
|
||||||
|
@ -38,16 +34,28 @@ WaterSurfaceRender::WaterSurfaceRender() : Quad()
|
||||||
shareAlphaWithChildren = 0;
|
shareAlphaWithChildren = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterSurfaceRender::onUpdate(float dt)
|
WaterSurfaceRender::~WaterSurfaceRender()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterSurfaceRender::onEndOfLife()
|
||||||
|
{
|
||||||
|
if(qLine)
|
||||||
|
qLine->safeKill();
|
||||||
|
if(qSurface)
|
||||||
|
qSurface->safeKill();
|
||||||
|
|
||||||
|
qLine = NULL;
|
||||||
|
qSurface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterSurfaceRender::prepareRender()
|
||||||
|
{
|
||||||
|
bool fbEffectVisible = false;
|
||||||
if (game->waterLevel.x > 0)
|
if (game->waterLevel.x > 0)
|
||||||
{
|
{
|
||||||
Quad::onUpdate(dt);
|
|
||||||
|
|
||||||
qLine->alpha = qSurface->alpha = 1;
|
qLine->alpha = qSurface->alpha = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
position.x = core->screenCenter.x;
|
position.x = core->screenCenter.x;
|
||||||
position.y = game->waterLevel.x;
|
position.y = game->waterLevel.x;
|
||||||
|
|
||||||
|
@ -88,28 +96,24 @@ void WaterSurfaceRender::onUpdate(float dt)
|
||||||
|
|
||||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
||||||
{
|
{
|
||||||
qSurface->alphaMod = 0.5;
|
qSurface->alphaMod = 0.5f;
|
||||||
|
fbEffectVisible = this->isOnScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qLine->alpha = qSurface->alpha = 0;
|
qLine->alpha = qSurface->alpha = 0;
|
||||||
|
|
||||||
if (qLine2)
|
|
||||||
{
|
|
||||||
qLine2->alpha = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
if (fbEffectVisible)
|
||||||
{
|
{
|
||||||
const float reflectSize = 97;
|
const float reflectSize = 97;
|
||||||
const float reflectPos = (game->waterLevel.x - core->cameraPos.y)
|
const float reflectPos = (game->waterLevel.x - core->cameraPos.y)
|
||||||
+ (game->waterLevel.x - core->screenCenter.y) / 3;
|
+ (game->waterLevel.x - core->screenCenter.y) / 3;
|
||||||
const float reflectOffset = -0.03f;
|
const float reflectOffset = -0.03f;
|
||||||
const float coordDiv = 768;
|
const float coordMul = 1.0f / 768;
|
||||||
const float v0 = 1 + reflectOffset - (reflectPos * core->globalScale.x) / coordDiv;
|
const float v0 = 1 + reflectOffset - (reflectPos * core->globalScale.x) * coordMul;
|
||||||
const float v1 = v0 + (reflectSize * core->globalScale.x) / coordDiv;
|
const float v1 = v0 + (reflectSize * core->globalScale.x) * coordMul;
|
||||||
|
|
||||||
texcoords.u1 = 0;
|
texcoords.u1 = 0;
|
||||||
texcoords.u2 = core->frameBuffer.getWidthP();
|
texcoords.u2 = core->frameBuffer.getWidthP();
|
||||||
|
@ -127,27 +131,73 @@ void WaterSurfaceRender::onUpdate(float dt)
|
||||||
color = Vector(0.4f, 0.7f, 0.8f);
|
color = Vector(0.4f, 0.7f, 0.8f);
|
||||||
alpha = 0.2f;
|
alpha = 0.2f;
|
||||||
}
|
}
|
||||||
|
//debugLog(fbEffectVisible ? "ws on screen" : "ws not vis");
|
||||||
|
this->fbEffectVisible = fbEffectVisible;
|
||||||
|
this->renderBorder = RenderObject::renderCollisionShape;
|
||||||
|
if(this->renderBorder)
|
||||||
|
{
|
||||||
|
this->renderBorderColor = fbEffectVisible ? Vector(1,0,1) : Vector(0,0.5f,1);
|
||||||
|
}
|
||||||
|
|
||||||
grid->setTexCoords(texcoords);
|
grid->setTexCoords(texcoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void quadBlit(const RenderState& rs, unsigned tex)
|
||||||
|
{
|
||||||
|
rs.gpu.setBlend(BLEND_DISABLED);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
|
glColor4f(1,1,1,1);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glScalef(core->globalResolutionScale.x, core->globalResolutionScale.y, core->globalResolutionScale.z);
|
||||||
|
|
||||||
|
int vw = core->getVirtualWidth();
|
||||||
|
int vh = core->getVirtualHeight();
|
||||||
|
int offx = -core->getVirtualOffX();
|
||||||
|
int offy = -core->getVirtualOffY();
|
||||||
|
|
||||||
|
// verts are in 0..1, transform so that we cover the entire screen
|
||||||
|
glTranslatef(offx, offy, 0);
|
||||||
|
glScalef(vw, vh, 1);
|
||||||
|
|
||||||
|
core->blitQuad.render(rs);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
void WaterSurfaceRender::render(const RenderState& rs) const
|
void WaterSurfaceRender::render(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
if (game->waterLevel.x > 0)
|
if (game->waterLevel.x > 0)
|
||||||
|
{
|
||||||
|
if (fbEffectVisible)
|
||||||
|
{
|
||||||
|
// Everything up until now was rendered to the first page; flip it
|
||||||
|
const unsigned curpage = core->frameBuffer.getCurrentPage();
|
||||||
|
const unsigned oldtex = core->frameBuffer.getTextureID(curpage);
|
||||||
|
const unsigned newtex = core->frameBuffer.getTextureID(curpage + 1);
|
||||||
|
|
||||||
|
core->frameBuffer.replaceCapture(curpage + 1);
|
||||||
|
|
||||||
|
if(glCopyImageSubDataEXT)
|
||||||
|
glCopyImageSubDataEXT(
|
||||||
|
oldtex, GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||||
|
newtex, GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||||
|
core->width, core->height, 1
|
||||||
|
);
|
||||||
|
else
|
||||||
|
quadBlit(rs, oldtex);
|
||||||
|
}
|
||||||
|
|
||||||
Quad::render(rs);
|
Quad::render(rs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterSurfaceRender::onRender(const RenderState& rs) const
|
void WaterSurfaceRender::onRender(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
if (game->waterLevel == 0) return;
|
if (!fbEffectVisible || game->waterLevel == 0) return;
|
||||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
|
||||||
{
|
|
||||||
dsq->frameBuffer.bindTexture();
|
core->frameBuffer.bindTexture(core->frameBuffer.getCurrentPage() - 1);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quad::onRender(rs);
|
Quad::onRender(rs);
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,14 @@ class WaterSurfaceRender : public Quad
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WaterSurfaceRender();
|
WaterSurfaceRender();
|
||||||
|
virtual ~WaterSurfaceRender();
|
||||||
void render(const RenderState& rs) const OVERRIDE;
|
void render(const RenderState& rs) const OVERRIDE;
|
||||||
|
void prepareRender();
|
||||||
protected:
|
protected:
|
||||||
Quad *qSurface, *qLine, *qLine2;
|
virtual void onEndOfLife() OVERRIDE;
|
||||||
|
Quad *qSurface, *qLine;
|
||||||
void onRender(const RenderState& rs) const OVERRIDE;
|
void onRender(const RenderState& rs) const OVERRIDE;
|
||||||
void onUpdate(float dt) OVERRIDE;
|
bool fbEffectVisible;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,6 +72,19 @@ void AfterEffectManager::deleteEffects()
|
||||||
openSpots.clear();
|
openSpots.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AfterEffectManager::beginCapture()
|
||||||
|
{
|
||||||
|
assert(core->frameBuffer.isInited());
|
||||||
|
core->frameBuffer.pushCapture(0);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AfterEffectManager::endCapture()
|
||||||
|
{
|
||||||
|
core->frameBuffer.popCapture();
|
||||||
|
}
|
||||||
|
|
||||||
void AfterEffectManager::deleteShaders()
|
void AfterEffectManager::deleteShaders()
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < shaderPipeline.size(); ++i)
|
for(size_t i = 0; i < shaderPipeline.size(); ++i)
|
||||||
|
@ -146,7 +159,7 @@ void AfterEffectManager::destroyEffect(int id)
|
||||||
openSpots.push_back(id);
|
openSpots.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfterEffectManager::render(const RenderState& rs) const
|
void AfterEffectManager::render(const RenderState& rs, unsigned fboPageWithImage) const
|
||||||
{
|
{
|
||||||
assert(core->frameBuffer.isInited());
|
assert(core->frameBuffer.isInited());
|
||||||
|
|
||||||
|
@ -154,48 +167,53 @@ void AfterEffectManager::render(const RenderState& rs) const
|
||||||
|
|
||||||
rs.gpu.setBlend(BLEND_DISABLED);
|
rs.gpu.setBlend(BLEND_DISABLED);
|
||||||
|
|
||||||
core->frameBuffer.endCapture();
|
|
||||||
glTranslatef(core->cameraPos.x, core->cameraPos.y, 0);
|
glTranslatef(core->cameraPos.x, core->cameraPos.y, 0);
|
||||||
glScalef(core->invGlobalScale, core->invGlobalScale,0);
|
glScalef(core->invGlobalScale, core->invGlobalScale,0);
|
||||||
|
|
||||||
glColor4f(1,1,1,1);
|
glColor4f(1,1,1,1);
|
||||||
renderGrid(rs);
|
renderGrid(rs, fboPageWithImage);
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfterEffectManager::renderGrid(const RenderState& rs) const
|
void AfterEffectManager::renderGrid(const RenderState& rs, unsigned fbPage) const
|
||||||
{
|
{
|
||||||
int firstShader = -1;
|
size_t firstShader, lastShader;
|
||||||
int lastShader = -1;
|
Shader *activeShader = NULL;
|
||||||
Shader *activeShader = 0;
|
|
||||||
for (size_t i = 0; i < shaderPipeline.size(); ++i)
|
for (size_t i = 0; i < shaderPipeline.size(); ++i)
|
||||||
{
|
{
|
||||||
if(shaderPipeline[i] && shaderPipeline[i]->isLoaded())
|
if(shaderPipeline[i] && shaderPipeline[i]->isLoaded())
|
||||||
{
|
{
|
||||||
if(firstShader < 0)
|
if(!activeShader)
|
||||||
{
|
{
|
||||||
firstShader = int(i);
|
firstShader = i;
|
||||||
activeShader = shaderPipeline[i];
|
activeShader = shaderPipeline[i];
|
||||||
}
|
}
|
||||||
lastShader = int(i);
|
lastShader = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable blending so we don't need to clear the framebuffers
|
||||||
|
rs.gpu.setBlend(BLEND_DISABLED);
|
||||||
|
|
||||||
int vw = core->getVirtualWidth();
|
int vw = core->getVirtualWidth();
|
||||||
int vh = core->getVirtualHeight();
|
int vh = core->getVirtualHeight();
|
||||||
int offx = -core->getVirtualOffX();
|
int offx = -core->getVirtualOffX();
|
||||||
int offy = -core->getVirtualOffY();
|
int offy = -core->getVirtualOffY();
|
||||||
|
|
||||||
core->frameBuffer.bindTexture();
|
const FrameBuffer * const fb = &core->frameBuffer;
|
||||||
|
|
||||||
|
// STARTING POINT: game image was just rendered into fb(0), use that as starting point
|
||||||
|
fb->bindTexture(fbPage);
|
||||||
|
|
||||||
if(activeShader)
|
if(activeShader)
|
||||||
{
|
{
|
||||||
activeShader->bind();
|
|
||||||
activeShader->setInt("tex", 0);
|
activeShader->setInt("tex", 0);
|
||||||
|
activeShader->bind();
|
||||||
|
|
||||||
|
// Unless this is the last pass, render to fb(1)
|
||||||
if(firstShader != lastShader)
|
if(firstShader != lastShader)
|
||||||
backupBuffer.startCapture();
|
fb->pushCapture(1 - fbPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// verts are in 0..1, transform so that we cover the entire screen
|
// verts are in 0..1, transform so that we cover the entire screen
|
||||||
|
@ -208,41 +226,46 @@ void AfterEffectManager::renderGrid(const RenderState& rs) const
|
||||||
//renderGridPoints(rs);
|
//renderGridPoints(rs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
blitQuad.render(rs);
|
core->blitQuad.render(rs);
|
||||||
|
|
||||||
if (activeShader)
|
if (activeShader)
|
||||||
|
{
|
||||||
activeShader->unbind();
|
activeShader->unbind();
|
||||||
|
|
||||||
if(firstShader != lastShader)
|
if(firstShader != lastShader)
|
||||||
{
|
{
|
||||||
// From here on: secondary shader passes.
|
// From here on: secondary shader passes.
|
||||||
// We just outputted to the backup buffer...
|
// We just outputted to the backup buffer...
|
||||||
const FrameBuffer *fbIn = &core->frameBuffer;
|
|
||||||
const FrameBuffer *fbOut = &backupBuffer;
|
|
||||||
|
|
||||||
for(int i = firstShader + 1; i <= lastShader; ++i)
|
unsigned pageOut = 1 - fbPage;
|
||||||
|
|
||||||
|
for(size_t i = firstShader + 1; i <= lastShader; ++i)
|
||||||
{
|
{
|
||||||
|
unsigned pageIn = 1 - pageOut;
|
||||||
activeShader = shaderPipeline[i];
|
activeShader = shaderPipeline[i];
|
||||||
if(!(activeShader && activeShader->isLoaded()))
|
if(!(activeShader && activeShader->isLoaded()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Swap and exchange framebuffers. The old output buffer serves as texture input for the other one
|
// Swap and exchange framebuffers. The old output buffer serves as texture input for the other one
|
||||||
fbOut->endCapture();
|
pageOut = pageIn;
|
||||||
std::swap(fbIn, fbOut);
|
|
||||||
fbIn->bindTexture();
|
|
||||||
|
|
||||||
// If this is the last pass, do not render to a frame buffer again
|
// If this is the last pass, do not render to a frame buffer again
|
||||||
if(i != lastShader)
|
if(i == lastShader)
|
||||||
fbOut->startCapture();
|
fb->popCapture();
|
||||||
|
else
|
||||||
|
fb->replaceCapture(pageOut);
|
||||||
|
|
||||||
|
fb->bindTexture(pageIn);
|
||||||
|
|
||||||
activeShader->bind();
|
activeShader->bind();
|
||||||
activeShader->setInt("tex", 0);
|
activeShader->setInt("tex", 0);
|
||||||
|
|
||||||
blitQuad.render(rs);
|
core->blitQuad.render(rs);
|
||||||
|
|
||||||
activeShader->unbind();
|
activeShader->unbind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenderObject::lastTextureApplied = 0;
|
RenderObject::lastTextureApplied = 0;
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
@ -255,9 +278,7 @@ void AfterEffectManager::renderGridPoints(const RenderState& rs) const
|
||||||
|
|
||||||
void AfterEffectManager::unloadDevice()
|
void AfterEffectManager::unloadDevice()
|
||||||
{
|
{
|
||||||
backupBuffer.unloadDevice();
|
|
||||||
grid.dropBuffers();
|
grid.dropBuffers();
|
||||||
blitQuad.dropBuffers();
|
|
||||||
unloadShaders();
|
unloadShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,30 +287,12 @@ void AfterEffectManager::_updateScreenSize()
|
||||||
screenWidth = core->getWindowWidth();
|
screenWidth = core->getWindowWidth();
|
||||||
screenHeight = core->getWindowHeight();
|
screenHeight = core->getWindowHeight();
|
||||||
|
|
||||||
if (core->frameBuffer.isInited())
|
grid.setTexCoords(core->blitQuad.getTexCoords());
|
||||||
{
|
|
||||||
textureWidth = core->frameBuffer.getTexWidth();
|
|
||||||
textureHeight = core->frameBuffer.getTexHeight();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
textureWidth = screenWidth;
|
|
||||||
sizePowerOf2Texture(textureWidth);
|
|
||||||
textureHeight = screenHeight;
|
|
||||||
sizePowerOf2Texture(textureHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float percentX = (float)screenWidth/(float)textureWidth;
|
|
||||||
const float percentY = (float)screenHeight/(float)textureHeight;
|
|
||||||
TexCoordBox tc = { 0, percentY, percentX, 0 }; // Y is upside down
|
|
||||||
grid.setTexCoords(tc);
|
|
||||||
blitQuad.setTexCoords(tc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfterEffectManager::updateDevice()
|
void AfterEffectManager::updateDevice()
|
||||||
{
|
{
|
||||||
_updateScreenSize();
|
_updateScreenSize();
|
||||||
backupBuffer.init(-1, -1, true);
|
|
||||||
_initGrid();
|
_initGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +300,6 @@ void AfterEffectManager::reloadDevice()
|
||||||
{
|
{
|
||||||
_updateScreenSize();
|
_updateScreenSize();
|
||||||
|
|
||||||
backupBuffer.reloadDevice();
|
|
||||||
_initGrid();
|
_initGrid();
|
||||||
|
|
||||||
for (size_t i = 0; i < loadedShaders.size(); ++i)
|
for (size_t i = 0; i < loadedShaders.size(); ++i)
|
||||||
|
@ -442,10 +444,6 @@ void AfterEffectManager::_initGrid()
|
||||||
grid.init(xDivs, yDivs);
|
grid.init(xDivs, yDivs);
|
||||||
else
|
else
|
||||||
grid.dropBuffers();
|
grid.dropBuffers();
|
||||||
|
|
||||||
blitQuad.init(2, 2);
|
|
||||||
blitQuad.reset01();
|
|
||||||
blitQuad.updateVBO(); // never changed afterwards
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfterEffectManager::deleteShader(int handle)
|
void AfterEffectManager::deleteShader(int handle)
|
||||||
|
|
|
@ -78,10 +78,13 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
void deleteEffects();
|
void deleteEffects();
|
||||||
|
|
||||||
|
void beginCapture();
|
||||||
|
void endCapture();
|
||||||
|
|
||||||
void resetGrid();
|
void resetGrid();
|
||||||
|
|
||||||
void render(const RenderState& rs) const;
|
void render(const RenderState& rs, unsigned fboPageWithImage) const;
|
||||||
void renderGrid(const RenderState& rs) const;
|
void renderGrid(const RenderState& rs, unsigned fbPage) const;
|
||||||
void renderGridPoints(const RenderState& rs) const;
|
void renderGridPoints(const RenderState& rs) const;
|
||||||
|
|
||||||
void loadShaders();
|
void loadShaders();
|
||||||
|
@ -105,17 +108,15 @@ protected:
|
||||||
int _insertShader(Shader *sh);
|
int _insertShader(Shader *sh);
|
||||||
void _initGrid();
|
void _initGrid();
|
||||||
|
|
||||||
RenderGrid grid, blitQuad;
|
RenderGrid grid;
|
||||||
bool active;
|
bool active;
|
||||||
int numEffects;
|
int numEffects;
|
||||||
int xDivs, yDivs;
|
int xDivs, yDivs;
|
||||||
int screenWidth, screenHeight;
|
int screenWidth, screenHeight;
|
||||||
int textureWidth, textureHeight;
|
|
||||||
std::vector<Effect*> effects;
|
std::vector<Effect*> effects;
|
||||||
std::vector<int> openSpots;
|
std::vector<int> openSpots;
|
||||||
std::vector<Shader*> shaderPipeline; // Shaders are applied in this order. Can contain the same pointer more than once.
|
std::vector<Shader*> shaderPipeline; // Shaders are applied in this order. Can contain the same pointer more than once.
|
||||||
std::vector<Shader*> loadedShaders;
|
std::vector<Shader*> loadedShaders;
|
||||||
FrameBuffer backupBuffer;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
117
BBGE/Core.cpp
117
BBGE/Core.cpp
|
@ -151,7 +151,7 @@ void Core::setup_opengl()
|
||||||
|
|
||||||
setClearColor(clearColor);
|
setClearColor(clearColor);
|
||||||
|
|
||||||
frameBuffer.init(-1, -1, true);
|
frameBuffer.init(-1, -1, 2);
|
||||||
if(afterEffectManager)
|
if(afterEffectManager)
|
||||||
afterEffectManager->updateDevice();
|
afterEffectManager->updateDevice();
|
||||||
|
|
||||||
|
@ -160,6 +160,32 @@ void Core::setup_opengl()
|
||||||
defaultQuadGrid.init(2, 2, defaultTC);
|
defaultQuadGrid.init(2, 2, defaultTC);
|
||||||
|
|
||||||
defautQuadBorder.initQuadVertices(defaultTC, GPUACCESS_DEFAULT);
|
defautQuadBorder.initQuadVertices(defaultTC, GPUACCESS_DEFAULT);
|
||||||
|
|
||||||
|
int screenWidth = getWindowWidth();
|
||||||
|
int screenHeight = core->getWindowHeight();
|
||||||
|
int textureWidth, textureHeight;
|
||||||
|
|
||||||
|
if (core->frameBuffer.isInited())
|
||||||
|
{
|
||||||
|
textureWidth = core->frameBuffer.getTexWidth();
|
||||||
|
textureHeight = core->frameBuffer.getTexHeight();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textureWidth = screenWidth;
|
||||||
|
sizePowerOf2Texture(textureWidth);
|
||||||
|
textureHeight = screenHeight;
|
||||||
|
sizePowerOf2Texture(textureHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float percentX = (float)screenWidth/(float)textureWidth;
|
||||||
|
const float percentY = (float)screenHeight/(float)textureHeight;
|
||||||
|
TexCoordBox tc = { 0, percentY, percentX, 0 }; // Y is upside down
|
||||||
|
blitQuad.setTexCoords(tc);
|
||||||
|
blitQuad.init(2, 2);
|
||||||
|
blitQuad.reset01();
|
||||||
|
blitQuad.updateVBO(); // never changed afterwards
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::resizeWindow(int w, int h, int full, int bpp, int vsync, int display, int hz)
|
void Core::resizeWindow(int w, int h, int full, int bpp, int vsync, int display, int hz)
|
||||||
|
@ -378,7 +404,6 @@ Core::Core(const std::string &filesystem, const std::string& extraDataDir, int n
|
||||||
baseCullRadius = 1;
|
baseCullRadius = 1;
|
||||||
width = height = 0;
|
width = height = 0;
|
||||||
_lastEnumeratedDisplayIndex = -1;
|
_lastEnumeratedDisplayIndex = -1;
|
||||||
afterEffectManagerLayer = 0;
|
|
||||||
renderObjectLayers.resize(1);
|
renderObjectLayers.resize(1);
|
||||||
invGlobalScale = 1.0;
|
invGlobalScale = 1.0;
|
||||||
invGlobalScaleSqr = 1.0;
|
invGlobalScaleSqr = 1.0;
|
||||||
|
@ -740,7 +765,9 @@ void Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsyn
|
||||||
enumerateScreenModes(window->getDisplayIndex());
|
enumerateScreenModes(window->getDisplayIndex());
|
||||||
|
|
||||||
window->updateSize();
|
window->updateSize();
|
||||||
cacheRender(); // Clears the window bg to black early; prevents flickering
|
glClearColor(0,0,0,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
showBuffer();
|
||||||
lib_graphics = true;
|
lib_graphics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,14 +1209,13 @@ void Core::run(float runTime)
|
||||||
|
|
||||||
if (settings.renderOn)
|
if (settings.renderOn)
|
||||||
{
|
{
|
||||||
if (darkLayer.isUsed())
|
if(!minimized)
|
||||||
{
|
{
|
||||||
darkLayer.preRender();
|
prepareRender();
|
||||||
}
|
renderInternal(-1, -1, true);
|
||||||
|
|
||||||
render();
|
|
||||||
|
|
||||||
showBuffer();
|
showBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
if (nestedMains == 1)
|
if (nestedMains == 1)
|
||||||
clearGarbage();
|
clearGarbage();
|
||||||
|
@ -1221,11 +1247,6 @@ void Core::run(float runTime)
|
||||||
nestedMains--;
|
nestedMains--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::clearBuffers()
|
|
||||||
{
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::setupRenderPositionAndScale()
|
void Core::setupRenderPositionAndScale()
|
||||||
{
|
{
|
||||||
glScalef(globalScale.x*globalResolutionScale.x, globalScale.y*globalResolutionScale.y, globalScale.z*globalResolutionScale.z);
|
glScalef(globalScale.x*globalResolutionScale.x, globalScale.y*globalResolutionScale.y, globalScale.z*globalResolutionScale.z);
|
||||||
|
@ -1766,7 +1787,7 @@ void Core::print(int x, int y, const char *str, float sz)
|
||||||
|
|
||||||
void Core::cacheRender()
|
void Core::cacheRender()
|
||||||
{
|
{
|
||||||
render();
|
renderExternal();
|
||||||
// what if the screen was full white? then you wouldn't want to clear buffers
|
// what if the screen was full white? then you wouldn't want to clear buffers
|
||||||
//clearBuffers();
|
//clearBuffers();
|
||||||
showBuffer();
|
showBuffer();
|
||||||
|
@ -1780,7 +1801,13 @@ void Core::updateCullData()
|
||||||
screenCenter = cullCenter = cameraPos + Vector(400.0f*invGlobalScale,300.0f*invGlobalScale);
|
screenCenter = cullCenter = cameraPos + Vector(400.0f*invGlobalScale,300.0f*invGlobalScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail)
|
void Core::renderExternal()
|
||||||
|
{
|
||||||
|
prepareRender();
|
||||||
|
renderInternal(-1, -1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::prepareRender()
|
||||||
{
|
{
|
||||||
renderObjectCount = 0;
|
renderObjectCount = 0;
|
||||||
processedRenderObjectCount = 0;
|
processedRenderObjectCount = 0;
|
||||||
|
@ -1788,13 +1815,10 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail)
|
||||||
|
|
||||||
globalScaleChanged();
|
globalScaleChanged();
|
||||||
|
|
||||||
if (minimized) return;
|
|
||||||
onRender();
|
|
||||||
|
|
||||||
RenderObject::lastTextureApplied = 0;
|
|
||||||
|
|
||||||
updateCullData();
|
updateCullData();
|
||||||
|
|
||||||
|
onPrepareRender();
|
||||||
|
|
||||||
// TODO: this could be done in parallel
|
// TODO: this could be done in parallel
|
||||||
for (size_t i = 0; i < renderObjectLayers.size(); ++i)
|
for (size_t i = 0; i < renderObjectLayers.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -1802,50 +1826,54 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail)
|
||||||
renderObjectLayers[i].prepareRender();
|
renderObjectLayers[i].prepareRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (darkLayer.isUsed())
|
||||||
|
{
|
||||||
|
darkLayer.preRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glViewport(0, 0, core->width, core->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make sure to call prepareRender() before calling this!
|
||||||
|
void Core::renderInternal(int startLayer, int endLayer, bool allowSkip)
|
||||||
|
{
|
||||||
|
onRender();
|
||||||
|
|
||||||
|
RenderObject::lastTextureApplied = 0;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glLoadIdentity(); // Reset The View
|
glLoadIdentity(); // Reset The View
|
||||||
clearBuffers();
|
|
||||||
|
|
||||||
if (afterEffectManager && frameBuffer.isInited() && useFrameBufferIfAvail)
|
|
||||||
{
|
|
||||||
frameBuffer.startCapture();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupRenderPositionAndScale();
|
setupRenderPositionAndScale();
|
||||||
|
|
||||||
CombinedRenderAndGPUState rs;
|
CombinedRenderAndGPUState rs;
|
||||||
|
|
||||||
|
|
||||||
for (size_t c = 0; c < renderObjectLayerOrder.size(); c++)
|
for (size_t c = 0; c < renderObjectLayerOrder.size(); c++)
|
||||||
{
|
{
|
||||||
int i = renderObjectLayerOrder[c];
|
int i = renderObjectLayerOrder[c];
|
||||||
if (i == -1) continue;
|
if (i == -1) continue;
|
||||||
if ((startLayer != -1 && endLayer != -1) && (i < startLayer || i > endLayer)) continue;
|
if ((startLayer != -1 && endLayer != -1) && (i < startLayer || i > endLayer)) continue;
|
||||||
|
|
||||||
if (darkLayer.isUsed() )
|
// don't render the layers that the dark layer takes as input
|
||||||
{
|
if(allowSkip && !darkLayer.shouldRenderLayer(i))
|
||||||
|
|
||||||
if (i == darkLayer.getRenderLayer())
|
|
||||||
{
|
|
||||||
darkLayer.render(rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == darkLayer.getLayer() && startLayer != i)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (afterEffectManager /*&& afterEffectManager->active*/ && i == afterEffectManagerLayer)
|
|
||||||
{
|
|
||||||
afterEffectManager->render(rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderObjectLayer *r = &renderObjectLayers[i];
|
RenderObjectLayer *r = &renderObjectLayers[i];
|
||||||
if(!r->visible)
|
if(!r->visible)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(r->preRender)
|
||||||
|
if(!r->preRender(rs))
|
||||||
|
continue;
|
||||||
|
|
||||||
r->render(rs);
|
r->render(rs);
|
||||||
|
|
||||||
|
if(r->postRender)
|
||||||
|
r->postRender(rs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1949,6 +1977,7 @@ void Core::shutdown()
|
||||||
|
|
||||||
defaultQuadGrid.dropBuffers();
|
defaultQuadGrid.dropBuffers();
|
||||||
defautQuadBorder.dropBuffer();
|
defautQuadBorder.dropBuffer();
|
||||||
|
blitQuad.dropBuffers();
|
||||||
|
|
||||||
debugLog("Shutdown Graphics Library...");
|
debugLog("Shutdown Graphics Library...");
|
||||||
shutdownGraphicsLibrary();
|
shutdownGraphicsLibrary();
|
||||||
|
|
15
BBGE/Core.h
15
BBGE/Core.h
|
@ -113,6 +113,9 @@ enum FollowCameraLock
|
||||||
|
|
||||||
typedef std::vector <RenderObject*> RenderObjects;
|
typedef std::vector <RenderObject*> RenderObjects;
|
||||||
|
|
||||||
|
typedef bool (*PreRenderFunc)(const RenderState& rs);
|
||||||
|
typedef void (*PostRenderFunc)(const RenderState& rs);
|
||||||
|
|
||||||
class RenderObjectLayer
|
class RenderObjectLayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -170,6 +173,9 @@ public:
|
||||||
|
|
||||||
bool update;
|
bool update;
|
||||||
|
|
||||||
|
PreRenderFunc preRender;
|
||||||
|
PostRenderFunc postRender;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RenderObjects renderObjects;
|
RenderObjects renderObjects;
|
||||||
std::vector<const RenderObject*> toRender;
|
std::vector<const RenderObject*> toRender;
|
||||||
|
@ -206,8 +212,9 @@ public:
|
||||||
|
|
||||||
void applyState(const std::string &state);
|
void applyState(const std::string &state);
|
||||||
|
|
||||||
void clearBuffers();
|
void renderExternal();
|
||||||
void render(int startLayer=-1, int endLayer=-1, bool useFrameBufferIfAvail=true);
|
void prepareRender();
|
||||||
|
void renderInternal(int startLayer, int endLayer, bool allowSkip);
|
||||||
void showBuffer();
|
void showBuffer();
|
||||||
void quit();
|
void quit();
|
||||||
bool isShuttingDown();
|
bool isShuttingDown();
|
||||||
|
@ -465,7 +472,6 @@ protected:
|
||||||
virtual void onJoystickAdded(int deviceID);
|
virtual void onJoystickAdded(int deviceID);
|
||||||
virtual void onJoystickRemoved(int instanceID);
|
virtual void onJoystickRemoved(int instanceID);
|
||||||
|
|
||||||
int afterEffectManagerLayer;
|
|
||||||
Vector cameraOffset;
|
Vector cameraOffset;
|
||||||
std::vector<float> avgFPS;
|
std::vector<float> avgFPS;
|
||||||
virtual void modifyDt(float &dt){}
|
virtual void modifyDt(float &dt){}
|
||||||
|
@ -486,6 +492,7 @@ protected:
|
||||||
|
|
||||||
virtual void onUpdate(float dt);
|
virtual void onUpdate(float dt);
|
||||||
virtual void onRender(){}
|
virtual void onRender(){}
|
||||||
|
virtual void onPrepareRender(){}
|
||||||
|
|
||||||
void setupFileAccess();
|
void setupFileAccess();
|
||||||
std::string _extraDataDir;
|
std::string _extraDataDir;
|
||||||
|
@ -498,6 +505,8 @@ protected:
|
||||||
DynamicGPUBuffer defautQuadBorder;
|
DynamicGPUBuffer defautQuadBorder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
RenderGrid blitQuad;
|
||||||
|
|
||||||
// inclusive!
|
// inclusive!
|
||||||
inline int getMaxActionStatusIndex() const { return int(actionStatus.size()) - 2; }
|
inline int getMaxActionStatusIndex() const { return int(actionStatus.size()) - 2; }
|
||||||
// pass -1 for is a sentinel that captures all input
|
// pass -1 for is a sentinel that captures all input
|
||||||
|
|
|
@ -26,12 +26,11 @@ DarkLayer::DarkLayer()
|
||||||
{
|
{
|
||||||
quality = 0;
|
quality = 0;
|
||||||
active = false;
|
active = false;
|
||||||
layer = -1;
|
|
||||||
renderLayer = -1;
|
|
||||||
texture = 0;
|
texture = 0;
|
||||||
|
useFrameBuffer = false;
|
||||||
format = GL_RGB; //FIXED?: used to be GL_LUMINANCE, that might have been causing problems
|
layer = -1;
|
||||||
useFrameBuffer = true; //BUG?: will do this even if frame buffer is off in usersettings...
|
beginLayer = -1;
|
||||||
|
lastLayer = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DarkLayer::unloadDevice()
|
void DarkLayer::unloadDevice()
|
||||||
|
@ -53,23 +52,16 @@ void DarkLayer::reloadDevice()
|
||||||
texture = generateEmptyTexture(quality);
|
texture = generateEmptyTexture(quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DarkLayer::getRenderLayer()
|
bool DarkLayer::isUsed() const
|
||||||
{
|
{
|
||||||
return renderLayer;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DarkLayer::isUsed()
|
bool DarkLayer::shouldRenderLayer(int lr) const
|
||||||
{
|
{
|
||||||
//HACK: disabling dark layer for temporary testing build
|
if(!active)
|
||||||
// MAKE SURE TO RESTORE THIS CODE TO THE WAY IT WAS
|
return true;
|
||||||
return layer > -1 && active;
|
return useFrameBuffer || (lr < beginLayer || lr > lastLayer);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DarkLayer::setLayers(int layer, int rl)
|
|
||||||
{
|
|
||||||
this->layer = layer;
|
|
||||||
this->renderLayer = rl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DarkLayer::init(int quality, bool useFrameBufferParam)
|
void DarkLayer::init(int quality, bool useFrameBufferParam)
|
||||||
|
@ -80,7 +72,7 @@ void DarkLayer::init(int quality, bool useFrameBufferParam)
|
||||||
|
|
||||||
if (useFrameBuffer)
|
if (useFrameBuffer)
|
||||||
{
|
{
|
||||||
if (!frameBuffer.init(quality, quality))
|
if (!frameBuffer.init(quality, quality, 1))
|
||||||
useFrameBuffer = false;
|
useFrameBuffer = false;
|
||||||
else
|
else
|
||||||
debugLog("Dark Layer: using framebuffer");
|
debugLog("Dark Layer: using framebuffer");
|
||||||
|
@ -92,11 +84,6 @@ void DarkLayer::init(int quality, bool useFrameBufferParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DarkLayer::getLayer()
|
|
||||||
{
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DarkLayer::toggle(bool on)
|
void DarkLayer::toggle(bool on)
|
||||||
{
|
{
|
||||||
this->active = on;
|
this->active = on;
|
||||||
|
@ -104,44 +91,46 @@ void DarkLayer::toggle(bool on)
|
||||||
|
|
||||||
void DarkLayer::preRender()
|
void DarkLayer::preRender()
|
||||||
{
|
{
|
||||||
if (layer != -1)
|
if(!useFrameBuffer)
|
||||||
{
|
{
|
||||||
glViewport(0,0,quality,quality);
|
glViewport(0, 0, quality, quality);
|
||||||
|
|
||||||
if (useFrameBuffer)
|
|
||||||
frameBuffer.startCapture();
|
|
||||||
|
|
||||||
glClearColor(1,1,1,0);
|
glClearColor(1,1,1,0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
core->renderInternal(beginLayer, lastLayer, false);
|
||||||
core->render(layer, layer, false);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glReadBuffer(GL_BACK);
|
||||||
if (useFrameBuffer)
|
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, quality, quality, 0);
|
||||||
frameBuffer.endCapture();
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D,texture); // Bind To The Blur Texture
|
|
||||||
// Copy Our ViewPort To The Blur Texture (From 0,0 To q,q... No Border)
|
|
||||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, quality, quality, 0);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glViewport(0, 0, core->width, core->height);
|
void DarkLayer::beginCapture()
|
||||||
glClearColor(0,0,0,0);
|
{
|
||||||
|
if(useFrameBuffer)
|
||||||
|
{
|
||||||
|
frameBuffer.pushCapture(0);
|
||||||
|
glClearColor(1,1,1,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DarkLayer::endCapture()
|
||||||
|
{
|
||||||
|
if(useFrameBuffer)
|
||||||
|
{
|
||||||
|
frameBuffer.popCapture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DarkLayer::render(const RenderState& rs) const
|
void DarkLayer::render(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
if (renderLayer != -1)
|
|
||||||
{
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
if (useFrameBuffer)
|
if (useFrameBuffer)
|
||||||
frameBuffer.bindTexture();
|
frameBuffer.bindTexture(0);
|
||||||
else
|
else
|
||||||
glBindTexture(GL_TEXTURE_2D,texture);
|
glBindTexture(GL_TEXTURE_2D,texture);
|
||||||
|
|
||||||
|
@ -175,6 +164,4 @@ void DarkLayer::render(const RenderState& rs) const
|
||||||
|
|
||||||
RenderObject::lastTextureApplied = 0;
|
RenderObject::lastTextureApplied = 0;
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,24 +32,28 @@ public:
|
||||||
DarkLayer();
|
DarkLayer();
|
||||||
void init(int quality, bool useFrameBuffer=true);
|
void init(int quality, bool useFrameBuffer=true);
|
||||||
void toggle(bool on);
|
void toggle(bool on);
|
||||||
void setLayers(int layer, int renderLayer);
|
void setSrcLayer(int layer);
|
||||||
void preRender();
|
void preRender(); // call before rendering anything else. this is for render-to-texture mode
|
||||||
|
void beginCapture(); // call this + endCapture() when rendering the layer where dark layer objects are located
|
||||||
|
void endCapture();
|
||||||
|
|
||||||
void render(const RenderState& rs) const;
|
void render(const RenderState& rs) const;
|
||||||
int getLayer();
|
bool isUsed() const;
|
||||||
int getRenderLayer();
|
bool shouldRenderLayer(int lr) const;
|
||||||
bool isUsed();
|
|
||||||
|
|
||||||
void unloadDevice();
|
void unloadDevice();
|
||||||
void reloadDevice();
|
void reloadDevice();
|
||||||
|
|
||||||
|
int beginLayer;
|
||||||
|
int lastLayer; // inclusive
|
||||||
|
|
||||||
|
protected:
|
||||||
bool useFrameBuffer;
|
bool useFrameBuffer;
|
||||||
FrameBuffer frameBuffer;
|
FrameBuffer frameBuffer;
|
||||||
protected:
|
|
||||||
int quality;
|
int quality;
|
||||||
|
int layer;
|
||||||
bool active;
|
bool active;
|
||||||
int layer, renderLayer;
|
|
||||||
unsigned texture;
|
unsigned texture;
|
||||||
unsigned format;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,15 +24,47 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
//WARNING: FrameBuffer objects have to have reloadDevice/unloadDevice called manually!
|
//WARNING: FrameBuffer objects have to have reloadDevice/unloadDevice called manually!
|
||||||
|
|
||||||
|
|
||||||
|
struct FBOStack
|
||||||
|
{
|
||||||
|
const FrameBuffer *fbo;
|
||||||
|
unsigned page;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FBOStack s_fbostack[4]; // first entry is always unused
|
||||||
|
static size_t s_stackpos = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static bool isOnTop(const FrameBuffer *fbo)
|
||||||
|
{
|
||||||
|
return s_fbostack[s_stackpos].fbo == fbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInStack(const FrameBuffer *fbo, unsigned page)
|
||||||
|
{
|
||||||
|
for(size_t i = 1; i <= s_stackpos; ++i) // first entry is always NULL
|
||||||
|
if(s_fbostack[i].fbo == fbo && s_fbostack[i].page == page)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FrameBuffer::FrameBuffer()
|
FrameBuffer::FrameBuffer()
|
||||||
{
|
{
|
||||||
inited = false;
|
inited = false;
|
||||||
texw = 0;
|
texw = 0;
|
||||||
texh = 0;
|
texh = 0;
|
||||||
g_frameBuffer = 0;
|
viewportW = 0;
|
||||||
g_depthRenderBuffer = 0;
|
viewportH = 0;
|
||||||
g_dynamicTextureID = 0;
|
_curpage = 0;
|
||||||
_w = _h = 0;
|
_w = _h = 0;
|
||||||
|
_numpages = 0;
|
||||||
|
_numfbos = 0;
|
||||||
|
for(size_t i = 0; i < Countof(_texs); ++i)
|
||||||
|
{
|
||||||
|
_fbos[i] = 0;
|
||||||
|
_texs[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameBuffer::~FrameBuffer()
|
FrameBuffer::~FrameBuffer()
|
||||||
|
@ -50,10 +82,18 @@ float FrameBuffer::getHeightP() const
|
||||||
return (float)core->getWindowHeight()/(float)texh;
|
return (float)core->getWindowHeight()/(float)texh;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
bool FrameBuffer::getCurrentPage() const
|
||||||
{
|
{
|
||||||
|
assert(_curpage);
|
||||||
|
return _curpage - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrameBuffer::init(int width, int height, unsigned pages)
|
||||||
|
{
|
||||||
|
assert(pages && pages < Countof(_texs));
|
||||||
_w = width;
|
_w = width;
|
||||||
_h = height;
|
_h = height;
|
||||||
|
_numpages = pages;
|
||||||
|
|
||||||
if (width == -1)
|
if (width == -1)
|
||||||
width = core->width;
|
width = core->width;
|
||||||
|
@ -61,13 +101,12 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
||||||
if (height == -1)
|
if (height == -1)
|
||||||
height = core->height;
|
height = core->height;
|
||||||
|
|
||||||
if (fitToScreen)
|
viewportW = width;
|
||||||
{
|
viewportH = height;
|
||||||
|
|
||||||
sizePowerOf2Texture(width);
|
sizePowerOf2Texture(width);
|
||||||
sizePowerOf2Texture(height);
|
sizePowerOf2Texture(height);
|
||||||
}
|
|
||||||
|
|
||||||
_fitToScreen = fitToScreen;
|
|
||||||
if (width == 0 || height == 0)
|
if (width == 0 || height == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -78,12 +117,8 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
||||||
os << "Loading EXT_framebuffer_object (" << texw << ", " << texh << ")";
|
os << "Loading EXT_framebuffer_object (" << texw << ", " << texh << ")";
|
||||||
debugLog(os.str());
|
debugLog(os.str());
|
||||||
|
|
||||||
if( !glIsRenderbufferEXT || !glBindRenderbufferEXT || !glDeleteRenderbuffersEXT ||
|
if( !glIsFramebufferEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
|
||||||
!glGenRenderbuffersEXT || !glRenderbufferStorageEXT || !glGetRenderbufferParameterivEXT ||
|
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture2DEXT)
|
||||||
!glIsFramebufferEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
|
|
||||||
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture1DEXT ||
|
|
||||||
!glFramebufferTexture2DEXT || !glFramebufferTexture3DEXT || !glFramebufferRenderbufferEXT||
|
|
||||||
!glGetFramebufferAttachmentParameterivEXT)
|
|
||||||
{
|
{
|
||||||
debugLog("One or more EXT_framebuffer_object functions were not found");
|
debugLog("One or more EXT_framebuffer_object functions were not found");
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,47 +126,46 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
||||||
|
|
||||||
unloadDevice();
|
unloadDevice();
|
||||||
|
|
||||||
//
|
// If glDrawBuffersARB() is present, we can attach multiple textures per FBO
|
||||||
// Create a frame-buffer object and a render-buffer object...
|
// and switch between them as render targets. More efficient than switching FBOs.
|
||||||
//
|
_numfbos = glDrawBuffersARB ? 1 : pages;
|
||||||
|
|
||||||
glGenFramebuffersEXT( 1, &g_frameBuffer );
|
glGenFramebuffersEXT(_numfbos, &_fbos[0]);
|
||||||
glGenRenderbuffersEXT( 1, &g_depthRenderBuffer );
|
for(unsigned i = 0; i < _numfbos; ++i)
|
||||||
|
if(!_fbos[i])
|
||||||
|
return false;
|
||||||
|
|
||||||
// Initialize the render-buffer for usage as a depth buffer.
|
if(_numfbos == 1)
|
||||||
// We don't really need this to render things into the frame-buffer object,
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fbos[0] );
|
||||||
// but without it the geometry will not be sorted properly.
|
|
||||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, g_depthRenderBuffer );
|
|
||||||
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height );
|
|
||||||
|
|
||||||
|
glGenTextures( pages, &_texs[0] );
|
||||||
|
|
||||||
glGenTextures( 1, &g_dynamicTextureID );
|
for(unsigned i = 0; i < pages; ++i)
|
||||||
|
{
|
||||||
|
unsigned attach = GL_COLOR_ATTACHMENT0_EXT;
|
||||||
|
if(_numfbos > 1)
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fbos[i] );
|
||||||
|
else
|
||||||
|
attach += i;
|
||||||
|
|
||||||
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
|
glBindTexture(GL_TEXTURE_2D, _texs[i]);
|
||||||
// GL_LINEAR
|
// GL_LINEAR
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
|
||||||
width, height,
|
width, height,
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
|
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attach, GL_TEXTURE_2D, _texs[i], 0);
|
||||||
// Put together
|
}
|
||||||
|
|
||||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_frameBuffer );
|
|
||||||
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_dynamicTextureID, 0 );
|
|
||||||
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, g_depthRenderBuffer );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check for errors...
|
|
||||||
//
|
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
for(unsigned i = 0; i < _numfbos; ++i)
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fbos[i] );
|
||||||
|
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
|
||||||
switch( status )
|
switch( status )
|
||||||
{
|
{
|
||||||
|
@ -144,6 +178,7 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
||||||
unloadDevice();
|
unloadDevice();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debugLog("Done");
|
debugLog("Done");
|
||||||
inited = true;
|
inited = true;
|
||||||
|
@ -161,58 +196,107 @@ void FrameBuffer::unloadDevice()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_frameBuffer)
|
for(size_t i = 0; i < Countof(_texs); ++i)
|
||||||
|
if (_fbos[i])
|
||||||
{
|
{
|
||||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
|
||||||
|
|
||||||
debugLog("frameBuffer handle present, deleting");
|
debugLog("frameBuffer handle present, deleting");
|
||||||
glDeleteFramebuffersEXT(1, &g_frameBuffer);
|
glDeleteFramebuffersEXT(1, &_fbos[i]);
|
||||||
g_frameBuffer = 0;
|
_fbos[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_dynamicTextureID)
|
for(size_t i = 0; i < Countof(_texs); ++i)
|
||||||
|
if (_texs[i])
|
||||||
{
|
{
|
||||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
debugLog("delete framebuffer texture");
|
||||||
|
glDeleteTextures(1, &_texs[i]);
|
||||||
debugLog("dynamic texture ID handle present, deleting");
|
_texs[i] = 0;
|
||||||
glDeleteTextures(1, &g_dynamicTextureID);
|
|
||||||
g_dynamicTextureID = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_depthRenderBuffer)
|
|
||||||
{
|
|
||||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
|
||||||
|
|
||||||
debugLog("depth render buffer handle present, deleting");
|
|
||||||
glDeleteRenderbuffersEXT(1, &g_depthRenderBuffer);
|
|
||||||
g_depthRenderBuffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugLog("done");
|
debugLog("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameBuffer::reloadDevice()
|
void FrameBuffer::reloadDevice()
|
||||||
{
|
{
|
||||||
|
if(!_numpages)
|
||||||
|
return;
|
||||||
debugLog("frameBuffer::reloadDevice");
|
debugLog("frameBuffer::reloadDevice");
|
||||||
init(_w, _h, _fitToScreen);
|
init(_w, _h, _numpages);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameBuffer::startCapture() const
|
void FrameBuffer::_bind(unsigned page) const
|
||||||
|
{
|
||||||
|
assert(page < _numpages);
|
||||||
|
_curpage = page + 1;
|
||||||
|
if(glDrawBuffersARB)
|
||||||
|
{
|
||||||
|
assert(_numfbos == 1);
|
||||||
|
if(!isOnTop(this))
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbos[0]);
|
||||||
|
GLenum buf = GL_COLOR_ATTACHMENT0_EXT + page;
|
||||||
|
glDrawBuffersARB(1, &buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(_fbos[page]);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbos[page]);
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport(0,0,viewportW,viewportH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameBuffer::pushCapture(unsigned page) const
|
||||||
{
|
{
|
||||||
assert(inited);
|
assert(inited);
|
||||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_frameBuffer );
|
|
||||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
_bind(page);
|
||||||
|
|
||||||
|
size_t idx = ++s_stackpos;
|
||||||
|
assert(idx < Countof(s_fbostack));
|
||||||
|
s_fbostack[idx].fbo = this;
|
||||||
|
s_fbostack[idx].page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameBuffer::endCapture() const
|
unsigned FrameBuffer::popCapture() const
|
||||||
{
|
{
|
||||||
assert(inited);
|
assert(inited && s_stackpos && isOnTop(this));
|
||||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
|
const unsigned page = s_fbostack[s_stackpos].page;
|
||||||
|
|
||||||
|
FBOStack prev = s_fbostack[--s_stackpos];
|
||||||
|
if(prev.fbo)
|
||||||
|
prev.fbo->_bind(prev.page);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
if(glDrawBuffersARB)
|
||||||
|
glDrawBuffer(GL_BACK);
|
||||||
|
glViewport(0, 0, core->width, core->height);
|
||||||
|
}
|
||||||
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameBuffer::bindTexture() const
|
void FrameBuffer::replaceCapture(unsigned page) const
|
||||||
{
|
{
|
||||||
assert(inited);
|
assert(inited && s_stackpos);
|
||||||
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
|
|
||||||
|
_bind(page);
|
||||||
|
s_fbostack[s_stackpos].fbo = this;
|
||||||
|
s_fbostack[s_stackpos].page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned FrameBuffer::getTextureID(unsigned page) const
|
||||||
|
{
|
||||||
|
assert(inited && page < _numpages);
|
||||||
|
return _texs[page];
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameBuffer::bindTexture(unsigned page) const
|
||||||
|
{
|
||||||
|
// Technically it's enough that this texture isn't the one currently rendered to,
|
||||||
|
// but because we don't know when the topmost FBO is popped (and subsequently
|
||||||
|
// writing to the texture we're now about to read from) let's be extra safe
|
||||||
|
// and generalize this to: Textures part of the FBO stack are forbidden to bind.
|
||||||
|
assert(!isInStack(this, page));
|
||||||
|
unsigned tex = getTextureID(page);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
|
}
|
||||||
|
|
|
@ -23,32 +23,47 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
|
||||||
|
class FrameBufferCapture;
|
||||||
|
struct RenderState;
|
||||||
|
|
||||||
|
|
||||||
class FrameBuffer
|
class FrameBuffer
|
||||||
{
|
{
|
||||||
|
friend class FrameBufferCapture;
|
||||||
public:
|
public:
|
||||||
FrameBuffer();
|
FrameBuffer();
|
||||||
~FrameBuffer();
|
~FrameBuffer();
|
||||||
bool init(int width, int height, bool fitToScreen=false);
|
bool init(int width, int height, unsigned pages);
|
||||||
bool isInited() const { return inited; }
|
bool isInited() const { return inited; }
|
||||||
void startCapture() const;
|
unsigned getTextureID(unsigned page) const;
|
||||||
void endCapture() const;
|
void bindTexture(unsigned page) const;
|
||||||
void bindTexture() const;
|
|
||||||
int getTexWidth() const { return texw; }
|
int getTexWidth() const { return texw; }
|
||||||
int getTexHeight() const { return texh; }
|
int getTexHeight() const { return texh; }
|
||||||
float getWidthP() const;
|
float getWidthP() const;
|
||||||
float getHeightP() const;
|
float getHeightP() const;
|
||||||
|
bool getCurrentPage() const;
|
||||||
|
|
||||||
void unloadDevice();
|
void unloadDevice();
|
||||||
void reloadDevice();
|
void reloadDevice();
|
||||||
|
|
||||||
|
// push/pop capture stack
|
||||||
|
void pushCapture(unsigned page) const;
|
||||||
|
unsigned popCapture() const; // returns page
|
||||||
|
|
||||||
|
// replace top of capture stack with this
|
||||||
|
void replaceCapture(unsigned page) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void _bind(unsigned page) const;
|
||||||
|
|
||||||
|
unsigned _fbos[8];
|
||||||
|
unsigned _texs[8];
|
||||||
|
|
||||||
int _w, _h;
|
int _w, _h;
|
||||||
bool _fitToScreen;
|
mutable unsigned _curpage; // 0 if not currently bound
|
||||||
unsigned g_frameBuffer;
|
unsigned _numpages, _numfbos;
|
||||||
unsigned g_depthRenderBuffer;
|
|
||||||
unsigned g_dynamicTextureID;
|
|
||||||
int texw, texh;
|
int texw, texh;
|
||||||
|
int viewportW, viewportH;
|
||||||
bool inited;
|
bool inited;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -98,22 +98,13 @@ PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL;
|
||||||
PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
|
PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
|
||||||
|
|
||||||
// GL_ARB_shader_objects and related
|
// GL_ARB_shader_objects and related
|
||||||
PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL;
|
|
||||||
PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
|
|
||||||
PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
|
|
||||||
PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
|
|
||||||
PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
|
|
||||||
PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL;
|
|
||||||
PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL;
|
PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL;
|
||||||
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
|
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
|
||||||
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
|
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
|
||||||
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
|
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
|
||||||
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
|
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
|
||||||
PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL;
|
|
||||||
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
|
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
|
||||||
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
|
PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
|
||||||
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
|
|
||||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
|
|
||||||
|
|
||||||
// ARB_vertex_buffer_object
|
// ARB_vertex_buffer_object
|
||||||
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
|
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
|
||||||
|
@ -124,6 +115,8 @@ PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
|
||||||
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
|
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
|
||||||
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
|
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
|
||||||
|
|
||||||
|
PFNGLCOPYIMAGESUBDATAEXTPROC glCopyImageSubDataEXT = NULL;
|
||||||
|
|
||||||
// extern
|
// extern
|
||||||
unsigned g_dbg_numRenderCalls = 0;
|
unsigned g_dbg_numRenderCalls = 0;
|
||||||
bool g_has_GL_GENERATE_MIPMAP = false;
|
bool g_has_GL_GENERATE_MIPMAP = false;
|
||||||
|
@ -182,22 +175,16 @@ bool lookup_all_glsyms()
|
||||||
debugLog(os.str());
|
debugLog(os.str());
|
||||||
}
|
}
|
||||||
// framebuffer
|
// framebuffer
|
||||||
glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glIsRenderbufferEXT");
|
|
||||||
glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glBindRenderbufferEXT");
|
|
||||||
glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT");
|
|
||||||
glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)SDL_GL_GetProcAddress("glGenRenderbuffersEXT");
|
|
||||||
glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)SDL_GL_GetProcAddress("glRenderbufferStorageEXT");
|
|
||||||
glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT");
|
|
||||||
glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glIsFramebufferEXT");
|
glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glIsFramebufferEXT");
|
||||||
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glBindFramebufferEXT");
|
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glBindFramebufferEXT");
|
||||||
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
|
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
|
||||||
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glGenFramebuffersEXT");
|
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glGenFramebuffersEXT");
|
||||||
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
|
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
|
||||||
glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture1DEXT");
|
|
||||||
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
|
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
|
||||||
glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture3DEXT");
|
glDrawBuffersARB = NULL;//(PFNGLDRAWBUFFERSARBPROC)SDL_GL_GetProcAddress("glDrawBuffersARB");
|
||||||
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
|
|
||||||
glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT");
|
// GL 4.3+, but maybe available as an extension
|
||||||
|
glCopyImageSubDataEXT = (PFNGLCOPYIMAGESUBDATAEXTPROC)SDL_GL_GetProcAddress("glCopyImageSubDataEXT");
|
||||||
|
|
||||||
// shaders
|
// shaders
|
||||||
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB");
|
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB");
|
||||||
|
@ -265,22 +252,13 @@ void unload_all_glsyms()
|
||||||
|
|
||||||
// set these back to NULL and reload them upon reinit, otherwise they
|
// set these back to NULL and reload them upon reinit, otherwise they
|
||||||
// might point to a bogus address when the shared library is reloaded.
|
// might point to a bogus address when the shared library is reloaded.
|
||||||
glIsRenderbufferEXT = NULL;
|
|
||||||
glBindRenderbufferEXT = NULL;
|
|
||||||
glDeleteRenderbuffersEXT = NULL;
|
|
||||||
glGenRenderbuffersEXT = NULL;
|
|
||||||
glRenderbufferStorageEXT = NULL;
|
|
||||||
glGetRenderbufferParameterivEXT = NULL;
|
|
||||||
glIsFramebufferEXT = NULL;
|
glIsFramebufferEXT = NULL;
|
||||||
glBindFramebufferEXT = NULL;
|
glBindFramebufferEXT = NULL;
|
||||||
glDeleteFramebuffersEXT = NULL;
|
glDeleteFramebuffersEXT = NULL;
|
||||||
glGenFramebuffersEXT = NULL;
|
glGenFramebuffersEXT = NULL;
|
||||||
glCheckFramebufferStatusEXT = NULL;
|
glCheckFramebufferStatusEXT = NULL;
|
||||||
glFramebufferTexture1DEXT = NULL;
|
|
||||||
glFramebufferTexture2DEXT = NULL;
|
glFramebufferTexture2DEXT = NULL;
|
||||||
glFramebufferTexture3DEXT = NULL;
|
glDrawBuffersARB = NULL;
|
||||||
glFramebufferRenderbufferEXT = NULL;
|
|
||||||
glGetFramebufferAttachmentParameterivEXT = NULL;
|
|
||||||
|
|
||||||
glCreateProgramObjectARB = NULL;
|
glCreateProgramObjectARB = NULL;
|
||||||
glDeleteObjectARB = NULL;
|
glDeleteObjectARB = NULL;
|
||||||
|
|
|
@ -87,6 +87,8 @@ 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,glReadBuffer,(GLenum mode),(mode),)
|
||||||
|
GL_FUNC(void,glDrawBuffer,(GLenum mode),(mode),)
|
||||||
|
|
||||||
// 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),)
|
||||||
|
|
|
@ -50,6 +50,10 @@ GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GL
|
||||||
#endif
|
#endif
|
||||||
#endif /* GL_ARB_debug_output */
|
#endif /* GL_ARB_debug_output */
|
||||||
|
|
||||||
|
#if !defined(GL_ARB_copy_image) && !defined(GL_VERSION_4_3)
|
||||||
|
typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WINDOWS_
|
#ifdef _WINDOWS_
|
||||||
#error windows.h was included! euuugh!
|
#error windows.h was included! euuugh!
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,22 +90,13 @@ extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
|
||||||
extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
|
extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
|
||||||
extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
|
extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
|
||||||
|
|
||||||
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
|
|
||||||
extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
|
|
||||||
extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
|
|
||||||
extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT;
|
|
||||||
extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
|
|
||||||
extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT;
|
|
||||||
extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
|
extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
|
||||||
extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
|
extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
|
||||||
extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
|
extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
|
||||||
extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
|
extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
|
||||||
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
|
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
|
||||||
extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
|
|
||||||
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
|
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
|
||||||
extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
|
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
|
||||||
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
|
|
||||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
|
|
||||||
|
|
||||||
extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
|
extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
|
||||||
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
|
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
|
||||||
|
@ -111,4 +106,6 @@ extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
|
||||||
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
|
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
|
||||||
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
|
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
|
||||||
|
|
||||||
|
extern PFNGLCOPYIMAGESUBDATAEXTPROC glCopyImageSubDataEXT;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,6 +37,8 @@ RenderObjectLayer::RenderObjectLayer()
|
||||||
renderObjects[i] = 0;
|
renderObjects[i] = 0;
|
||||||
objectCount = 0;
|
objectCount = 0;
|
||||||
firstFreeIdx = 0;
|
firstFreeIdx = 0;
|
||||||
|
preRender = NULL;
|
||||||
|
postRender = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderObjectLayer::~RenderObjectLayer()
|
RenderObjectLayer::~RenderObjectLayer()
|
||||||
|
@ -251,8 +253,10 @@ void RenderObjectLayer::render(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
assert(rs.pass == RenderObject::RENDER_ALL);
|
assert(rs.pass == RenderObject::RENDER_ALL);
|
||||||
const RenderObject * const * rlist = &toRender[0]; // known to have at least one element
|
const RenderObject * const * rlist = &toRender[0]; // known to have at least one element
|
||||||
while(const RenderObject *ro = *rlist++)
|
const RenderObject *ro = *rlist++;
|
||||||
|
do
|
||||||
ro->render(rs);
|
ro->render(rs);
|
||||||
|
while( (ro = *rlist++) );
|
||||||
proc += toRender.size() - 1;
|
proc += toRender.size() - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -81,11 +81,12 @@ void ScreenTransition::reloadDevice()
|
||||||
void ScreenTransition::capture()
|
void ScreenTransition::capture()
|
||||||
{
|
{
|
||||||
assert(screen_texture);
|
assert(screen_texture);
|
||||||
core->render();
|
core->renderExternal();
|
||||||
|
|
||||||
if (screen_texture)
|
if (screen_texture)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
||||||
|
glReadBuffer(GL_BACK);
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, windowWidth, windowHeight);
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, windowWidth, windowHeight);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue