Wiki

Clone wiki

Core / RadialBlurShader

Back to Built-in Shader Packs


Radial Blur Shader

Introduction

'Radial Blur' is an example shader provided in Codea's 'Filters' Shaders Pack.

Vertex shader

The vertex shader simply passes the 'attribute' variables color and texCoord on to the accompanying fragment shader as 'varying' variables vColor and vTexCoord:

void main()
{
    ...
    vColor = color;
    vTexCoord = texCoord;
    ...
    gl_Position = modelViewProjection * position;
}

gl_Position is a variable that is intended for outputting the vertex position in homogenous co-ordinates (that is, as a vec4 value). All vertex shaders must write a value into that variable. (See Section 7.1 'Vertex Shader Special Variables' of the GLSL ES specification.) Here, the modelViewProjection 4x4 matrix is applied to the vertex's position. modelViewProjection is a 'uniform' mat4 variable supplied automatically by Codea when the shader is used with a mesh. It is the current model matrix * view matrix * projection matrix. position is a vec4 'attribute' variable, also supplied automatically by Codea from the mesh.

Fragment shader

The fragment shader sets gl_FragColor to a mix of two colours, tinted by multiplying the result by vColor. The two colours are col and sum:

lowp vec4 col = texture2D(texture, vTexCoord);
...
gl_FragColor = mix(col, sum, t) * vColor;

sum is calculated as the average of col and ten colours sampled from the texture texture:

mediump vec4 sum = col;
for (int i = 0; i < 10; i++)
{
    sum += texture2D(texture, vTexCoord + dir * samples[i] * sampleDist);
}
sum *= 1.0 / 11.0;

dir is a normalised vec2 from the vTexCoord to the centre of the texture, at vec2(0.5, 0.5):

vec2 dir = 0.5 - vTexCoord.xy;
float dist = sqrt(dir.x * dir.x + dir.y * dir.y);
dir = dir / dist;

The ten points sampled are determined by the array samples[10].

The value of the mixing variable, t, depends on the distance, dist, clamped to the range 0.0 to 1.0:

float t = dist * sampleStrength;
t = clamp(t, 0.0, 1.0);

Example of use

The code below is a simple example of the use of the shader:

function setup()
    myMesh = mesh()
    local img = readImage("Cargo Bot:Startup Screen")
    local w, h = img.width, img.height
    local s = math.min(WIDTH / w, HEIGHT / h)
    myMesh:addRect(WIDTH / 2, HEIGHT / 2, w * s, h * s)
    myMesh.texture = img
    myShader = shader("Filters:Radial Blur")
    parameter.boolean("isOn", true)
    parameter.number("distance", 0.1, 3, 1,
        function () isOn = true end)
    parameter.number("strength", 0, 5, 2,
        function () isOn = true end)
end

function draw()
    background(0)
    if isOn then
        myMesh.shader = myShader
        myMesh.shader.sampleDist = distance
        myMesh.shader.sampleStrength = strength
    else
        myMesh.shader = nil
    end
    myMesh:draw()
end

Updated