Port over Bitmap 'radial_blur' from old SFML codebase

This implementation is also heaps better than the old
one as it doesn't use a (differently sized) aux texture,
meaning the Bitmap discards its old texture and aquires
one of same size, making reuse through the TexPool a
lot more likely. It also saves on the aux texture blits
and binding switches.

As the setup / resource acquisition far outweighs the
actual rendering cost, operation time is relatively
constant no matter how many divisions are used.
This commit is contained in:
Jonas Kulla 2013-09-04 21:03:59 +02:00
parent 088f0a2a30
commit 9f26ff9fb0
8 changed files with 151 additions and 1 deletions

View File

@ -104,6 +104,7 @@ EMBED = shader/transSimple.frag \
shader/simple.vert \
shader/simpleColor.vert \
shader/sprite.vert \
shader/simpleMatrix.vert \
assets/liberation.ttf
defineReplace(xxdOutput) {

20
shader/simpleMatrix.vert Normal file
View File

@ -0,0 +1,20 @@
uniform mat4 projMat;
uniform mat4 matrix;
uniform vec2 texSizeInv;
attribute vec2 position;
attribute vec2 texCoord;
attribute vec4 color;
varying vec2 v_texCoord;
varying vec4 v_color;
void main()
{
gl_Position = projMat * matrix * vec4(position, 0, 1);
v_texCoord = texCoord * texSizeInv;
v_color = color;
}

View File

@ -31,6 +31,7 @@
#include "gl-util.h"
#include "quad.h"
#include "quadarray.h"
#include "transform.h"
#include "exception.h"
#include "globalstate.h"
@ -507,6 +508,103 @@ void Bitmap::clearRect(const IntRect &rect)
modified();
}
void Bitmap::radialBlur(int angle, int divisions)
{
GUARD_DISPOSED;
GUARD_MEGA;
flush();
angle = clamp<int>(angle, 0, 359);
divisions = clamp<int>(divisions, 2, 100);
const int _width = width();
const int _height = height();
float angleStep = (float) angle / (divisions-1);
float opacity = 1.0f / divisions;
float baseAngle = -((float) angle / 2);
ColorQuadArray qArray;
qArray.resize(5);
QVector<Vertex> &vert = qArray.vertices;
int i = 0;
/* Center */
FloatRect texRect(0, 0, _width, _height);
FloatRect posRect(0, 0, _width, _height);
i += Quad::setTexPosRect(&vert[i*4], texRect, posRect);
/* Upper */
posRect = FloatRect(0, 0, _width, -_height);
i += Quad::setTexPosRect(&vert[i*4], texRect, posRect);
/* Lower */
posRect = FloatRect(0, _height*2, _width, -_height);
i += Quad::setTexPosRect(&vert[i*4], texRect, posRect);
/* Left */
posRect = FloatRect(0, 0, -_width, _height);
i += Quad::setTexPosRect(&vert[i*4], texRect, posRect);
/* Right */
posRect = FloatRect(_width*2, 0, -_width, _height);
i += Quad::setTexPosRect(&vert[i*4], texRect, posRect);
for (int i = 0; i < 4*5; ++i)
vert[i].color = Vec4(1, 1, 1, opacity);
qArray.commit();
TEXFBO newTex = gState->texPool().request(_width, _height);
FBO::bind(newTex.fbo, FBO::Draw);
glState.clearColor.pushSet(Vec4());
glClear(GL_COLOR_BUFFER_BIT);
Transform trans;
trans.setOrigin(Vec2(_width / 2.0f, _height / 2.0f));
trans.setPosition(Vec2(_width / 2.0f, _height / 2.0f));
glState.blendMode.pushSet(BlendAddition);
SimpleMatrixShader &shader = gState->simpleMatrixShader();
shader.bind();
p->bindTexture(shader);
TEX::setSmooth(true);
p->pushSetViewport(shader);
for (int i = 0; i < divisions; i++)
{
trans.setRotation(baseAngle + i*angleStep);
shader.setMatrix(trans.getMatrix());
qArray.draw();
}
p->popViewport();
TEX::setSmooth(false);
glState.blendMode.pop();
glState.clearColor.pop();
gState->texPool().release(p->tex);
p->tex = newTex;
modified();
}
void Bitmap::clear()
{
GUARD_DISPOSED;

View File

@ -74,7 +74,7 @@ public:
int width, int height);
void clearRect(const IntRect &rect);
// void radialBlur(int angle, int divisions);
void radialBlur(int angle, int divisions);
// /* ----- */
void clear();

View File

@ -69,6 +69,7 @@ struct GlobalStatePrivate
SimpleColorShader simpleColorShader;
SimpleAlphaShader simpleAlphaShader;
SimpleSpriteShader simpleSpriteShader;
SimpleMatrixShader simpleMatrixShader;
SpriteShader spriteShader;
PlaneShader planeShader;
FlashMapShader flashMapShader;
@ -188,6 +189,7 @@ GSATT(SimpleShader&, simpleShader)
GSATT(SimpleColorShader&, simpleColorShader)
GSATT(SimpleAlphaShader&, simpleAlphaShader)
GSATT(SimpleSpriteShader&, simpleSpriteShader)
GSATT(SimpleMatrixShader&, simpleMatrixShader)
GSATT(SpriteShader&, spriteShader)
GSATT(PlaneShader&, planeShader)
GSATT(FlashMapShader&, flashMapShader)

View File

@ -46,6 +46,7 @@ class SimpleShader;
class SimpleColorShader;
class SimpleAlphaShader;
class SimpleSpriteShader;
class SimpleMatrixShader;
class SpriteShader;
class PlaneShader;
class FlashMapShader;
@ -86,6 +87,7 @@ struct GlobalState
SimpleColorShader &simpleColorShader();
SimpleAlphaShader &simpleAlphaShader();
SimpleSpriteShader &simpleSpriteShader();
SimpleMatrixShader &simpleMatrixShader();
SpriteShader &spriteShader();
PlaneShader &planeShader();
FlashMapShader &flashMapShader();

View File

@ -40,6 +40,7 @@
#include "../simple.vert.xxd"
#include "../simpleColor.vert.xxd"
#include "../sprite.vert.xxd"
#include "../simpleMatrix.vert.xxd"
#define INIT_SHADER(vert, frag) \
@ -226,6 +227,21 @@ void SimpleSpriteShader::setSpriteMat(const float value[16])
}
SimpleMatrixShader::SimpleMatrixShader()
{
INIT_SHADER(simpleMatrix, simpleAlpha);
ShaderBase::init();
GET_U(matrix);
}
void SimpleMatrixShader::setMatrix(const float value[16])
{
glUniformMatrix4fv(u_matrix, 1, GL_FALSE, value);
}
TransShader::TransShader()
{
INIT_SHADER(simple, trans);

View File

@ -118,6 +118,17 @@ private:
GLint u_spriteMat;
};
class SimpleMatrixShader : public ShaderBase
{
public:
SimpleMatrixShader();
void setMatrix(const float value[16]);
private:
GLint u_matrix;
};
class TransShader : public ShaderBase
{
public: