You're only calculating the average of the pixels below and above (and left and right) of the current image.
You could visualize it like this: (shown here only in x-direction, but it's the same in y-direction):
Every pixel around the current pixel in each direction and up to a distance of 10 (in your implementation) is used with the same weight (0.1).
While that works for blurring a bit, it's not a great result.
A better filter would be the gaussian-filter or gaussian blur (called so because of the gaussian function it uses):
As you can see, the weights have changed - the further away a pixel is, the less it influences the currrent pixel.
The weights can easily be pre-calculated and you can find many tables on the internet (see the code below for the one I use). Otherwise you'd have to calculate a gauss every frame, which is a waste of GPU power because it's constant anyways.
There's one more optimization step - and an important one, too:
Usually, gaussian blurs use two passes. This means that first, you blurr the whole image in x direction and draw the result to a canvas, then you blurr that in y direction and draw it to the screen.
Here's an example:
(Note: blurSize is not given in pixels, here. Instead it is given in the GPU's screen space, ranging from 0 to 1. So to blur exactly 9 pixels, you need to set blurSize to 9/screenWidth or 9/screenHeigth.)
Edit: Changed code to run in 0.9.0 instead of 0.8.0
Code: Select all
img = love.graphics.newImage("grid.png")
function love.load()
canvas = love.graphics.newCanvas( )
blur1 = love.graphics.newShader [[
vec4 effect(vec4 color, Image texture, vec2 vTexCoord, vec2 pixel_coords)
{
vec4 sum = vec4(0.0);
number blurSize = 0.005;
//number d = distance(vTexCoord, mousePos/screenSize);
//number blurSize = clamp(1/d/screenSize.x, 0, 1.0);
// blur in y (vertical)
// take nine samples, with the distance blurSize between them
sum += texture2D(texture, vec2(vTexCoord.x - 4.0*blurSize, vTexCoord.y)) * 0.05;
sum += texture2D(texture, vec2(vTexCoord.x - 3.0*blurSize, vTexCoord.y)) * 0.09;
sum += texture2D(texture, vec2(vTexCoord.x - 2.0*blurSize, vTexCoord.y)) * 0.12;
sum += texture2D(texture, vec2(vTexCoord.x - blurSize, vTexCoord.y)) * 0.15;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y)) * 0.16;
sum += texture2D(texture, vec2(vTexCoord.x + blurSize, vTexCoord.y)) * 0.15;
sum += texture2D(texture, vec2(vTexCoord.x + 2.0*blurSize, vTexCoord.y)) * 0.12;
sum += texture2D(texture, vec2(vTexCoord.x + 3.0*blurSize, vTexCoord.y)) * 0.09;
sum += texture2D(texture, vec2(vTexCoord.x + 4.0*blurSize, vTexCoord.y)) * 0.05;
return sum;
}
]]
blur2 = love.graphics.newShader [[
vec4 effect(vec4 color, Image texture, vec2 vTexCoord, vec2 pixel_coords)
{
vec4 sum = vec4(0.0);
number blurSize = 0.005;
// blur in y (vertical)
// take nine samples, with the distance blurSize between them
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y - 4.0*blurSize)) * 0.05;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y - 3.0*blurSize)) * 0.09;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y - 2.0*blurSize)) * 0.12;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y- blurSize)) * 0.15;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y)) * 0.16;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y + blurSize)) * 0.15;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y + 2.0*blurSize)) * 0.12;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y + 3.0*blurSize)) * 0.09;
sum += texture2D(texture, vec2(vTexCoord.x, vTexCoord.y + 4.0*blurSize)) * 0.05;
return sum;
}
]]
love.graphics.setBackgroundColor(0,0,0)
end
function love.draw()
love.graphics.setCanvas(canvas)
-- LOOK AT THE PRETTY COLORS!
love.graphics.setShader(blur1)
love.graphics.draw(img, 0, 0)
--love.graphics.rectangle('fill', 10,10, love.graphics.getWidth()-20, love.graphics.getHeight()-20)
love.graphics.setCanvas()
--love.graphics.draw(img, 0, 0)
--love.graphics.draw(canvas, 0, love.graphics.getHeight()/2)
love.graphics.setShader(blur2)
--love.graphics.draw(canvas, love.graphics.getWidth()/2, love.graphics.getHeight()/2)
love.graphics.draw(canvas, 0,0)
end
P.S. I ripped the weights from some online-example which I cannot find any more. Shame on me for not citing it properly.
But the weigths are, I guess, a commonly known fact, since all they really are is evaluations of the gaussian function. Still - bad me.