From a54acce6b77481d4e76651e56207feefbbb13d57 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Tue, 1 Oct 2013 18:10:43 +0200 Subject: [PATCH] Implement Bitmap 'blur' I was a bit confused at first because I thought Enterbrain had actually implemented a full Gaussian blur, but nope, just dumb averaging. --- mkxp.pro | 3 +++ shader/blur.frag | 16 +++++++++++++++ shader/blurH.vert | 19 ++++++++++++++++++ shader/blurV.vert | 19 ++++++++++++++++++ src/bitmap.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++ src/bitmap.h | 4 +++- src/globalstate.cpp | 2 ++ src/globalstate.h | 2 ++ src/shader.cpp | 19 ++++++++++++++++++ src/shader.h | 19 ++++++++++++++++++ 10 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 shader/blur.frag create mode 100644 shader/blurH.vert create mode 100644 shader/blurV.vert diff --git a/mkxp.pro b/mkxp.pro index 9673a6b..97ae314 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -101,10 +101,13 @@ EMBED = shader/transSimple.frag \ shader/simpleColor.frag \ shader/simpleAlpha.frag \ shader/flashMap.frag \ + shader/blur.frag \ shader/simple.vert \ shader/simpleColor.vert \ shader/sprite.vert \ shader/simpleMatrix.vert \ + shader/blurH.vert \ + shader/blurV.vert \ assets/liberation.ttf defineReplace(xxdOutput) { diff --git a/shader/blur.frag b/shader/blur.frag new file mode 100644 index 0000000..0fb7c46 --- /dev/null +++ b/shader/blur.frag @@ -0,0 +1,16 @@ + +uniform sampler2D texture; + +varying vec2 v_texCoord; +varying vec2 v_blurCoord[2]; + +void main() +{ + vec4 frag = vec4(0, 0, 0, 0); + + frag += texture2D(texture, v_texCoord); + frag += texture2D(texture, v_blurCoord[0]); + frag += texture2D(texture, v_blurCoord[1]); + + gl_FragColor = frag / 3.0; +} diff --git a/shader/blurH.vert b/shader/blurH.vert new file mode 100644 index 0000000..cfb87c5 --- /dev/null +++ b/shader/blurH.vert @@ -0,0 +1,19 @@ + +uniform mat4 projMat; + +uniform vec2 texSizeInv; + +attribute vec2 position; +attribute vec2 texCoord; + +varying vec2 v_texCoord; +varying vec2 v_blurCoord[2]; + +void main() +{ + gl_Position = projMat * vec4(position, 0, 1); + + v_texCoord = texCoord * texSizeInv; + v_blurCoord[0] = vec2(texCoord.x-1, texCoord.y) * texSizeInv; + v_blurCoord[1] = vec2(texCoord.x+1, texCoord.y) * texSizeInv; +} diff --git a/shader/blurV.vert b/shader/blurV.vert new file mode 100644 index 0000000..6558d25 --- /dev/null +++ b/shader/blurV.vert @@ -0,0 +1,19 @@ + +uniform mat4 projMat; + +uniform vec2 texSizeInv; + +attribute vec2 position; +attribute vec2 texCoord; + +varying vec2 v_texCoord; +varying vec2 v_blurCoord[2]; + +void main() +{ + gl_Position = projMat * vec4(position, 0, 1); + + v_texCoord = texCoord * texSizeInv; + v_blurCoord[0] = vec2(texCoord.x, texCoord.y-1) * texSizeInv; + v_blurCoord[1] = vec2(texCoord.x, texCoord.y+1) * texSizeInv; +} diff --git a/src/bitmap.cpp b/src/bitmap.cpp index dd11638..d2681e5 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -508,6 +508,53 @@ void Bitmap::clearRect(const IntRect &rect) modified(); } +void Bitmap::blur() +{ + GUARD_DISPOSED; + + GUARD_MEGA; + + flush(); + + Quad &quad = gState->gpQuad(); + FloatRect rect(0, 0, width(), height()); + quad.setTexPosRect(rect, rect); + + TEXFBO auxTex = gState->texPool().request(width(), height()); + + BlurShader &shader = gState->blurShader(); + BlurShader::HPass &pass1 = shader.pass1; + BlurShader::VPass &pass2 = shader.pass2; + + glState.blendMode.pushSet(BlendNone); + glState.viewport.pushSet(IntRect(0, 0, width(), height())); + + TEX::bind(p->tex.tex); + FBO::bind(auxTex.fbo, FBO::Draw); + + pass1.bind(); + pass1.setTexSize(Vec2i(width(), height())); + pass1.applyViewportProj(); + + quad.draw(); + + TEX::bind(auxTex.tex); + FBO::bind(p->tex.fbo, FBO::Draw); + + pass2.bind(); + pass2.setTexSize(Vec2i(width(), height())); + pass2.applyViewportProj(); + + quad.draw(); + + glState.viewport.pop(); + glState.blendMode.pop(); + + gState->texPool().release(auxTex); + + modified(); +} + void Bitmap::radialBlur(int angle, int divisions) { GUARD_DISPOSED; diff --git a/src/bitmap.h b/src/bitmap.h index 1f6822e..bf48edd 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -74,8 +74,10 @@ public: int width, int height); void clearRect(const IntRect &rect); + void blur(); + void radialBlur(int angle, int divisions); -// /* ----- */ + /* ----- */ void clear(); diff --git a/src/globalstate.cpp b/src/globalstate.cpp index 1c247af..8cc1697 100644 --- a/src/globalstate.cpp +++ b/src/globalstate.cpp @@ -76,6 +76,7 @@ struct GlobalStatePrivate TransShader transShader; SimpleTransShader sTransShader; HueShader hueShader; + BlurShader blurShader; BltShader bltShader; TexPool texPool; @@ -196,6 +197,7 @@ GSATT(FlashMapShader&, flashMapShader) GSATT(TransShader&, transShader) GSATT(SimpleTransShader&, sTransShader) GSATT(HueShader&, hueShader) +GSATT(BlurShader&, blurShader) GSATT(BltShader&, bltShader) GSATT(TexPool&, texPool) GSATT(FontPool&, fontPool) diff --git a/src/globalstate.h b/src/globalstate.h index b0e2a4d..ae33b46 100644 --- a/src/globalstate.h +++ b/src/globalstate.h @@ -57,6 +57,7 @@ class BltShader; class TexPool; class FontPool; class Font; +struct BlurShader; struct GlobalIBO; struct Config; struct Vec2i; @@ -94,6 +95,7 @@ struct GlobalState TransShader &transShader(); SimpleTransShader &sTransShader(); HueShader &hueShader(); + BlurShader &blurShader(); BltShader &bltShader(); TexPool &texPool(); diff --git a/src/shader.cpp b/src/shader.cpp index 845bbb4..faefb7d 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -37,10 +37,13 @@ #include "../simpleColor.frag.xxd" #include "../simpleAlpha.frag.xxd" #include "../flashMap.frag.xxd" +#include "../blur.frag.xxd" #include "../simple.vert.xxd" #include "../simpleColor.vert.xxd" #include "../sprite.vert.xxd" #include "../simpleMatrix.vert.xxd" +#include "../blurH.vert.xxd" +#include "../blurV.vert.xxd" #define INIT_SHADER(vert, frag) \ @@ -422,6 +425,22 @@ void HueShader::setInputTexture(TEX::ID tex) } +BlurShader::HPass::HPass() +{ + INIT_SHADER(blurH, blur); + + ShaderBase::init(); +} + +BlurShader::VPass::VPass() +{ + INIT_SHADER(blurV, blur); + + ShaderBase::init(); +} + + + BltShader::BltShader() { INIT_SHADER(simple, bitmapBlit); diff --git a/src/shader.h b/src/shader.h index e5ece70..fe319c2 100644 --- a/src/shader.h +++ b/src/shader.h @@ -210,6 +210,25 @@ private: GLint u_hueAdjust, u_inputTexture; }; +/* Gaussian blur */ +struct BlurShader +{ + class HPass : public ShaderBase + { + public: + HPass(); + }; + + class VPass : public ShaderBase + { + public: + VPass(); + }; + + HPass pass1; + VPass pass2; +}; + /* Bitmap blit */ class BltShader : public ShaderBase {