From 3485199bec073aafcde759b3dc42189afae699f6 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 00:58:32 +0200 Subject: [PATCH 1/4] temp commit - work on shaders --- Aquaria/Avatar.cpp | 32 ------- Aquaria/Game.cpp | 5 - Aquaria/ScriptInterface.cpp | 12 ++- Aquaria/UserSettings.cpp | 8 -- Aquaria/UserSettings.h | 2 - BBGE/AfterEffect.cpp | 186 +++++++++++++----------------------- BBGE/AfterEffect.h | 22 +---- 7 files changed, 75 insertions(+), 192 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index e4b8bad..1abb763 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -5742,38 +5742,6 @@ void Avatar::onUpdate(float dt) } - - // setup shader - if (core->afterEffectManager) - { - - /* - if (!_isUnderWater) - { - core->afterEffectManager->setActiveShader(AS_WASHOUT); - //core->afterEffectManager->setActiveShader(AS_NONE); - } - else - */ - if (dsq->user.video.shader != AS_NONE) - { - core->afterEffectManager->setActiveShader((ActiveShader)dsq->user.video.shader); - } - else - { - if (damageTimer.isActive() && dsq->isShakingCamera()) - { - if (dsq->user.video.blur) - core->afterEffectManager->setActiveShader(AS_BLUR); - } - else - { - core->afterEffectManager->setActiveShader(AS_NONE); - } - - } - } - Entity::onUpdate(dt); if (isEntityDead() && skeletalSprite.getCurrentAnimation()->name != "dead") diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 1f44e86..5f2de4e 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -10719,11 +10719,6 @@ void Game::removeState() elementUpdateList.clear(); - if (core->afterEffectManager) - { - //core->afterEffectManager->blurShader.setMode(0); - core->afterEffectManager->setActiveShader(AS_NONE); - } dsq->setCursor(CURSOR_NORMAL); dsq->darkLayer.toggle(0); dsq->shakeCamera(0,0); diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index f21ded2..0987607 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -3995,6 +3995,8 @@ luaFunc(entity_damage) d.attacker = lua_isuserdata(L, 2) ? entity(L, 2) : NULL; d.damage = lua_tonumber(L, 3); d.damageType = (DamageType)lua_tointeger(L, 4); + d.effectTime = lua_tonumber(L, 5); + d.useTimer = !getBool(L, 6); didDamage = e->damage(d); } luaReturnBool(didDamage); @@ -7779,7 +7781,9 @@ luaFunc(createShader) luaFunc(shader_setAsAfterEffect) { - core->afterEffectManager->scriptShader = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; + int idx = lua_tointeger(L, 2); + if(idx < core->afterEffectManager->scriptShader.size()) + core->afterEffectManager->scriptShader[idx] = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; luaReturnNil(); } @@ -7805,8 +7809,10 @@ luaFunc(shader_delete) { Shader *sh = getShader(L); delete sh; - if(core->afterEffectManager->scriptShader == sh) - core->afterEffectManager->scriptShader = NULL; + size_t sz = core->afterEffectManager->scriptShader.size(); + for(size_t i = 0; i < sz; ++i) + if(core->afterEffectManager->scriptShader[i] == sh) + core->afterEffectManager->scriptShader[i] = NULL; luaReturnNil(); } diff --git a/Aquaria/UserSettings.cpp b/Aquaria/UserSettings.cpp index 49e19f4..32d47e9 100644 --- a/Aquaria/UserSettings.cpp +++ b/Aquaria/UserSettings.cpp @@ -91,12 +91,6 @@ void UserSettings::save() TiXmlElement xml_video("Video"); { - TiXmlElement xml_shader("Shader"); - { - xml_shader.SetAttribute("num", video.shader); - } - xml_video.InsertEndChild(xml_shader); - TiXmlElement xml_blur("Blur"); { xml_blur.SetAttribute("on", video.blur); @@ -413,8 +407,6 @@ void UserSettings::load(bool doApply, const std::string &overrideFile) TiXmlElement *xml_video = doc.FirstChildElement("Video"); if (xml_video) { - readInt(xml_video, "Shader", "num", &video.shader); - readInt(xml_video, "Blur", "on", &video.blur); readInt(xml_video, "NoteEffects", "on", &video.noteEffects); diff --git a/Aquaria/UserSettings.h b/Aquaria/UserSettings.h index 1e31763..1c4607e 100644 --- a/Aquaria/UserSettings.h +++ b/Aquaria/UserSettings.h @@ -100,7 +100,6 @@ public: numParticles = 2048; parallaxOn0 = parallaxOn1 = parallaxOn2 = 1; saveSlotScreens = 1; - shader = 0; blur = 1; noteEffects = 0; fpsSmoothing = 30; @@ -115,7 +114,6 @@ public: displaylists = 0; worldMapRevealMethod = 0; } - int shader; int blur; int noteEffects; int fpsSmoothing; diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 5e7a091..474c22c 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -32,10 +32,9 @@ Effect::Effect() AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) { active = false; - activeShader = AS_NONE; numEffects = 0; bRenderGridPoints = true; - scriptShader = 0; + scriptShader.resize(10, 0); screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); @@ -44,46 +43,11 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) this->yDivs = 0; drawGrid = 0; - -#ifdef BBGE_BUILD_OPENGL - this->xDivs = xDivs; this->yDivs = yDivs; - //cameraPointer = nCameraPointer; - //Asssuming the resolutions values are > 256 and < 2048 - //Set the texture heights and widths - if (core->frameBuffer.isInited()) - { - textureWidth = core->frameBuffer.getWidth(); - textureHeight = core->frameBuffer.getHeight(); - } - else - { - if (screenWidth <= 512) - textureWidth = 512; - else if (screenWidth <= 1024) - textureWidth = 1024; - else - textureWidth = 2048; - if (screenHeight <= 512) - textureHeight = 512; - else if (screenHeight <= 1024) - textureHeight = 1024; - else - textureHeight = 2048; - } - - //create our texture - glGenTextures(1,&texture); - glBindTexture(GL_TEXTURE_2D,texture); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, 3, textureWidth, textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - -#endif - //BuildMip(); + reloadDevice(); if (xDivs != 0 && yDivs != 0) { @@ -99,14 +63,6 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) void AfterEffectManager::loadShaders() { - /* - blurShader.load("data/shaders/stan.vert", "data/shaders/blur.frag"); - bwShader.load("data/shaders/stan.vert", "data/shaders/bw.frag"); - washoutShader.load("data/shaders/stan.vert", "data/shaders/washout.frag"); - //motionBlurShader.load("data/shaders/stan.vert", "data/shaders/hoblur.frag"); - motionBlurShader.load("data/shaders/stan.vert", "data/shaders/blur.frag"); - glowShader.load("data/shaders/stan.vert", "data/shaders/glow.frag"); - */ } AfterEffectManager::~AfterEffectManager() @@ -191,29 +147,6 @@ void AfterEffectManager::destroyEffect(int id) openSpots.push(id); } -void AfterEffectManager::capture() -{ - /* -#ifdef BBGE_BUILD_OPENGL - glBindTexture(GL_TEXTURE_2D,texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight); -#endif - */ - if (core->frameBuffer.isInited()) - { - core->frameBuffer.endCapture(); - //core->enable2D(core->pixelScale); - } - else - { -#ifdef BBGE_BUILD_OPENGL - glBindTexture(GL_TEXTURE_2D,texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight); -#endif - } -//glDisable(GL_TEXTURE_2D); - -} void AfterEffectManager::render() { #ifdef BBGE_BUILD_OPENGL @@ -225,7 +158,7 @@ void AfterEffectManager::render() glDisable (GL_ALPHA_TEST); glDisable(GL_BLEND); - capture(); + core->frameBuffer.endCapture(); glTranslatef(core->cameraPos.x, core->cameraPos.y, 0); glScalef(core->invGlobalScale, core->invGlobalScale,0); /* @@ -241,48 +174,33 @@ void AfterEffectManager::render() #endif } -void AfterEffectManager::setActiveShader(ActiveShader as) -{ - activeShader = as; -} - - void AfterEffectManager::renderGrid() { #ifdef BBGE_BUILD_OPENGL - //glBindTexture(GL_TEXTURE_2D, texture); + + + int shadersOn = 0; + int firstShader = -1; + int lastShader = -1; + for (size_t i = 0; i < scriptShader.size(); ++i) + { + if(scriptShader[i]) + { + ++shadersOn; + if(firstShader < 0) + firstShader = i; + lastShader = i; + } + } + if (core->frameBuffer.isInited()) core->frameBuffer.bindTexture(); - else - glBindTexture(GL_TEXTURE_2D, texture); - - - //bwShader.bind(); Shader *activeShader=0; if (core->frameBuffer.isInited()) { - switch(this->activeShader) - { - case AS_BLUR: - activeShader = &blurShader; - break; - case AS_BW: - activeShader = &bwShader; - break; - case AS_WASHOUT: - activeShader = &washoutShader; - break; - case AS_MOTIONBLUR: - activeShader = &motionBlurShader; - break; - case AS_GLOW: - activeShader = &glowShader; - break; - } - - if(scriptShader) - activeShader = scriptShader; + if(scriptShader.size() && scriptShader[0]) + activeShader = scriptShader[0]; } @@ -359,6 +277,40 @@ void AfterEffectManager::renderGrid() } } + if (activeShader) + activeShader->unbind(); + + float width2 = float(vw)/2; + float height2 = float(vh)/2; + + /* + for(size_t i = 1; i < scriptShader.size(); ++i) + { + if(scriptShader[i]) + { + if (core->frameBuffer.isInited()) + core->frameBuffer.startCapture(); + + scriptShader[i]->bind(); + scriptShader[i]->setInt("tex", 0); + glBegin(GL_QUADS); + glTexCoord2d(0.0f, 0.0f); + glVertex3f(-width2, height2, 0.0f); + glTexCoord2d(percentX, 0.0f); + glVertex3f( width2, height2, 0.0f); + glTexCoord2d(percentX, percentY); + glVertex3f( width2, -height2, 0.0f); + glTexCoord2d(0.0f, percentY); + glVertex3f(-width2, -height2, 0.0f); + glEnd(); + scriptShader[i]->unbind(); + + capture(); + } + } + */ + + // uncomment to render grid points /* glBindTexture(GL_TEXTURE_2D, 0); @@ -394,9 +346,6 @@ void AfterEffectManager::renderGrid() //glDisable(GL_TEXTURE_2D); RenderObject::lastTextureApplied = 0; glBindTexture(GL_TEXTURE_2D, 0); - - if (activeShader) - activeShader->unbind(); //bwShader.unbind(); //glActiveTextureARB(GL_TEXTURE0_ARB); @@ -427,8 +376,7 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { - if (texture) - glDeleteTextures(1,&texture); + backupBuffer.unloadDevice(); } void AfterEffectManager::reloadDevice() @@ -443,22 +391,16 @@ void AfterEffectManager::reloadDevice() } else { - if (screenWidth <= 1024) - textureWidth = 1024; - else - textureWidth = 2048; - if (screenHeight <= 1024) - textureHeight = 1024; - else - textureHeight = 2048; + textureWidth = screenWidth; + sizePowerOf2Texture(textureWidth); + textureHeight = screenHeight; + sizePowerOf2Texture(textureHeight); } - //create our texture - glGenTextures(1,&texture); - glBindTexture(GL_TEXTURE_2D,texture); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, 3, textureWidth, textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + if(backupBuffer.isInited()) + backupBuffer.reloadDevice(); + else + backupBuffer.init(-1, -1, true); } void AfterEffectManager::addEffect(Effect *e) diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index bfe70f7..c43a11d 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -72,16 +72,6 @@ public: float time; }; -enum ActiveShader -{ - AS_NONE = 0, - AS_BLUR , - AS_BW , - AS_WASHOUT , - AS_MOTIONBLUR , - AS_GLOW -}; - class AfterEffectManager { public: @@ -96,7 +86,6 @@ public: void resetGrid(); - void capture(); void render(); void renderGrid(); void renderGridPoints(); @@ -111,12 +100,6 @@ public: bool active; - void setActiveShader(ActiveShader as); - -#ifdef BBGE_BUILD_OPENGL - GLuint texture; -#endif - bool bRenderGridPoints; int numEffects; @@ -124,12 +107,11 @@ public: int screenWidth, screenHeight; int textureWidth, textureHeight; - Shader blurShader, bwShader, washoutShader, motionBlurShader, glowShader; - Shader *scriptShader; + std::vector scriptShader; Vector ** drawGrid; - ActiveShader activeShader; + FrameBuffer backupBuffer; }; From 836de140936f1140255e0e86147e4a6800fe0446 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 02:38:49 +0200 Subject: [PATCH 2/4] Implement multi-pass postprocessing shader. This allows attaching multiple shader programs, processing the entire screen as texture. Chaining shaders works, each shader will use the output of the previous shader as input. --- BBGE/AfterEffect.cpp | 161 +++++++++++++++++++++++-------------------- BBGE/AfterEffect.h | 1 + BBGE/Shader.cpp | 7 ++ 3 files changed, 96 insertions(+), 73 deletions(-) diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 474c22c..85f5cc8 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -63,6 +63,28 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) void AfterEffectManager::loadShaders() { + deleteShaders(); + + Shader *sh = new Shader(); + sh->load("data/shaders/test.vert", "data/shaders/test.frag"); + if(sh->isLoaded()) + scriptShader[0] = sh; + else + delete sh; + + sh = new Shader(); + sh->load("data/shaders/test2.vert", "data/shaders/test2.frag"); + if(sh->isLoaded()) + scriptShader[1] = sh; + else + delete sh; + + sh = new Shader(); + sh->load("data/shaders/test3.vert", "data/shaders/test3.frag"); + if(sh->isLoaded()) + scriptShader[2] = sh; + else + delete sh; } AfterEffectManager::~AfterEffectManager() @@ -77,6 +99,7 @@ AfterEffectManager::~AfterEffectManager() delete[] drawGrid; } deleteEffects(); + deleteShaders(); } void AfterEffectManager::deleteEffects() @@ -94,6 +117,18 @@ void AfterEffectManager::deleteEffects() openSpots.pop(); } +void AfterEffectManager::deleteShaders() +{ + for(size_t i = 0; i < scriptShader.size(); ++i) + { + if(scriptShader[i]) + { + delete scriptShader[i]; + scriptShader[i] = 0; + } + } +} + void AfterEffectManager::clear() { deleteEffects(); @@ -149,24 +184,18 @@ void AfterEffectManager::destroyEffect(int id) void AfterEffectManager::render() { + assert(core->frameBuffer.isInited()); + #ifdef BBGE_BUILD_OPENGL glPushMatrix(); - //glDisable(GL_BLEND); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDisable (GL_ALPHA_TEST); glDisable(GL_BLEND); core->frameBuffer.endCapture(); glTranslatef(core->cameraPos.x, core->cameraPos.y, 0); glScalef(core->invGlobalScale, core->invGlobalScale,0); - /* - static float angle; - angle += 0.03f; - */ - //glRotatef(angle, 0, 0, 1); - //glColor4f(1,1,1,0.75); + glColor4f(1,1,1,1); renderGrid(); //renderGridPoints(); @@ -178,78 +207,45 @@ void AfterEffectManager::renderGrid() { #ifdef BBGE_BUILD_OPENGL - - int shadersOn = 0; int firstShader = -1; int lastShader = -1; + Shader *activeShader = 0; for (size_t i = 0; i < scriptShader.size(); ++i) { if(scriptShader[i]) { - ++shadersOn; if(firstShader < 0) + { firstShader = i; + activeShader = scriptShader[i]; + } lastShader = i; } } - if (core->frameBuffer.isInited()) - core->frameBuffer.bindTexture(); - - Shader *activeShader=0; - if (core->frameBuffer.isInited()) - { - if(scriptShader.size() && scriptShader[0]) - activeShader = scriptShader[0]; - - } - - if (activeShader) - { - //while(glGetError() != GL_NO_ERROR) {} - - activeShader->bind(); - - activeShader->setInt("tex", 0); - } - screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); - /* - float percentX, percentY; - percentX = 1; - percentY = 0.5; - */ - - /* - percentX = (float)textureWidth/(float)screenWidth; - percentY = (float)textureHeight/(float)screenHeight; - */ - float percentX, percentY; percentX = (float)screenWidth/(float)textureWidth; percentY = (float)screenHeight/(float)textureHeight; - - /* - if (screenWidth <= textureWidth) - { - percentX = (float)screenWidth/(float)textureWidth; - percentY = (float)screenHeight/(float)textureHeight; - } - else - { - percentY = 10; - } - */ - - int vw = core->getVirtualWidth(); int vh = core->getVirtualHeight(); int offx = -core->getVirtualOffX(); int offy = -core->getVirtualOffY(); + core->frameBuffer.bindTexture(); + + if(activeShader) + { + activeShader->bind(); + activeShader->setInt("tex", 0); + + if(firstShader != lastShader) + backupBuffer.startCapture(); + } + //float div = xDivs; for (int i = 0; i < (xDivs-1); i++) { @@ -283,32 +279,48 @@ void AfterEffectManager::renderGrid() float width2 = float(vw)/2; float height2 = float(vh)/2; - /* - for(size_t i = 1; i < scriptShader.size(); ++i) + + if(firstShader != lastShader) { - if(scriptShader[i]) + // From here on: secondary shader passes. + // We just outputted to the backup buffer... + FrameBuffer *fbIn = &core->frameBuffer; + FrameBuffer *fbOut = &backupBuffer; + + + for(int i = firstShader + 1; i <= lastShader; ++i) { - if (core->frameBuffer.isInited()) - core->frameBuffer.startCapture(); + activeShader = scriptShader[i]; + if(!activeShader) + continue; + + // Swap and exchange framebuffers. The old output buffer serves as texture input for the other one + fbOut->endCapture(); + std::swap(fbIn, fbOut); + fbIn->bindTexture(); + + // If this is the last pass, do not render to a frame buffer again + if(i != lastShader) + fbOut->startCapture(); + + activeShader->bind(); + activeShader->setInt("tex", 0); - scriptShader[i]->bind(); - scriptShader[i]->setInt("tex", 0); + // note that offx, offy are negative here! glBegin(GL_QUADS); glTexCoord2d(0.0f, 0.0f); - glVertex3f(-width2, height2, 0.0f); + glVertex3f(offx, vh+offy, 0.0f); glTexCoord2d(percentX, 0.0f); - glVertex3f( width2, height2, 0.0f); + glVertex3f( vw+offx, vh+offy, 0.0f); glTexCoord2d(percentX, percentY); - glVertex3f( width2, -height2, 0.0f); + glVertex3f( vw+offx, offy, 0.0f); glTexCoord2d(0.0f, percentY); - glVertex3f(-width2, -height2, 0.0f); + glVertex3f(offx, offy, 0.0f); glEnd(); - scriptShader[i]->unbind(); - - capture(); + + activeShader->unbind(); } } - */ // uncomment to render grid points @@ -377,6 +389,7 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { backupBuffer.unloadDevice(); + deleteShaders(); } void AfterEffectManager::reloadDevice() @@ -401,6 +414,8 @@ void AfterEffectManager::reloadDevice() backupBuffer.reloadDevice(); else backupBuffer.init(-1, -1, true); + + loadShaders(); } void AfterEffectManager::addEffect(Effect *e) diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index c43a11d..1de7063 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -91,6 +91,7 @@ public: void renderGridPoints(); void loadShaders(); + void deleteShaders(); void unloadDevice(); void reloadDevice(); diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index d29707e..faed2a3 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -192,6 +192,13 @@ unsigned int Shader::_compileShader(int type, const char *src, char *errbuf, siz #ifdef BBGE_BUILD_SHADERS GLint compiled = 0; GLhandleARB handle = glCreateShaderObjectARB(type); + if(!handle) + { + std::ostringstream os; + os << "Failed to create shader object of type " << type; + debugLog(os.str()); + return 0; + } glShaderSourceARB( handle, 1, &src, NULL ); glCompileShaderARB( handle); From 486e8f92ad4e29c0639b4d6ecf1a70ad8db1260a Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 03:00:20 +0200 Subject: [PATCH 3/4] Make the dark layer affected by postprocessing shaders. This has the side effect that elements on the dark layer will now properly wiggle when affected by water ripples. Before this patch, the dark layer was always drawn above the postprocessed screen content, unaffected. --- BBGE/Core.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/BBGE/Core.cpp b/BBGE/Core.cpp index 3bb0f1e..9f68f9f 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -3852,10 +3852,6 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail) int i = renderObjectLayerOrder[c]; if (i == -1) continue; if ((startLayer != -1 && endLayer != -1) && (i < startLayer || i > endLayer)) continue; - if (afterEffectManager && afterEffectManager->active && i == afterEffectManagerLayer) - { - afterEffectManager->render(); - } if (i == postProcessingFx.layer) { @@ -3885,6 +3881,11 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail) } } + if (afterEffectManager && afterEffectManager->active && i == afterEffectManagerLayer) + { + afterEffectManager->render(); + } + RenderObjectLayer *r = &renderObjectLayers[i]; RenderObject::rlayer = r; if (r->visible) From 6962a3e3ab59c2f1b44519a5b10ce53097b0ed2d Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 04:11:11 +0200 Subject: [PATCH 4/4] Improvements to shader API; use handles instead of raw pointers. --- Aquaria/ScriptInterface.cpp | 75 ++++++++++++----------- BBGE/AfterEffect.cpp | 118 +++++++++++++++++++++++++++--------- BBGE/AfterEffect.h | 16 ++++- BBGE/Shader.cpp | 1 - BBGE/Shader.h | 2 +- 5 files changed, 145 insertions(+), 67 deletions(-) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 0987607..3c2b116 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -378,7 +378,6 @@ static void compile_time_assertions() compile_assert(oo(Path) == oo(Avatar)); compile_assert(oo(Path) == oo(BaseText)); compile_assert(oo(Path) == oo(PauseQuad)); - compile_assert(oo(Path) == oo(Shader)); #undef oo } #endif @@ -7750,6 +7749,7 @@ luaFunc(text_setWidth) luaFunc(loadShader) { + int handle = 0; const char *vertRaw = getCString(L, 1); const char *fragRaw = getCString(L, 2); std::string vert, frag; @@ -7757,62 +7757,68 @@ luaFunc(loadShader) findFile_helper(vertRaw, vert); if(fragRaw) findFile_helper(fragRaw, frag); - Shader *sh = new Shader(); - sh->load(vert, frag); - if(!sh->isLoaded()) - { - delete sh; - sh = NULL; - } - luaReturnPtr(sh); + + if(core->afterEffectManager) + handle = core->afterEffectManager->loadShaderFile(vert.c_str(), frag.c_str()); + + luaReturnInt(handle); } luaFunc(createShader) { - Shader *sh = new Shader(); - sh->loadSrc(getCString(L, 1), getCString(L, 2)); - if(!sh->isLoaded()) - { - delete sh; - sh = NULL; - } - luaReturnPtr(sh); + int handle = 0; + if(core->afterEffectManager) + handle = core->afterEffectManager->loadShaderSrc(getCString(L, 1), getCString(L, 2)); + luaReturnInt(handle); } luaFunc(shader_setAsAfterEffect) { - int idx = lua_tointeger(L, 2); - if(idx < core->afterEffectManager->scriptShader.size()) - core->afterEffectManager->scriptShader[idx] = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; + int handle = lua_tointeger(L, 1); + int pos = lua_tointeger(L, 2); + bool done = false; + + if(core->afterEffectManager) + done = core->afterEffectManager->setShaderPipelinePos(handle, pos); + + luaReturnBool(done); +} + +luaFunc(shader_setNumAfterEffects) +{ + if(core->afterEffectManager) + core->afterEffectManager->setShaderPipelineSize(lua_tointeger(L, 1)); luaReturnNil(); } luaFunc(shader_setInt) { - Shader *sh = getShader(L, 1); - const char *name = getCString(L, 2); - if(sh && name) - sh->setInt(name, lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5), lua_tointeger(L, 6)); + if(core->afterEffectManager) + { + Shader *sh = core->afterEffectManager->getShaderPtr(lua_tointeger(L, 1)); + const char *name = getCString(L, 2); + if(sh && name) + sh->setInt(name, lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5), lua_tointeger(L, 6)); + } luaReturnNil(); } luaFunc(shader_setFloat) { - Shader *sh = getShader(L, 1); - const char *name = getCString(L, 2); - if(sh && name) - sh->setFloat(name, lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6)); + if(core->afterEffectManager) + { + Shader *sh = core->afterEffectManager->getShaderPtr(lua_tointeger(L, 1)); + const char *name = getCString(L, 2); + if(sh && name) + sh->setFloat(name, lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6)); + } luaReturnNil(); } luaFunc(shader_delete) { - Shader *sh = getShader(L); - delete sh; - size_t sz = core->afterEffectManager->scriptShader.size(); - for(size_t i = 0; i < sz; ++i) - if(core->afterEffectManager->scriptShader[i] == sh) - core->afterEffectManager->scriptShader[i] = NULL; + if(core->afterEffectManager) + core->afterEffectManager->unloadShader(lua_tointeger(L, 1)); luaReturnNil(); } @@ -8693,6 +8699,7 @@ static const struct { luaRegister(loadShader), luaRegister(createShader), luaRegister(shader_setAsAfterEffect), + luaRegister(shader_setNumAfterEffects), luaRegister(shader_setFloat), luaRegister(shader_setInt), luaRegister(shader_delete), diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 85f5cc8..938d535 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -34,7 +34,7 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) active = false; numEffects = 0; bRenderGridPoints = true; - scriptShader.resize(10, 0); + shaderPipeline.resize(10, 0); screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); @@ -65,26 +65,7 @@ void AfterEffectManager::loadShaders() { deleteShaders(); - Shader *sh = new Shader(); - sh->load("data/shaders/test.vert", "data/shaders/test.frag"); - if(sh->isLoaded()) - scriptShader[0] = sh; - else - delete sh; - - sh = new Shader(); - sh->load("data/shaders/test2.vert", "data/shaders/test2.frag"); - if(sh->isLoaded()) - scriptShader[1] = sh; - else - delete sh; - - sh = new Shader(); - sh->load("data/shaders/test3.vert", "data/shaders/test3.frag"); - if(sh->isLoaded()) - scriptShader[2] = sh; - else - delete sh; + // ...Load shaders here... } AfterEffectManager::~AfterEffectManager() @@ -119,12 +100,15 @@ void AfterEffectManager::deleteEffects() void AfterEffectManager::deleteShaders() { - for(size_t i = 0; i < scriptShader.size(); ++i) + for(size_t i = 0; i < shaderPipeline.size(); ++i) + shaderPipeline[i] = 0; + + for(size_t i = 0; i < loadedShaders.size(); ++i) { - if(scriptShader[i]) + if(loadedShaders[i]) { - delete scriptShader[i]; - scriptShader[i] = 0; + delete loadedShaders[i]; + loadedShaders[i] = 0; } } } @@ -210,14 +194,14 @@ void AfterEffectManager::renderGrid() int firstShader = -1; int lastShader = -1; Shader *activeShader = 0; - for (size_t i = 0; i < scriptShader.size(); ++i) + for (size_t i = 0; i < shaderPipeline.size(); ++i) { - if(scriptShader[i]) + if(shaderPipeline[i]) { if(firstShader < 0) { firstShader = i; - activeShader = scriptShader[i]; + activeShader = shaderPipeline[i]; } lastShader = i; } @@ -290,7 +274,7 @@ void AfterEffectManager::renderGrid() for(int i = firstShader + 1; i <= lastShader; ++i) { - activeShader = scriptShader[i]; + activeShader = shaderPipeline[i]; if(!activeShader) continue; @@ -567,3 +551,79 @@ void RippleEffect::update(float dt, Vector ** drawGrid, int xDivs, int yDivs) } } } + +int AfterEffectManager::loadShaderFile(const char *vert, const char *frag) +{ + Shader *sh = new Shader(); + sh->load(vert, frag); + if(!sh->isLoaded()) + { + delete sh; + return 0; + } + return _insertShader(sh); +} + +int AfterEffectManager::loadShaderSrc(const char *vert, const char *frag) +{ + Shader *sh = new Shader(); + sh->loadSrc(vert, frag); + if(!sh->isLoaded()) + { + delete sh; + return 0; + } + return _insertShader(sh); +} + +Shader *AfterEffectManager::getShaderPtr(int handle) +{ + size_t idx = handle - 1; + return idx < loadedShaders.size() ? loadedShaders[idx] : 0; +} + +void AfterEffectManager::setShaderPipelineSize(size_t size) +{ + shaderPipeline.resize(size, 0); +} + +bool AfterEffectManager::setShaderPipelinePos(int handle, size_t pos) +{ + if(pos < shaderPipeline.size()) + { + shaderPipeline[pos] = getShaderPtr(handle); + return true; + } + return false; +} + +// returns handle (= index + 1) +int AfterEffectManager::_insertShader(Shader *sh) +{ + for(size_t i = 0; i < loadedShaders.size(); ++i) + { + if(!loadedShaders[i]) + { + loadedShaders[i] = sh; + return i+1; + } + } + loadedShaders.push_back(sh); + return loadedShaders.size(); +} + +void AfterEffectManager::unloadShader(int handle) +{ + Shader *sh = getShaderPtr(handle); + if(!sh) + return; + + for(size_t i = 0; i < shaderPipeline.size(); ++i) + if(shaderPipeline[i] == sh) + shaderPipeline[i] = 0; + + size_t idx = handle - 1; + loadedShaders[idx] = 0; + delete sh; +} + diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index 1de7063..90c7d9f 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -108,11 +108,23 @@ public: int screenWidth, screenHeight; int textureWidth, textureHeight; - std::vector scriptShader; + Vector ** drawGrid; - Vector ** drawGrid; + // returns handle > 0 on success + int loadShaderFile(const char *vert, const char *frag); + int loadShaderSrc(const char *vert, const char *frag); + Shader *getShaderPtr(int handle); + void setShaderPipelineSize(size_t size); + bool setShaderPipelinePos(int handle, size_t pos); + void unloadShader(int handle); +protected: + int _insertShader(Shader *sh); + + std::vector shaderPipeline; // Shaders are applied in this order. Can contain the same pointer more than once. + std::vector loadedShaders; FrameBuffer backupBuffer; + }; diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index faed2a3..c6468bc 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -131,7 +131,6 @@ end: Shader::Shader() { - addType(SCO_SHADER); numUniforms = -1; uniformsDirty = false; diff --git a/BBGE/Shader.h b/BBGE/Shader.h index 3d21050..2b978e7 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "Base.h" #include "ScriptObject.h" -class Shader : public ScriptObject +class Shader { public: Shader();