Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Radial blur effect class — Gideros Forum

Radial blur effect class

hgy29hgy29 Maintainer
edited November 2017 in Code snippets
Here is a quick lua class to add a fast-but-not-perfect blur effect to any sprite (except stage).
BlurEffect={}
BlurEffect.VS_GL=[[
attribute highp vec3 vVertex;
attribute mediump vec2 vTexCoord;
uniform highp mat4 vMatrix;
varying mediump vec2 fTexCoord;
 
void main() {
  vec4 vertex = vec4(vVertex,1.0);
  gl_Position = vMatrix*vertex;
  fTexCoord=vTexCoord;
}
]]
 
BlurEffect.FS_GL=[[
uniform lowp vec4 fColor;
uniform lowp sampler2D fTexture;
varying mediump vec2 fTexCoord;
uniform mediump vec4 fTexSize;
 
void main() {
 mediump vec4 frag=vec4(0.0,0.0,0.0,0.0); 
 mediump vec2 centerDir=normalize((fTexSize.xy/2.0-fTexCoord)/fTexSize.xy)*fTexSize.zw;
 for (int k=0;k<=5;k++)
	frag=frag+texture2D(fTexture, fTexCoord-centerDir*float(k));
 frag=frag/6.0;
 if (frag.a<=0.0) discard;
 gl_FragColor = frag;
}
]]
 
BlurEffect.Shader=Shader.new(BlurEffect.VS_GL,BlurEffect.FS_GL,Shader.FLAG_FROM_CODE,
{
{name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true},
{name="fColor",type=Shader.CFLOAT4,sys=Shader.SYS_COLOR,vertex=false},
{name="fTexture",type=Shader.CTEXTURE,vertex=false},
{name="fTexSize",type=Shader.CFLOAT4,sys=Shader.SYS_TEXTUREINFO,vertex=false},
},
{
{name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
{name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0},
{name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0},
});
 
local identity=Matrix.new()
function BlurEffect.blur(spr)
	local sm=spr:getMatrix()
	spr:setMatrix(identity)
	local spx,spy,spw,sph=spr:getBounds(spr)
	if spw>=spr._blur_tgt:getWidth() or sph>=spr._blur_tgt:getHeight() then
		spr._blur_tgt=RenderTarget.new(spw,sph,true)
		local p=spr._blur_spr:getParent()
		spr._blur_spr:removeFromParent()
		spr._blur_spr:removeEventListener(Event.ENTER_FRAME,BlurEffect.blur,spr)
		spr._blur_spr=Bitmap.new(spr._blur_tgt)
		p:addChild(spr._blur_spr)
		spr._blur_spr._orig_spr=spr
		spr._blur_spr:setShader(BlurEffect.Shader)
		spr._blur_spr:addEventListener(Event.ENTER_FRAME,BlurEffect.blur,spr)
	end
	spr._blur_spr:setMatrix(sm)
    spr._blur_tgt:clear(0xFFFFFF,0)
	spr._blur_tgt:draw(spr)
	spr:setMatrix(sm)
end
 
function BlurEffect.apply(sprite)
	local spx,spy,spw,sph=sprite:getBounds(sprite)
	sprite._blur_tgt=RenderTarget.new(spw,sph,true)
	local p=sprite:getParent()
	sprite:removeFromParent()
	sprite._blur_spr=Bitmap.new(sprite._blur_tgt)
	p:addChild(sprite._blur_spr)
	sprite._blur_spr._orig_spr=sprite
	sprite._blur_spr:setShader(BlurEffect.Shader)
	sprite._blur_spr:addEventListener(Event.ENTER_FRAME,BlurEffect.blur,sprite)
	return sprite._blur_spr
end
 
function BlurEffect.cancel(sprite)
	if sprite._blur_spr then
		sprite._blur_spr:removeEventListener(Event.ENTER_FRAME,BlurEffect.blur,sprite)
		sprite._blur_tgt=nil
		local p=sprite._blur_spr:getParent()
		p:addChild(sprite)
		sprite._blur_spr:removeFromParent()
		sprite._blur_spr=nil
	end
end
 
function BlurEffect.isApplied(sprite)
	return sprite._blur_spr~=nil
end
UPDATED: 7.11.2017

Usage:
BlurEffect.apply(sprite) -- enable blur on 'sprite'
BlurEffect.cancel(sprite) -- disable blur on 'sprite'
BlueEffect.isApplied(sprite) -- test if blur is active on 'sprite'
+1 -1 (+9 / -0 )Share on Facebook

Comments

  • Hi @hgy29,

    How exactly does that work?
    I either get huge white things(if applied directly a bitmap subsprite) or no image at all if applied to a game sprite.
    Do I need to do something special?
  • hgy29hgy29 Maintainer
    Hi @kussakov,

    The original code would only work for static sprites without any kind of transform. I updated it to take transform changes into account a few minutes ago. Let me know if it works now.

    Likes: keszegh, antix, pie

    +1 -1 (+3 / -0 )Share on Facebook
  • Thanks @hgy29!

    Interesting.
    Now it kind of works, but:

    1. It now kills the app - I get only 1 FPS on windows player(i7 with nvidia GPU) and 5 FPS on Samsung galaxy S8. I have about 12 sprites with a blur. With just one sprite I get about 30-40 FPS.

    2. I can see only 1/4 of the sprite (the lower right quarter). I guess because the images have anchor point 0.5,0.5 or something.
  • Would performance be better if you had all 12 sprites attached to one parent sprite and then ran the shader on that?

    Also could you use maybe a pool of RenderTargets instead of creating them on the fly to improve performance?
  • kussakovkussakov Member
    edited November 2017
    For sure, but that is not what I need.
    I am already doing that using the Bloom example. No decline in fps.
    However, I needed a way to apply this to some sprites only and I wanted to avoid all the trouble of having multiple containers, reordering the containers so that all looks nice, etc.
    The other problem with the bloom example is that I need some kind of dark background on the container(using shape), so having multiple containers will not work well.

    Not sure how to do a pool of RenderTargets...
  • antixantix Member
    edited November 2017
    Ahh okay I see. Managing things in containers is a pain sometimes :D

    There's a thread here about pooled objects...
    http://giderosmobile.com/forum/discussion/6699/enter_frame-and-sprites/p1
    You could just use RenderTarget objects instead of Sprites. Depending on the actual size of your objects however it might chew a lot of texture RAM.
  • hgy29hgy29 Maintainer
    Yes, there is a huge performance impact due to the fact that the sprite needs to be drawn to a rendertarget before the effect can be applied

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • I wonder, are your blurs going to change in real-time on an object? If not you could apply the blur and set the result as the objects texture so only having to do the blur once when the object is created.
  • @antix, that is a good idea. The blur does not change. I will try it. Thanks!

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.