From 427806ac235ebf64278657a035f0ec1e5c5e3e62 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Sat, 2 Apr 2016 18:56:07 +0600 Subject: [PATCH] Rewrite PostProcessor: do not modify original buffer, use special frame buffer instead. Fixed dual heroes: incorrect colors in menu #926 --- src/FrameBuffer.cpp | 32 +++++++------- src/PostProcessor.cpp | 97 ++++++++++++++++++++++++++++++++++--------- src/PostProcessor.h | 12 +++--- 3 files changed, 98 insertions(+), 43 deletions(-) diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 2b7cb8ce..d11fae34 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -835,15 +835,15 @@ void FrameBufferList::renderBuffer(u32 _address) dstCoord[0] += 1; // workaround for Adreno's issue with glBindFramebuffer; #endif // GLESX - PostProcessor::get().doGammaCorrection(pBuffer); - PostProcessor::get().doBlur(pBuffer); + FrameBuffer * pFilteredBuffer = PostProcessor::get().doBlur(PostProcessor::get().doGammaCorrection(pBuffer)); + pBuffer->m_postProcessed = pFilteredBuffer->m_postProcessed; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //glDrawBuffer( GL_BACK ); float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; render.clearColorBuffer(clearColor); GLenum filter = GL_LINEAR; - if (config.video.multisampling != 0) { + if (config.video.multisampling != 0 && pFilteredBuffer == pBuffer) { if (X0 > 0 || dstPartHeight > 0 || (srcCoord[2] - srcCoord[0]) != (dstCoord[2] - dstCoord[0]) || (srcCoord[3] - srcCoord[1]) != (dstCoord[3] - dstCoord[1])) { @@ -855,7 +855,7 @@ void FrameBufferList::renderBuffer(u32 _address) filter = GL_NEAREST; } } else - glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, pFilteredBuffer->m_FBO); // glDisable(GL_SCISSOR_TEST) does not affect glBlitFramebuffer, at least on AMD glScissor(0, 0, ogl.getScreenWidth(), ogl.getScreenHeight() + ogl.getHeightOffset()); @@ -902,8 +902,8 @@ void FrameBufferList::renderBuffer(u32 _address) OGLVideo & ogl = video(); ogl.getRender().updateScissor(pBuffer); - PostProcessor::get().doGammaCorrection(pBuffer); - PostProcessor::get().doBlur(pBuffer); + FrameBuffer * pFilteredBuffer = PostProcessor::get().doBlur(PostProcessor::get().doGammaCorrection(pBuffer)); + pBuffer->m_postProcessed = pFilteredBuffer->m_postProcessed; ogl.getRender().dropRenderState(); gSP.changed = gDP.changed = 0; @@ -913,16 +913,16 @@ void FrameBufferList::renderBuffer(u32 _address) glDisable( GL_CULL_FACE ); glDisable( GL_POLYGON_OFFSET_FILL ); - const u32 width = pBuffer->m_width; - const u32 height = pBuffer->m_height; + const u32 width = pFilteredBuffer->m_width; + const u32 height = pFilteredBuffer->m_height; - pBuffer->m_pTexture->scaleS = ogl.getScaleX() / (float)pBuffer->m_pTexture->realWidth; - pBuffer->m_pTexture->scaleT = ogl.getScaleY() / (float)pBuffer->m_pTexture->realHeight; - pBuffer->m_pTexture->shiftScaleS = 1.0f; - pBuffer->m_pTexture->shiftScaleT = 1.0f; - pBuffer->m_pTexture->offsetS = 0; - pBuffer->m_pTexture->offsetT = (float)height; - textureCache().activateTexture(0, pBuffer->m_pTexture); + pFilteredBuffer->m_pTexture->scaleS = ogl.getScaleX() / (float)pFilteredBuffer->m_pTexture->realWidth; + pFilteredBuffer->m_pTexture->scaleT = ogl.getScaleY() / (float)pFilteredBuffer->m_pTexture->realHeight; + pFilteredBuffer->m_pTexture->shiftScaleS = 1.0f; + pFilteredBuffer->m_pTexture->shiftScaleT = 1.0f; + pFilteredBuffer->m_pTexture->offsetS = 0; + pFilteredBuffer->m_pTexture->offsetT = (float)height; + textureCache().activateTexture(0, pFilteredBuffer->m_pTexture); gSP.textureTile[0]->fuls = gSP.textureTile[0]->fult = 0.0f; gSP.textureTile[0]->shifts = gSP.textureTile[0]->shiftt = 0; currentCombiner()->updateTextureInfo(true); @@ -932,7 +932,7 @@ void FrameBufferList::renderBuffer(u32 _address) glBindFramebuffer(GL_FRAMEBUFFER, 0); - OGLRender::TexturedRectParams params(0.0f, 0.0f, width, height, 0.0f, 0.0f, width - 1.0f, height - 1.0f, false, false, pBuffer); + OGLRender::TexturedRectParams params(0.0f, 0.0f, width, height, 0.0f, 0.0f, width - 1.0f, height - 1.0f, false, false, pFilteredBuffer); ogl.getRender().drawTexturedRect(params); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); diff --git a/src/PostProcessor.cpp b/src/PostProcessor.cpp index baeb39f5..315d8eb8 100644 --- a/src/PostProcessor.cpp +++ b/src/PostProcessor.cpp @@ -285,9 +285,8 @@ GLuint _createShaderProgram(const char * _strVertex, const char * _strFragment) } static -CachedTexture * _createTexture() +void _initTexture(CachedTexture * pTexture) { - CachedTexture * pTexture = textureCache().addFrameBufferTexture(); pTexture->format = G_IM_FMT_RGBA; pTexture->clampS = 1; pTexture->clampT = 1; @@ -306,25 +305,58 @@ CachedTexture * _createTexture() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); +} + +static +CachedTexture * _createTexture() +{ + CachedTexture * pTexture = textureCache().addFrameBufferTexture(); + _initTexture(pTexture); return pTexture; } +static +void _initFBO(GLuint _FBO, CachedTexture * _pTexture) +{ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _FBO); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _pTexture->glName, 0); + assert(checkFBO()); +} + static GLuint _createFBO(CachedTexture * _pTexture) { GLuint FBO; glGenFramebuffers(1, &FBO); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _pTexture->glName, 0); - assert(checkFBO()); + _initFBO(FBO, _pTexture); return FBO; } +PostProcessor::PostProcessor() + : m_extractBloomProgram(0) + , m_seperableBlurProgram(0) + , m_glowProgram(0) + , m_bloomProgram(0) + , m_copyProgram(0) + , m_gammaCorrectionProgram(0) + , m_pResultBuffer(nullptr) + , m_FBO_original(0) + , m_FBO_glowMap(0) + , m_FBO_blur(0) + , m_pTextureOriginal(nullptr) + , m_pTextureGlowMap(nullptr) + , m_pTextureBlur(nullptr) +{} + void PostProcessor::_initCommon() { m_pTextureOriginal = _createTexture(); m_FBO_original = _createFBO(m_pTextureOriginal); + m_pResultBuffer = new FrameBuffer(); + _initTexture(m_pResultBuffer->m_pTexture); + _initFBO(m_pResultBuffer->m_FBO, m_pResultBuffer->m_pTexture); + #ifdef GLES2 m_copyProgram = _createShaderProgram(vertexShader, copyShader); glUseProgram(m_copyProgram); @@ -424,6 +456,10 @@ void PostProcessor::_destroyCommon() if (m_pTextureOriginal != nullptr) textureCache().removeFrameBufferTexture(m_pTextureOriginal); + m_pTextureOriginal = nullptr; + + delete m_pResultBuffer; + m_pResultBuffer = nullptr; } void PostProcessor::_destroyGammaCorrection() @@ -438,12 +474,15 @@ void PostProcessor::_destroyBlur() if (m_extractBloomProgram != 0) glDeleteProgram(m_extractBloomProgram); m_extractBloomProgram = 0; + if (m_seperableBlurProgram != 0) glDeleteProgram(m_seperableBlurProgram); m_seperableBlurProgram = 0; + if (m_glowProgram != 0) glDeleteProgram(m_glowProgram); m_glowProgram = 0; + if (m_bloomProgram != 0) glDeleteProgram(m_bloomProgram); m_bloomProgram = 0; @@ -451,14 +490,15 @@ void PostProcessor::_destroyBlur() if (m_FBO_glowMap != 0) glDeleteFramebuffers(1, &m_FBO_glowMap); m_FBO_glowMap = 0; + if (m_FBO_blur != 0) glDeleteFramebuffers(1, &m_FBO_blur); m_FBO_blur = 0; - m_pTextureOriginal = nullptr; if (m_pTextureGlowMap != nullptr) textureCache().removeFrameBufferTexture(m_pTextureGlowMap); m_pTextureGlowMap = nullptr; + if (m_pTextureBlur != nullptr) textureCache().removeFrameBufferTexture(m_pTextureBlur); m_pTextureBlur = nullptr; @@ -510,6 +550,11 @@ void PostProcessor::_preDraw(FrameBuffer * _pBuffer) OGLVideo & ogl = video(); #ifdef GLES2 + m_pResultBuffer->m_width = _pBuffer->m_width; + m_pResultBuffer->m_height = _pBuffer->m_height; + m_pResultBuffer->m_scaleX = _pBuffer->m_scaleX; + m_pResultBuffer->m_scaleY = _pBuffer->m_scaleY; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO_original); textureCache().activateTexture(0, _pBuffer->m_pTexture); glUseProgram(m_copyProgram); @@ -534,13 +579,18 @@ void PostProcessor::_postDraw() glUseProgram(0); } -void PostProcessor::doBlur(FrameBuffer * _pBuffer) +FrameBuffer * PostProcessor::doBlur(FrameBuffer * _pBuffer) { - if (config.bloomFilter.enable == 0) - return; + if (_pBuffer == nullptr) + return nullptr; - if (_pBuffer == nullptr || (_pBuffer->m_postProcessed&PostProcessor::postEffectBlur) == PostProcessor::postEffectBlur) - return; + m_pResultBuffer->m_postProcessed = _pBuffer->m_postProcessed; + + if (config.bloomFilter.enable == 0) + return _pBuffer; + + if ((_pBuffer->m_postProcessed&PostProcessor::postEffectBlur) == PostProcessor::postEffectBlur) + return m_pResultBuffer; _pBuffer->m_postProcessed |= PostProcessor::postEffectBlur; @@ -564,33 +614,40 @@ void PostProcessor::doBlur(FrameBuffer * _pBuffer) glUniform1i(loc, 1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pResultBuffer->m_FBO); textureCache().activateTexture(0, m_pTextureOriginal); textureCache().activateTexture(1, m_pTextureGlowMap); glUseProgram(m_glowProgram); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); _postDraw(); + m_pResultBuffer->m_postProcessed = _pBuffer->m_postProcessed; + return m_pResultBuffer; } - - -void PostProcessor::doGammaCorrection(FrameBuffer * _pBuffer) +FrameBuffer * PostProcessor::doGammaCorrection(FrameBuffer * _pBuffer) { - if (((*REG.VI_STATUS & 8)|config.gammaCorrection.force) == 0) - return; + if (_pBuffer == nullptr) + return nullptr; - if (_pBuffer == nullptr || (_pBuffer->m_postProcessed&PostProcessor::postEffectGammaCorrection) == PostProcessor::postEffectGammaCorrection) - return; + m_pResultBuffer->m_postProcessed = _pBuffer->m_postProcessed; + + if (((*REG.VI_STATUS & 8) | config.gammaCorrection.force) == 0) + return _pBuffer; + + if ((_pBuffer->m_postProcessed&PostProcessor::postEffectGammaCorrection) == PostProcessor::postEffectGammaCorrection) + return m_pResultBuffer; _pBuffer->m_postProcessed |= PostProcessor::postEffectGammaCorrection; _preDraw(_pBuffer); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pResultBuffer->m_FBO); textureCache().activateTexture(0, m_pTextureOriginal); glUseProgram(m_gammaCorrectionProgram); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); _postDraw(); + m_pResultBuffer->m_postProcessed = _pBuffer->m_postProcessed; + return m_pResultBuffer; } diff --git a/src/PostProcessor.h b/src/PostProcessor.h index ea641ae5..4a558f3d 100644 --- a/src/PostProcessor.h +++ b/src/PostProcessor.h @@ -10,8 +10,8 @@ public: void init(); void destroy(); - void doBlur(FrameBuffer * _pBuffer); - void doGammaCorrection(FrameBuffer * _pBuffer); + FrameBuffer * doBlur(FrameBuffer * _pBuffer); + FrameBuffer * doGammaCorrection(FrameBuffer * _pBuffer); static PostProcessor & get(); @@ -19,11 +19,7 @@ public: static const u32 postEffectGammaCorrection = 2U; private: - PostProcessor() : - m_extractBloomProgram(0), m_seperableBlurProgram(0), - m_glowProgram(0), m_bloomProgram(0), m_copyProgram(0), m_gammaCorrectionProgram(0), - m_FBO_original(0), m_FBO_glowMap(0), m_FBO_blur(0), - m_pTextureOriginal(NULL), m_pTextureGlowMap(NULL), m_pTextureBlur(NULL) {} + PostProcessor(); PostProcessor(const PostProcessor & _other); void _initCommon(); void _destroyCommon(); @@ -42,6 +38,8 @@ private: GLuint m_gammaCorrectionProgram; + FrameBuffer * m_pResultBuffer; + GLuint m_FBO_original; GLuint m_FBO_glowMap; GLuint m_FBO_blur;