New shader for the blur effect, the old one is ineffecient and difficult to maintain.

This commit is contained in:
vision 2014-06-11 14:54:14 +08:00
parent 14ea582fbc
commit e2c75c1f11
3 changed files with 59 additions and 158 deletions

View File

@ -421,22 +421,14 @@ class SpriteBlur : public Sprite
{
public:
~SpriteBlur();
void setBlurSize(float f);
void setBlurRadius(float radius);
bool initWithTexture(Texture2D* texture, const Rect& rect);
void initGLProgram();
static SpriteBlur* create(const char *pszFileName);
protected:
int _blurRadius;
Vec2 _pixelSize;
int _samplingRadius;
//gaussian = cons * exp( (dx*dx + dy*dy) * scale);
float _scale;
float _cons;
float _weightSum;
float _blurRadius;
};
SpriteBlur::~SpriteBlur()
@ -472,14 +464,7 @@ bool SpriteBlur::initWithTexture(Texture2D* texture, const Rect& rect)
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
#endif
auto s = getTexture()->getContentSizeInPixels();
_pixelSize = Vec2(1/s.width, 1/s.height);
_samplingRadius = 0;
this->initGLProgram();
getGLProgramState()->setUniformVec2("onePixelSize", _pixelSize);
initGLProgram();
return true;
}
@ -495,43 +480,16 @@ void SpriteBlur::initGLProgram()
auto glProgramState = GLProgramState::getOrCreateWithGLProgram(program);
setGLProgramState(glProgramState);
auto size = getTexture()->getContentSizeInPixels();
getGLProgramState()->setUniformVec2("resolution", size);
getGLProgramState()->setUniformFloat("blurRadius", _blurRadius);
}
void SpriteBlur::setBlurSize(float f)
void SpriteBlur::setBlurRadius(float radius)
{
if(_blurRadius == (int)f)
return;
_blurRadius = (int)f;
_samplingRadius = _blurRadius;
if (_samplingRadius > 10)
{
_samplingRadius = 10;
}
if (_blurRadius > 0)
{
float sigma = _blurRadius / 2.0f;
_scale = -0.5f / (sigma * sigma);
_cons = -1.0f * _scale / 3.141592f;
_weightSum = -_cons;
float weight;
int squareX;
for(int dx = 0; dx <= _samplingRadius; ++dx)
{
squareX = dx * dx;
weight = _cons * exp(squareX * _scale);
_weightSum += 2.0 * weight;
for (int dy = 1; dy <= _samplingRadius; ++dy)
{
weight = _cons * exp((squareX + dy * dy) * _scale);
_weightSum += 4.0 * weight;
}
}
}
log("_blurRadius:%d",_blurRadius);
getGLProgramState()->setUniformVec4("gaussianCoefficient", Vec4(_samplingRadius, _scale, _cons, _weightSum));
_blurRadius = radius;
getGLProgramState()->setUniformFloat("blurRadius", _blurRadius);
}
// ShaderBlur
@ -597,7 +555,7 @@ bool ShaderBlur::init()
void ShaderBlur::sliderAction(Ref* sender, Control::EventType controlEvent)
{
ControlSlider* slider = (ControlSlider*)sender;
_blurSprite->setBlurSize(slider->getValue());
_blurSprite->setBlurRadius(slider->getValue());
}
// ShaderRetroEffect

View File

@ -249,80 +249,33 @@ class EffectBlur : public Effect
{
public:
CREATE_FUNC(EffectBlur);
virtual void setTarget(EffectSprite *sprite) override;
void setGaussian(float value);
void setCustomUniforms();
void setBlurSize(float f);
void setBlurRadius(float radius);
protected:
bool init(float blurSize=3.0);
int _blurRadius;
Vec2 _pixelSize;
int _samplingRadius;
float _scale;
float _cons;
float _weightSum;
bool init(float blurRadius = 10.0f);
float _blurRadius;
};
void EffectBlur::setTarget(EffectSprite *sprite)
{
Size s = sprite->getTexture()->getContentSizeInPixels();
_pixelSize = Vec2(1/s.width, 1/s.height);
_glprogramstate->setUniformVec2("onePixelSize", _pixelSize);
Size size = sprite->getTexture()->getContentSizeInPixels();
_glprogramstate->setUniformVec2("resolution", size);
_glprogramstate->setUniformFloat("blurRadius", _blurRadius);
}
bool EffectBlur::init(float blurSize)
bool EffectBlur::init(float blurRadius)
{
initGLProgramState("Shaders/example_Blur.fsh");
auto s = Size(100,100);
_blurRadius = 0;
_pixelSize = Vec2(1/s.width, 1/s.height);
_samplingRadius = 0;
setBlurSize(blurSize);
_glprogramstate->setUniformVec2("onePixelSize", _pixelSize);
_glprogramstate->setUniformVec4("gaussianCoefficient", Vec4(_samplingRadius, _scale, _cons, _weightSum));
_blurRadius = blurRadius;
return true;
}
void EffectBlur::setBlurSize(float f)
void EffectBlur::setBlurRadius(float radius)
{
if(_blurRadius == (int)f)
return;
_blurRadius = (int)f;
_samplingRadius = _blurRadius;
if (_samplingRadius > 10)
{
_samplingRadius = 10;
}
if (_blurRadius > 0)
{
float sigma = _blurRadius / 2.0f;
_scale = -0.5f / (sigma * sigma);
_cons = -1.0f * _scale / 3.141592f;
_weightSum = -_cons;
float weight;
int squareX;
for(int dx = 0; dx <= _samplingRadius; ++dx)
{
squareX = dx * dx;
weight = _cons * exp(squareX * _scale);
_weightSum += 2.0 * weight;
for (int dy = 1; dy <= _samplingRadius; ++dy)
{
weight = _cons * exp((squareX + dy * dy) * _scale);
_weightSum += 4.0 * weight;
}
}
}
_blurRadius = radius;
}
// Outline

View File

@ -1,5 +1,3 @@
// Shader taken from: http://webglsamples.googlecode.com/hg/electricflower/electricflower.html
#ifdef GL_ES
precision mediump float;
#endif
@ -7,50 +5,42 @@ precision mediump float;
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec4 gaussianCoefficient;
uniform vec2 onePixelSize;
uniform vec2 resolution;
uniform float blurRadius;
void main() {
if(gaussianCoefficient.x > 0.0) {
vec4 sum = vec4(0.0);
vec2 offset;
float weight;
float squareX;
for(float dx = 0.0; dx <= gaussianCoefficient.x; dx += 1.0) {
squareX = dx * dx;
weight = gaussianCoefficient.z * exp(squareX * gaussianCoefficient.y);
offset.x = -dx * onePixelSize.x;
offset.y = 0.0;
sum += texture2D(CC_Texture0, v_texCoord + offset) * weight;
offset.x = dx * onePixelSize.x;
sum += texture2D(CC_Texture0, v_texCoord + offset) * weight;
for(float dy = 1.0; dy <= gaussianCoefficient.x; dy += 1.0) {
weight = gaussianCoefficient.z * exp((squareX + dy * dy) * gaussianCoefficient.y);
offset.x = -dx * onePixelSize.x;
offset.y = -dy * onePixelSize.y;
sum += texture2D(CC_Texture0, v_texCoord + offset) * weight;
offset.y = dy * onePixelSize.y;
sum += texture2D(CC_Texture0, v_texCoord + offset) * weight;
offset.x = dx * onePixelSize.x;
sum += texture2D(CC_Texture0, v_texCoord + offset) * weight;
offset.y = -dy * onePixelSize.y;
sum += texture2D(CC_Texture0, v_texCoord + offset) * weight;
}
}
sum -= texture2D(CC_Texture0, v_texCoord) * gaussianCoefficient.z;
sum /= gaussianCoefficient.w;
gl_FragColor = sum * v_fragmentColor;
}
else {
gl_FragColor = texture2D(CC_Texture0, v_texCoord) * v_fragmentColor;
}
vec3 blur(vec2);
void main(void)
{
vec3 col = blur(v_texCoord);
gl_FragColor = vec4(col, 1.0);
}
vec3 blur(vec2 p)
{
if (blurRadius > 0.0)
{
vec3 col = vec3(0);
vec2 unit = 1.0 / resolution.xy;
float r = blurRadius;
float sampleStep = r / 7.37;
float count = 0.0;
for(float x = -r; x < r; x += sampleStep)
{
for(float y = -r; y < r; y += sampleStep)
{
float weight = (r - abs(x)) * (r - abs(y));
col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)).rgb * weight;
count += weight;
}
}
return col / count;
}
return texture2D(CC_Texture0, p).rgb;
}