mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-02-16 17:45:52 +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;
|
||||
cmDebug = 0;
|
||||
saveSlotMode = SSM_NONE;
|
||||
afterEffectManagerLayer = LR_AFTER_EFFECTS; // LR_AFTER_EFFECTS
|
||||
renderObjectLayers.resize(LR_MAX);
|
||||
|
||||
entities.resize(64, 0);
|
||||
|
@ -585,7 +584,7 @@ static void loadBit(int index, float perc = 1)
|
|||
|
||||
loading->setWidthHeight(loadingProgress*600, 23);
|
||||
|
||||
dsq->render();
|
||||
dsq->renderExternal();
|
||||
dsq->showBuffer();
|
||||
}
|
||||
|
||||
|
@ -688,6 +687,45 @@ static bool sdlVideoModeOK(int disp, const int w, const int h, const int bpp)
|
|||
#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()
|
||||
{
|
||||
#define PSIZEOF(x) { std::ostringstream os_; os_ << ("sizeof(" #x ") = ") << sizeof(x); debugLog(os_.str()); }
|
||||
|
@ -911,12 +949,6 @@ void DSQ::init()
|
|||
precacher.clear();
|
||||
|
||||
|
||||
|
||||
render();
|
||||
showBuffer();
|
||||
|
||||
|
||||
|
||||
loadBit(LOAD_INITIAL);
|
||||
|
||||
debugLog("Loading Particle Bank...");
|
||||
|
@ -968,7 +1000,6 @@ void DSQ::init()
|
|||
|
||||
user.video.darkbuffersize = MAX(user.video.darkbuffersize,128);
|
||||
|
||||
darkLayer.setLayers(LR_ELEMENTS13, LR_AFTER_EFFECTS);
|
||||
debugLog("dark layer init");
|
||||
darkLayer.init(user.video.darkbuffersize, user.video.darkfbuffer);
|
||||
debugLog("dark layer togle...");
|
||||
|
@ -1270,6 +1301,14 @@ void DSQ::init()
|
|||
renderObjectLayerOrder[LR_ENTITIES_MINUS3] = -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);
|
||||
|
@ -2717,8 +2756,8 @@ void DSQ::doSaveSlotMenu(SaveSlotMode ssm, const Vector &position)
|
|||
|
||||
glPushAttrib(GL_VIEWPORT_BIT);
|
||||
glViewport(0, 0, renderWidth, renderHeight);
|
||||
clearBuffers();
|
||||
render();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
renderExternal();
|
||||
scrShotData = grabScreenshot(x, y, scrShotWidth, scrShotHeight);
|
||||
glPopAttrib();
|
||||
showBuffer();
|
||||
|
@ -3315,6 +3354,11 @@ void DSQ::prepScreen(bool screenshot)
|
|||
}
|
||||
}
|
||||
|
||||
void DSQ::onPrepareRender()
|
||||
{
|
||||
game->onPrepareRender();
|
||||
}
|
||||
|
||||
void DSQ::onRender()
|
||||
{
|
||||
if (cursor)
|
||||
|
@ -3661,7 +3705,7 @@ void DSQ::onUpdate(float dt)
|
|||
pollEvents(sec);
|
||||
ActionMapper::onUpdate(sec);
|
||||
SDL_Delay(int(sec*1000));
|
||||
render();
|
||||
renderExternal();
|
||||
showBuffer();
|
||||
resetTimer();
|
||||
|
||||
|
@ -4162,17 +4206,18 @@ void AquariaScreenTransition::capture()
|
|||
InterpolatedVector oldAlpha = dsq->cursor->alpha;
|
||||
dsq->cursor->alpha.x = 0;
|
||||
int width=0, height=0;
|
||||
dsq->render();
|
||||
dsq->renderExternal();
|
||||
|
||||
width = dsq->getWindowWidth();
|
||||
height = dsq->getWindowHeight();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
||||
glReadBuffer(GL_BACK);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
|
||||
|
||||
|
||||
dsq->cursor->alpha = oldAlpha;
|
||||
dsq->render();
|
||||
dsq->renderExternal();
|
||||
dsq->showBuffer();
|
||||
|
||||
this->alpha = 1;
|
||||
|
|
|
@ -444,8 +444,9 @@ protected:
|
|||
float shakeCameraTimer;
|
||||
float shakeCameraMag;
|
||||
|
||||
void onUpdate(float dt);
|
||||
void onRender();
|
||||
void onUpdate(float dt) OVERRIDE;
|
||||
void onRender() OVERRIDE;
|
||||
void onPrepareRender() OVERRIDE;
|
||||
|
||||
void modifyDt(float &dt);
|
||||
|
||||
|
|
|
@ -232,6 +232,7 @@ Game::Game() : StateObject()
|
|||
noSceneTransitionFadeout = false;
|
||||
fullTilesetReload = false;
|
||||
highestLoadedEntityID = 0;
|
||||
waterSurfaceRender = NULL;
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
|
@ -2032,7 +2033,7 @@ bool Game::saveScene(std::string scene)
|
|||
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];
|
||||
std::ostringstream simpleElements;
|
||||
|
@ -2084,7 +2085,7 @@ bool Game::saveScene(std::string scene)
|
|||
{
|
||||
XMLElement *simpleElementsXML = saveFile.NewElement("SE");
|
||||
simpleElementsXML->SetAttribute("k", s.c_str());
|
||||
simpleElementsXML->SetAttribute("l", (unsigned)lr);
|
||||
simpleElementsXML->SetAttribute("l", lr);
|
||||
std::string str = simpleElements_repeatScale.str();
|
||||
if(!str.empty())
|
||||
simpleElementsXML->SetAttribute("repeatScale", str.c_str());
|
||||
|
@ -2436,6 +2437,7 @@ void Game::applyState()
|
|||
inHelpScreen = false;
|
||||
helpBG = 0;
|
||||
helpBG2 = 0;
|
||||
waterSurfaceRender = NULL;
|
||||
|
||||
dsq->returnToScene = "";
|
||||
|
||||
|
@ -4788,6 +4790,7 @@ void Game::removeState()
|
|||
gridRenderUser1 = 0;
|
||||
gridRenderUser2 = 0;
|
||||
worldMapRender = 0;
|
||||
waterSurfaceRender = 0;
|
||||
|
||||
clearObsRows();
|
||||
|
||||
|
@ -4987,3 +4990,9 @@ void Game::onContinuityReset()
|
|||
{
|
||||
themenu->onContinuityReset();
|
||||
}
|
||||
|
||||
void Game::onPrepareRender()
|
||||
{
|
||||
if(waterSurfaceRender)
|
||||
waterSurfaceRender->prepareRender();
|
||||
}
|
||||
|
|
|
@ -398,6 +398,7 @@ public:
|
|||
bool isIgnoreAction(AquariaActions ac) const;
|
||||
|
||||
void onContinuityReset();
|
||||
void onPrepareRender();
|
||||
|
||||
protected:
|
||||
unsigned highestLoadedEntityID;
|
||||
|
|
|
@ -6,30 +6,26 @@
|
|||
#include "RenderBase.h"
|
||||
|
||||
|
||||
|
||||
WaterSurfaceRender::WaterSurfaceRender() : Quad()
|
||||
{
|
||||
cull = false;
|
||||
this->texcoordOverride = true;
|
||||
|
||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
||||
if (dsq->useFrameBuffer)
|
||||
{
|
||||
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->repeatTextureToFill(1);
|
||||
qLine->cull = false;
|
||||
game->addRenderObject(qLine, LR_WATERSURFACE2);
|
||||
|
||||
qLine2 = 0;
|
||||
|
||||
|
||||
|
||||
qSurface = new Quad("missingimage", Vector(0,0));
|
||||
|
||||
qSurface->cull = false;
|
||||
qSurface->repeatTextureToFill(1);
|
||||
game->addRenderObject(qSurface, LR_WATERSURFACE2);
|
||||
|
@ -38,16 +34,28 @@ WaterSurfaceRender::WaterSurfaceRender() : Quad()
|
|||
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)
|
||||
{
|
||||
Quad::onUpdate(dt);
|
||||
|
||||
qLine->alpha = qSurface->alpha = 1;
|
||||
|
||||
|
||||
|
||||
position.x = core->screenCenter.x;
|
||||
position.y = game->waterLevel.x;
|
||||
|
||||
|
@ -88,28 +96,24 @@ void WaterSurfaceRender::onUpdate(float dt)
|
|||
|
||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
||||
{
|
||||
qSurface->alphaMod = 0.5;
|
||||
qSurface->alphaMod = 0.5f;
|
||||
fbEffectVisible = this->isOnScreen();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qLine->alpha = qSurface->alpha = 0;
|
||||
|
||||
if (qLine2)
|
||||
{
|
||||
qLine2->alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
||||
if (fbEffectVisible)
|
||||
{
|
||||
const float reflectSize = 97;
|
||||
const float reflectPos = (game->waterLevel.x - core->cameraPos.y)
|
||||
+ (game->waterLevel.x - core->screenCenter.y) / 3;
|
||||
const float reflectOffset = -0.03f;
|
||||
const float coordDiv = 768;
|
||||
const float v0 = 1 + reflectOffset - (reflectPos * core->globalScale.x) / coordDiv;
|
||||
const float v1 = v0 + (reflectSize * core->globalScale.x) / coordDiv;
|
||||
const float coordMul = 1.0f / 768;
|
||||
const float v0 = 1 + reflectOffset - (reflectPos * core->globalScale.x) * coordMul;
|
||||
const float v1 = v0 + (reflectSize * core->globalScale.x) * coordMul;
|
||||
|
||||
texcoords.u1 = 0;
|
||||
texcoords.u2 = core->frameBuffer.getWidthP();
|
||||
|
@ -127,27 +131,73 @@ void WaterSurfaceRender::onUpdate(float dt)
|
|||
color = Vector(0.4f, 0.7f, 0.8f);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void WaterSurfaceRender::onRender(const RenderState& rs) const
|
||||
{
|
||||
if (game->waterLevel == 0) return;
|
||||
if (dsq->useFrameBuffer && dsq->frameBuffer.isInited())
|
||||
{
|
||||
dsq->frameBuffer.bindTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
if (!fbEffectVisible || game->waterLevel == 0) return;
|
||||
|
||||
|
||||
core->frameBuffer.bindTexture(core->frameBuffer.getCurrentPage() - 1);
|
||||
|
||||
Quad::onRender(rs);
|
||||
|
||||
|
|
|
@ -27,11 +27,14 @@ class WaterSurfaceRender : public Quad
|
|||
{
|
||||
public:
|
||||
WaterSurfaceRender();
|
||||
virtual ~WaterSurfaceRender();
|
||||
void render(const RenderState& rs) const OVERRIDE;
|
||||
void prepareRender();
|
||||
protected:
|
||||
Quad *qSurface, *qLine, *qLine2;
|
||||
virtual void onEndOfLife() OVERRIDE;
|
||||
Quad *qSurface, *qLine;
|
||||
void onRender(const RenderState& rs) const OVERRIDE;
|
||||
void onUpdate(float dt) OVERRIDE;
|
||||
bool fbEffectVisible;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,6 +72,19 @@ void AfterEffectManager::deleteEffects()
|
|||
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()
|
||||
{
|
||||
for(size_t i = 0; i < shaderPipeline.size(); ++i)
|
||||
|
@ -146,7 +159,7 @@ void AfterEffectManager::destroyEffect(int 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());
|
||||
|
||||
|
@ -154,48 +167,53 @@ void AfterEffectManager::render(const RenderState& rs) const
|
|||
|
||||
rs.gpu.setBlend(BLEND_DISABLED);
|
||||
|
||||
core->frameBuffer.endCapture();
|
||||
glTranslatef(core->cameraPos.x, core->cameraPos.y, 0);
|
||||
glScalef(core->invGlobalScale, core->invGlobalScale,0);
|
||||
|
||||
glColor4f(1,1,1,1);
|
||||
renderGrid(rs);
|
||||
renderGrid(rs, fboPageWithImage);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void AfterEffectManager::renderGrid(const RenderState& rs) const
|
||||
void AfterEffectManager::renderGrid(const RenderState& rs, unsigned fbPage) const
|
||||
{
|
||||
int firstShader = -1;
|
||||
int lastShader = -1;
|
||||
Shader *activeShader = 0;
|
||||
size_t firstShader, lastShader;
|
||||
Shader *activeShader = NULL;
|
||||
for (size_t i = 0; i < shaderPipeline.size(); ++i)
|
||||
{
|
||||
if(shaderPipeline[i] && shaderPipeline[i]->isLoaded())
|
||||
{
|
||||
if(firstShader < 0)
|
||||
if(!activeShader)
|
||||
{
|
||||
firstShader = int(i);
|
||||
firstShader = 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 vh = core->getVirtualHeight();
|
||||
int offx = -core->getVirtualOffX();
|
||||
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)
|
||||
{
|
||||
activeShader->bind();
|
||||
activeShader->setInt("tex", 0);
|
||||
activeShader->bind();
|
||||
|
||||
// Unless this is the last pass, render to fb(1)
|
||||
if(firstShader != lastShader)
|
||||
backupBuffer.startCapture();
|
||||
fb->pushCapture(1 - fbPage);
|
||||
}
|
||||
|
||||
// verts are in 0..1, transform so that we cover the entire screen
|
||||
|
@ -208,39 +226,44 @@ void AfterEffectManager::renderGrid(const RenderState& rs) const
|
|||
//renderGridPoints(rs);
|
||||
}
|
||||
else
|
||||
blitQuad.render(rs);
|
||||
core->blitQuad.render(rs);
|
||||
|
||||
if (activeShader)
|
||||
{
|
||||
activeShader->unbind();
|
||||
|
||||
if(firstShader != lastShader)
|
||||
{
|
||||
// From here on: secondary shader passes.
|
||||
// We just outputted to the backup buffer...
|
||||
const FrameBuffer *fbIn = &core->frameBuffer;
|
||||
const FrameBuffer *fbOut = &backupBuffer;
|
||||
|
||||
for(int i = firstShader + 1; i <= lastShader; ++i)
|
||||
if(firstShader != lastShader)
|
||||
{
|
||||
activeShader = shaderPipeline[i];
|
||||
if(!(activeShader && activeShader->isLoaded()))
|
||||
continue;
|
||||
// From here on: secondary shader passes.
|
||||
// We just outputted to the backup buffer...
|
||||
|
||||
// Swap and exchange framebuffers. The old output buffer serves as texture input for the other one
|
||||
fbOut->endCapture();
|
||||
std::swap(fbIn, fbOut);
|
||||
fbIn->bindTexture();
|
||||
unsigned pageOut = 1 - fbPage;
|
||||
|
||||
// If this is the last pass, do not render to a frame buffer again
|
||||
if(i != lastShader)
|
||||
fbOut->startCapture();
|
||||
for(size_t i = firstShader + 1; i <= lastShader; ++i)
|
||||
{
|
||||
unsigned pageIn = 1 - pageOut;
|
||||
activeShader = shaderPipeline[i];
|
||||
if(!(activeShader && activeShader->isLoaded()))
|
||||
continue;
|
||||
|
||||
activeShader->bind();
|
||||
activeShader->setInt("tex", 0);
|
||||
// Swap and exchange framebuffers. The old output buffer serves as texture input for the other one
|
||||
pageOut = pageIn;
|
||||
|
||||
blitQuad.render(rs);
|
||||
// If this is the last pass, do not render to a frame buffer again
|
||||
if(i == lastShader)
|
||||
fb->popCapture();
|
||||
else
|
||||
fb->replaceCapture(pageOut);
|
||||
|
||||
activeShader->unbind();
|
||||
fb->bindTexture(pageIn);
|
||||
|
||||
activeShader->bind();
|
||||
activeShader->setInt("tex", 0);
|
||||
|
||||
core->blitQuad.render(rs);
|
||||
|
||||
activeShader->unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,9 +278,7 @@ void AfterEffectManager::renderGridPoints(const RenderState& rs) const
|
|||
|
||||
void AfterEffectManager::unloadDevice()
|
||||
{
|
||||
backupBuffer.unloadDevice();
|
||||
grid.dropBuffers();
|
||||
blitQuad.dropBuffers();
|
||||
unloadShaders();
|
||||
}
|
||||
|
||||
|
@ -266,30 +287,12 @@ void AfterEffectManager::_updateScreenSize()
|
|||
screenWidth = core->getWindowWidth();
|
||||
screenHeight = core->getWindowHeight();
|
||||
|
||||
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
|
||||
grid.setTexCoords(tc);
|
||||
blitQuad.setTexCoords(tc);
|
||||
grid.setTexCoords(core->blitQuad.getTexCoords());
|
||||
}
|
||||
|
||||
void AfterEffectManager::updateDevice()
|
||||
{
|
||||
_updateScreenSize();
|
||||
backupBuffer.init(-1, -1, true);
|
||||
_initGrid();
|
||||
}
|
||||
|
||||
|
@ -297,7 +300,6 @@ void AfterEffectManager::reloadDevice()
|
|||
{
|
||||
_updateScreenSize();
|
||||
|
||||
backupBuffer.reloadDevice();
|
||||
_initGrid();
|
||||
|
||||
for (size_t i = 0; i < loadedShaders.size(); ++i)
|
||||
|
@ -442,10 +444,6 @@ void AfterEffectManager::_initGrid()
|
|||
grid.init(xDivs, yDivs);
|
||||
else
|
||||
grid.dropBuffers();
|
||||
|
||||
blitQuad.init(2, 2);
|
||||
blitQuad.reset01();
|
||||
blitQuad.updateVBO(); // never changed afterwards
|
||||
}
|
||||
|
||||
void AfterEffectManager::deleteShader(int handle)
|
||||
|
|
|
@ -78,10 +78,13 @@ public:
|
|||
void clear();
|
||||
void deleteEffects();
|
||||
|
||||
void beginCapture();
|
||||
void endCapture();
|
||||
|
||||
void resetGrid();
|
||||
|
||||
void render(const RenderState& rs) const;
|
||||
void renderGrid(const RenderState& rs) const;
|
||||
void render(const RenderState& rs, unsigned fboPageWithImage) const;
|
||||
void renderGrid(const RenderState& rs, unsigned fbPage) const;
|
||||
void renderGridPoints(const RenderState& rs) const;
|
||||
|
||||
void loadShaders();
|
||||
|
@ -105,17 +108,15 @@ protected:
|
|||
int _insertShader(Shader *sh);
|
||||
void _initGrid();
|
||||
|
||||
RenderGrid grid, blitQuad;
|
||||
RenderGrid grid;
|
||||
bool active;
|
||||
int numEffects;
|
||||
int xDivs, yDivs;
|
||||
int screenWidth, screenHeight;
|
||||
int textureWidth, textureHeight;
|
||||
std::vector<Effect*> effects;
|
||||
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*> loadedShaders;
|
||||
FrameBuffer backupBuffer;
|
||||
|
||||
};
|
||||
|
||||
|
|
121
BBGE/Core.cpp
121
BBGE/Core.cpp
|
@ -151,7 +151,7 @@ void Core::setup_opengl()
|
|||
|
||||
setClearColor(clearColor);
|
||||
|
||||
frameBuffer.init(-1, -1, true);
|
||||
frameBuffer.init(-1, -1, 2);
|
||||
if(afterEffectManager)
|
||||
afterEffectManager->updateDevice();
|
||||
|
||||
|
@ -160,6 +160,32 @@ void Core::setup_opengl()
|
|||
defaultQuadGrid.init(2, 2, defaultTC);
|
||||
|
||||
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)
|
||||
|
@ -378,7 +404,6 @@ Core::Core(const std::string &filesystem, const std::string& extraDataDir, int n
|
|||
baseCullRadius = 1;
|
||||
width = height = 0;
|
||||
_lastEnumeratedDisplayIndex = -1;
|
||||
afterEffectManagerLayer = 0;
|
||||
renderObjectLayers.resize(1);
|
||||
invGlobalScale = 1.0;
|
||||
invGlobalScaleSqr = 1.0;
|
||||
|
@ -740,7 +765,9 @@ void Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsyn
|
|||
enumerateScreenModes(window->getDisplayIndex());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1182,15 +1209,14 @@ void Core::run(float runTime)
|
|||
|
||||
if (settings.renderOn)
|
||||
{
|
||||
if (darkLayer.isUsed())
|
||||
if(!minimized)
|
||||
{
|
||||
darkLayer.preRender();
|
||||
prepareRender();
|
||||
renderInternal(-1, -1, true);
|
||||
|
||||
showBuffer();
|
||||
}
|
||||
|
||||
render();
|
||||
|
||||
showBuffer();
|
||||
|
||||
if (nestedMains == 1)
|
||||
clearGarbage();
|
||||
|
||||
|
@ -1221,11 +1247,6 @@ void Core::run(float runTime)
|
|||
nestedMains--;
|
||||
}
|
||||
|
||||
void Core::clearBuffers()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
|
||||
}
|
||||
|
||||
void Core::setupRenderPositionAndScale()
|
||||
{
|
||||
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()
|
||||
{
|
||||
render();
|
||||
renderExternal();
|
||||
// what if the screen was full white? then you wouldn't want to clear buffers
|
||||
//clearBuffers();
|
||||
showBuffer();
|
||||
|
@ -1780,7 +1801,13 @@ void Core::updateCullData()
|
|||
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;
|
||||
processedRenderObjectCount = 0;
|
||||
|
@ -1788,13 +1815,10 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail)
|
|||
|
||||
globalScaleChanged();
|
||||
|
||||
if (minimized) return;
|
||||
onRender();
|
||||
|
||||
RenderObject::lastTextureApplied = 0;
|
||||
|
||||
updateCullData();
|
||||
|
||||
onPrepareRender();
|
||||
|
||||
// TODO: this could be done in parallel
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
glLoadIdentity(); // Reset The View
|
||||
clearBuffers();
|
||||
|
||||
if (afterEffectManager && frameBuffer.isInited() && useFrameBufferIfAvail)
|
||||
{
|
||||
frameBuffer.startCapture();
|
||||
}
|
||||
|
||||
setupRenderPositionAndScale();
|
||||
|
||||
CombinedRenderAndGPUState rs;
|
||||
|
||||
|
||||
for (size_t c = 0; c < renderObjectLayerOrder.size(); c++)
|
||||
{
|
||||
int i = renderObjectLayerOrder[c];
|
||||
if (i == -1) continue;
|
||||
if ((startLayer != -1 && endLayer != -1) && (i < startLayer || i > endLayer)) continue;
|
||||
|
||||
if (darkLayer.isUsed() )
|
||||
{
|
||||
|
||||
if (i == darkLayer.getRenderLayer())
|
||||
{
|
||||
darkLayer.render(rs);
|
||||
}
|
||||
|
||||
if (i == darkLayer.getLayer() && startLayer != i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (afterEffectManager /*&& afterEffectManager->active*/ && i == afterEffectManagerLayer)
|
||||
{
|
||||
afterEffectManager->render(rs);
|
||||
}
|
||||
// don't render the layers that the dark layer takes as input
|
||||
if(allowSkip && !darkLayer.shouldRenderLayer(i))
|
||||
continue;
|
||||
|
||||
RenderObjectLayer *r = &renderObjectLayers[i];
|
||||
if(!r->visible)
|
||||
continue;
|
||||
|
||||
if(r->preRender)
|
||||
if(!r->preRender(rs))
|
||||
continue;
|
||||
|
||||
r->render(rs);
|
||||
|
||||
if(r->postRender)
|
||||
r->postRender(rs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1949,6 +1977,7 @@ void Core::shutdown()
|
|||
|
||||
defaultQuadGrid.dropBuffers();
|
||||
defautQuadBorder.dropBuffer();
|
||||
blitQuad.dropBuffers();
|
||||
|
||||
debugLog("Shutdown Graphics Library...");
|
||||
shutdownGraphicsLibrary();
|
||||
|
|
15
BBGE/Core.h
15
BBGE/Core.h
|
@ -113,6 +113,9 @@ enum FollowCameraLock
|
|||
|
||||
typedef std::vector <RenderObject*> RenderObjects;
|
||||
|
||||
typedef bool (*PreRenderFunc)(const RenderState& rs);
|
||||
typedef void (*PostRenderFunc)(const RenderState& rs);
|
||||
|
||||
class RenderObjectLayer
|
||||
{
|
||||
public:
|
||||
|
@ -170,6 +173,9 @@ public:
|
|||
|
||||
bool update;
|
||||
|
||||
PreRenderFunc preRender;
|
||||
PostRenderFunc postRender;
|
||||
|
||||
protected:
|
||||
RenderObjects renderObjects;
|
||||
std::vector<const RenderObject*> toRender;
|
||||
|
@ -206,8 +212,9 @@ public:
|
|||
|
||||
void applyState(const std::string &state);
|
||||
|
||||
void clearBuffers();
|
||||
void render(int startLayer=-1, int endLayer=-1, bool useFrameBufferIfAvail=true);
|
||||
void renderExternal();
|
||||
void prepareRender();
|
||||
void renderInternal(int startLayer, int endLayer, bool allowSkip);
|
||||
void showBuffer();
|
||||
void quit();
|
||||
bool isShuttingDown();
|
||||
|
@ -465,7 +472,6 @@ protected:
|
|||
virtual void onJoystickAdded(int deviceID);
|
||||
virtual void onJoystickRemoved(int instanceID);
|
||||
|
||||
int afterEffectManagerLayer;
|
||||
Vector cameraOffset;
|
||||
std::vector<float> avgFPS;
|
||||
virtual void modifyDt(float &dt){}
|
||||
|
@ -486,6 +492,7 @@ protected:
|
|||
|
||||
virtual void onUpdate(float dt);
|
||||
virtual void onRender(){}
|
||||
virtual void onPrepareRender(){}
|
||||
|
||||
void setupFileAccess();
|
||||
std::string _extraDataDir;
|
||||
|
@ -498,6 +505,8 @@ protected:
|
|||
DynamicGPUBuffer defautQuadBorder;
|
||||
|
||||
public:
|
||||
RenderGrid blitQuad;
|
||||
|
||||
// inclusive!
|
||||
inline int getMaxActionStatusIndex() const { return int(actionStatus.size()) - 2; }
|
||||
// pass -1 for is a sentinel that captures all input
|
||||
|
|
|
@ -26,12 +26,11 @@ DarkLayer::DarkLayer()
|
|||
{
|
||||
quality = 0;
|
||||
active = false;
|
||||
layer = -1;
|
||||
renderLayer = -1;
|
||||
texture = 0;
|
||||
|
||||
format = GL_RGB; //FIXED?: used to be GL_LUMINANCE, that might have been causing problems
|
||||
useFrameBuffer = true; //BUG?: will do this even if frame buffer is off in usersettings...
|
||||
useFrameBuffer = false;
|
||||
layer = -1;
|
||||
beginLayer = -1;
|
||||
lastLayer = -1;
|
||||
}
|
||||
|
||||
void DarkLayer::unloadDevice()
|
||||
|
@ -53,23 +52,16 @@ void DarkLayer::reloadDevice()
|
|||
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
|
||||
// MAKE SURE TO RESTORE THIS CODE TO THE WAY IT WAS
|
||||
return layer > -1 && active;
|
||||
|
||||
}
|
||||
|
||||
void DarkLayer::setLayers(int layer, int rl)
|
||||
{
|
||||
this->layer = layer;
|
||||
this->renderLayer = rl;
|
||||
if(!active)
|
||||
return true;
|
||||
return useFrameBuffer || (lr < beginLayer || lr > lastLayer);
|
||||
}
|
||||
|
||||
void DarkLayer::init(int quality, bool useFrameBufferParam)
|
||||
|
@ -80,7 +72,7 @@ void DarkLayer::init(int quality, bool useFrameBufferParam)
|
|||
|
||||
if (useFrameBuffer)
|
||||
{
|
||||
if (!frameBuffer.init(quality, quality))
|
||||
if (!frameBuffer.init(quality, quality, 1))
|
||||
useFrameBuffer = false;
|
||||
else
|
||||
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)
|
||||
{
|
||||
this->active = on;
|
||||
|
@ -104,77 +91,77 @@ void DarkLayer::toggle(bool on)
|
|||
|
||||
void DarkLayer::preRender()
|
||||
{
|
||||
if (layer != -1)
|
||||
if(!useFrameBuffer)
|
||||
{
|
||||
glViewport(0,0,quality,quality);
|
||||
|
||||
if (useFrameBuffer)
|
||||
frameBuffer.startCapture();
|
||||
|
||||
glViewport(0, 0, quality, quality);
|
||||
glClearColor(1,1,1,0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
core->renderInternal(beginLayer, lastLayer, false);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glReadBuffer(GL_BACK);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, quality, quality, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
core->render(layer, layer, false);
|
||||
void DarkLayer::beginCapture()
|
||||
{
|
||||
if(useFrameBuffer)
|
||||
{
|
||||
frameBuffer.pushCapture(0);
|
||||
glClearColor(1,1,1,0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
if (useFrameBuffer)
|
||||
frameBuffer.endCapture();
|
||||
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);
|
||||
glClearColor(0,0,0,0);
|
||||
void DarkLayer::endCapture()
|
||||
{
|
||||
if(useFrameBuffer)
|
||||
{
|
||||
frameBuffer.popCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void DarkLayer::render(const RenderState& rs) const
|
||||
{
|
||||
if (renderLayer != -1)
|
||||
{
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
if (useFrameBuffer)
|
||||
frameBuffer.bindTexture(0);
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D,texture);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
if (useFrameBuffer)
|
||||
frameBuffer.bindTexture();
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D,texture);
|
||||
rs.gpu.setBlend(BLEND_MULT);
|
||||
|
||||
rs.gpu.setBlend(BLEND_MULT);
|
||||
glColor4f(1,1,1,1);
|
||||
|
||||
glColor4f(1,1,1,1);
|
||||
const float width = core->getWindowWidth();
|
||||
const float height = core->getWindowHeight();
|
||||
const float offX = -(core->getVirtualOffX() * width / core->getVirtualWidth());
|
||||
const float offY = -(core->getVirtualOffY() * height / core->getVirtualHeight());
|
||||
const float stretch = 4;
|
||||
|
||||
const float width = core->getWindowWidth();
|
||||
const float height = core->getWindowHeight();
|
||||
const float offX = -(core->getVirtualOffX() * width / core->getVirtualWidth());
|
||||
const float offY = -(core->getVirtualOffY() * height / core->getVirtualHeight());
|
||||
const float stretch = 4;
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0,1);
|
||||
glVertex2f(offX-stretch, offY-stretch);
|
||||
|
||||
glTexCoord2f(0,1);
|
||||
glVertex2f(offX-stretch, offY-stretch);
|
||||
glTexCoord2f(0,0);
|
||||
glVertex2f(offX-stretch, height+offY+stretch);
|
||||
|
||||
glTexCoord2f(0,0);
|
||||
glVertex2f(offX-stretch, height+offY+stretch);
|
||||
glTexCoord2f(1,0);
|
||||
glVertex2f(width+offX+stretch, height+offY+stretch);
|
||||
|
||||
glTexCoord2f(1,0);
|
||||
glVertex2f(width+offX+stretch, height+offY+stretch);
|
||||
glTexCoord2f(1,1);
|
||||
glVertex2f(width+offX+stretch, offY-stretch);
|
||||
|
||||
glTexCoord2f(1,1);
|
||||
glVertex2f(width+offX+stretch, offY-stretch);
|
||||
glEnd();
|
||||
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
RenderObject::lastTextureApplied = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
}
|
||||
RenderObject::lastTextureApplied = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
|
|
@ -32,24 +32,28 @@ public:
|
|||
DarkLayer();
|
||||
void init(int quality, bool useFrameBuffer=true);
|
||||
void toggle(bool on);
|
||||
void setLayers(int layer, int renderLayer);
|
||||
void preRender();
|
||||
void setSrcLayer(int layer);
|
||||
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;
|
||||
int getLayer();
|
||||
int getRenderLayer();
|
||||
bool isUsed();
|
||||
bool isUsed() const;
|
||||
bool shouldRenderLayer(int lr) const;
|
||||
|
||||
void unloadDevice();
|
||||
void reloadDevice();
|
||||
|
||||
int beginLayer;
|
||||
int lastLayer; // inclusive
|
||||
|
||||
protected:
|
||||
bool useFrameBuffer;
|
||||
FrameBuffer frameBuffer;
|
||||
protected:
|
||||
int quality;
|
||||
int layer;
|
||||
bool active;
|
||||
int layer, renderLayer;
|
||||
unsigned texture;
|
||||
unsigned format;
|
||||
};
|
||||
|
||||
#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!
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
inited = false;
|
||||
texw = 0;
|
||||
texh = 0;
|
||||
g_frameBuffer = 0;
|
||||
g_depthRenderBuffer = 0;
|
||||
g_dynamicTextureID = 0;
|
||||
viewportW = 0;
|
||||
viewportH = 0;
|
||||
_curpage = 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()
|
||||
|
@ -50,10 +82,18 @@ float FrameBuffer::getHeightP() const
|
|||
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;
|
||||
_h = height;
|
||||
_numpages = pages;
|
||||
|
||||
if (width == -1)
|
||||
width = core->width;
|
||||
|
@ -61,13 +101,12 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
|||
if (height == -1)
|
||||
height = core->height;
|
||||
|
||||
if (fitToScreen)
|
||||
{
|
||||
sizePowerOf2Texture(width);
|
||||
sizePowerOf2Texture(height);
|
||||
}
|
||||
viewportW = width;
|
||||
viewportH = height;
|
||||
|
||||
sizePowerOf2Texture(width);
|
||||
sizePowerOf2Texture(height);
|
||||
|
||||
_fitToScreen = fitToScreen;
|
||||
if (width == 0 || height == 0)
|
||||
return false;
|
||||
|
||||
|
@ -78,12 +117,8 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
|||
os << "Loading EXT_framebuffer_object (" << texw << ", " << texh << ")";
|
||||
debugLog(os.str());
|
||||
|
||||
if( !glIsRenderbufferEXT || !glBindRenderbufferEXT || !glDeleteRenderbuffersEXT ||
|
||||
!glGenRenderbuffersEXT || !glRenderbufferStorageEXT || !glGetRenderbufferParameterivEXT ||
|
||||
!glIsFramebufferEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
|
||||
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture1DEXT ||
|
||||
!glFramebufferTexture2DEXT || !glFramebufferTexture3DEXT || !glFramebufferRenderbufferEXT||
|
||||
!glGetFramebufferAttachmentParameterivEXT)
|
||||
if( !glIsFramebufferEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
|
||||
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture2DEXT)
|
||||
{
|
||||
debugLog("One or more EXT_framebuffer_object functions were not found");
|
||||
return false;
|
||||
|
@ -91,58 +126,58 @@ bool FrameBuffer::init(int width, int height, bool fitToScreen)
|
|||
|
||||
unloadDevice();
|
||||
|
||||
//
|
||||
// Create a frame-buffer object and a render-buffer object...
|
||||
//
|
||||
// If glDrawBuffersARB() is present, we can attach multiple textures per FBO
|
||||
// and switch between them as render targets. More efficient than switching FBOs.
|
||||
_numfbos = glDrawBuffersARB ? 1 : pages;
|
||||
|
||||
glGenFramebuffersEXT( 1, &g_frameBuffer );
|
||||
glGenRenderbuffersEXT( 1, &g_depthRenderBuffer );
|
||||
glGenFramebuffersEXT(_numfbos, &_fbos[0]);
|
||||
for(unsigned i = 0; i < _numfbos; ++i)
|
||||
if(!_fbos[i])
|
||||
return false;
|
||||
|
||||
// Initialize the render-buffer for usage as a depth buffer.
|
||||
// We don't really need this to render things into the frame-buffer object,
|
||||
// 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 );
|
||||
if(_numfbos == 1)
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fbos[0] );
|
||||
|
||||
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 );
|
||||
// GL_LINEAR
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glBindTexture(GL_TEXTURE_2D, _texs[i]);
|
||||
// GL_LINEAR
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
width, height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
width, height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, 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 );
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attach, GL_TEXTURE_2D, _texs[i], 0);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
switch( status )
|
||||
for(unsigned i = 0; i < _numfbos; ++i)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
break;
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fbos[i] );
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
debugLog("GL_FRAMEBUFFER_UNSUPPORTED_EXT!");
|
||||
default:
|
||||
unloadDevice();
|
||||
return false;
|
||||
switch( status )
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
debugLog("GL_FRAMEBUFFER_UNSUPPORTED_EXT!");
|
||||
default:
|
||||
unloadDevice();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("Done");
|
||||
|
@ -161,58 +196,107 @@ void FrameBuffer::unloadDevice()
|
|||
return;
|
||||
}
|
||||
|
||||
if (g_frameBuffer)
|
||||
{
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
for(size_t i = 0; i < Countof(_texs); ++i)
|
||||
if (_fbos[i])
|
||||
{
|
||||
debugLog("frameBuffer handle present, deleting");
|
||||
glDeleteFramebuffersEXT(1, &_fbos[i]);
|
||||
_fbos[i] = 0;
|
||||
}
|
||||
|
||||
debugLog("frameBuffer handle present, deleting");
|
||||
glDeleteFramebuffersEXT(1, &g_frameBuffer);
|
||||
g_frameBuffer = 0;
|
||||
}
|
||||
for(size_t i = 0; i < Countof(_texs); ++i)
|
||||
if (_texs[i])
|
||||
{
|
||||
debugLog("delete framebuffer texture");
|
||||
glDeleteTextures(1, &_texs[i]);
|
||||
_texs[i] = 0;
|
||||
}
|
||||
|
||||
if (g_dynamicTextureID)
|
||||
{
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
|
||||
debugLog("dynamic texture ID handle present, deleting");
|
||||
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");
|
||||
}
|
||||
|
||||
void FrameBuffer::reloadDevice()
|
||||
{
|
||||
if(!_numpages)
|
||||
return;
|
||||
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);
|
||||
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);
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
|
||||
assert(inited && s_stackpos && isOnTop(this));
|
||||
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);
|
||||
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
|
||||
assert(inited && s_stackpos);
|
||||
|
||||
_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"
|
||||
|
||||
class FrameBufferCapture;
|
||||
struct RenderState;
|
||||
|
||||
|
||||
class FrameBuffer
|
||||
{
|
||||
friend class FrameBufferCapture;
|
||||
public:
|
||||
FrameBuffer();
|
||||
~FrameBuffer();
|
||||
bool init(int width, int height, bool fitToScreen=false);
|
||||
bool init(int width, int height, unsigned pages);
|
||||
bool isInited() const { return inited; }
|
||||
void startCapture() const;
|
||||
void endCapture() const;
|
||||
void bindTexture() const;
|
||||
unsigned getTextureID(unsigned page) const;
|
||||
void bindTexture(unsigned page) const;
|
||||
int getTexWidth() const { return texw; }
|
||||
int getTexHeight() const { return texh; }
|
||||
float getWidthP() const;
|
||||
float getHeightP() const;
|
||||
bool getCurrentPage() const;
|
||||
|
||||
void unloadDevice();
|
||||
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:
|
||||
void _bind(unsigned page) const;
|
||||
|
||||
unsigned _fbos[8];
|
||||
unsigned _texs[8];
|
||||
|
||||
int _w, _h;
|
||||
bool _fitToScreen;
|
||||
unsigned g_frameBuffer;
|
||||
unsigned g_depthRenderBuffer;
|
||||
unsigned g_dynamicTextureID;
|
||||
mutable unsigned _curpage; // 0 if not currently bound
|
||||
unsigned _numpages, _numfbos;
|
||||
int texw, texh;
|
||||
int viewportW, viewportH;
|
||||
bool inited;
|
||||
};
|
||||
|
||||
|
|
|
@ -98,22 +98,13 @@ PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL;
|
|||
PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
|
||||
|
||||
// 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;
|
||||
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
|
||||
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
|
||||
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
|
||||
PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
|
||||
|
||||
// ARB_vertex_buffer_object
|
||||
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
|
||||
|
@ -124,6 +115,8 @@ PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
|
|||
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
|
||||
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
|
||||
|
||||
PFNGLCOPYIMAGESUBDATAEXTPROC glCopyImageSubDataEXT = NULL;
|
||||
|
||||
// extern
|
||||
unsigned g_dbg_numRenderCalls = 0;
|
||||
bool g_has_GL_GENERATE_MIPMAP = false;
|
||||
|
@ -182,22 +175,16 @@ bool lookup_all_glsyms()
|
|||
debugLog(os.str());
|
||||
}
|
||||
// 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");
|
||||
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)SDL_GL_GetProcAddress("glBindFramebufferEXT");
|
||||
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
|
||||
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)SDL_GL_GetProcAddress("glGenFramebuffersEXT");
|
||||
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
|
||||
glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture1DEXT");
|
||||
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
|
||||
glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)SDL_GL_GetProcAddress("glFramebufferTexture3DEXT");
|
||||
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
|
||||
glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT");
|
||||
glDrawBuffersARB = NULL;//(PFNGLDRAWBUFFERSARBPROC)SDL_GL_GetProcAddress("glDrawBuffersARB");
|
||||
|
||||
// GL 4.3+, but maybe available as an extension
|
||||
glCopyImageSubDataEXT = (PFNGLCOPYIMAGESUBDATAEXTPROC)SDL_GL_GetProcAddress("glCopyImageSubDataEXT");
|
||||
|
||||
// shaders
|
||||
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
|
||||
// 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;
|
||||
glBindFramebufferEXT = NULL;
|
||||
glDeleteFramebuffersEXT = NULL;
|
||||
glGenFramebuffersEXT = NULL;
|
||||
glCheckFramebufferStatusEXT = NULL;
|
||||
glFramebufferTexture1DEXT = NULL;
|
||||
glFramebufferTexture2DEXT = NULL;
|
||||
glFramebufferTexture3DEXT = NULL;
|
||||
glFramebufferRenderbufferEXT = NULL;
|
||||
glGetFramebufferAttachmentParameterivEXT = NULL;
|
||||
glDrawBuffersARB = NULL;
|
||||
|
||||
glCreateProgramObjectARB = 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,glVertex2f,(GLfloat x, GLfloat y),(x,y),)
|
||||
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...
|
||||
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 /* 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_
|
||||
#error windows.h was included! euuugh!
|
||||
#endif
|
||||
|
@ -86,22 +90,13 @@ extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
|
|||
extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
|
||||
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 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
|
||||
extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
|
||||
extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
|
||||
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
|
||||
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
|
||||
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
|
||||
|
||||
extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
|
||||
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
|
||||
|
@ -111,4 +106,6 @@ extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
|
|||
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
|
||||
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
|
||||
|
||||
extern PFNGLCOPYIMAGESUBDATAEXTPROC glCopyImageSubDataEXT;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,6 +37,8 @@ RenderObjectLayer::RenderObjectLayer()
|
|||
renderObjects[i] = 0;
|
||||
objectCount = 0;
|
||||
firstFreeIdx = 0;
|
||||
preRender = NULL;
|
||||
postRender = NULL;
|
||||
}
|
||||
|
||||
RenderObjectLayer::~RenderObjectLayer()
|
||||
|
@ -251,8 +253,10 @@ void RenderObjectLayer::render(const RenderState& rs) const
|
|||
{
|
||||
assert(rs.pass == RenderObject::RENDER_ALL);
|
||||
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);
|
||||
while( (ro = *rlist++) );
|
||||
proc += toRender.size() - 1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -81,11 +81,12 @@ void ScreenTransition::reloadDevice()
|
|||
void ScreenTransition::capture()
|
||||
{
|
||||
assert(screen_texture);
|
||||
core->render();
|
||||
core->renderExternal();
|
||||
|
||||
if (screen_texture)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D,screen_texture);
|
||||
glReadBuffer(GL_BACK);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, windowWidth, windowHeight);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue