Wiki

Clone wiki

Core / BlurShader

Back to Built-in Shader Packs


Blur Shader

Introduction

'Blur' is an example shader provided in Codea's 'Filters' Shaders Pack. It performs a box blur on the texture associated with the mesh to which the shader is applied.

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 the gl_FragColor in main() as the product of three factors, vColor (the 'varying' passed on from the vertex shader), conWeight (a 'uniform' float variable) and color (which is calculated):

gl_FragColor = color * conWeight * vColor;

color is calculated as the sum of the colours of nine points sampled from the 'uniform' texture texture (of type sampler2D:

vec4 color = vec4(0.0);
...
for (int i = 0; i < 9; i++)
{
    color += texture2D(texture, current); 
    current.x += conPixel.x;
    if (i == 2 || i == 5) {
        current.x = start.x;
        current.y += conPixel.y; 
    }
}

The variable current holds the point being sampled. The starting point (start) is offset from vTexCoord by -1.5 * conPixel. Consequently, the nine points sampled are (in units of conPixel.x and conPixel.y):

ipointComment
0(-1.5, -1.5)start
1(-0.5, -1.5)Increase current.x
2( 0.5, -1.5)Increase current.x
3(-1.5, -0.5)Reset current.x and increase current.y
4(-0.5, -0.5)Increase current.x
5( 0.5, -0.5)Increase current.x
6(-1.5, 0.5)Reset current.x and increase current.y
7(-0.5, 0.5)Increase current.x
8( 0.5, 0.5)Increase current.x

Example of use

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

function setup()
    local img = readImage("Cargo Bot:Codea Logo")
    w, h = img.width, img.height
    local aspect = h / w
    local imgDim = math.min(w, h)
    local viewerDim = math.min(WIDTH, HEIGHT / aspect)
    myMesh = mesh()
    myMesh:addRect(WIDTH / 2, HEIGHT / 2, viewerDim, viewerDim * aspect)
    myMesh.shader = shader("Filters:Blur")
    myMesh.texture = img
    parameter.boolean("isSmooth", true, onChangeA)
    parameter.boolean("isBlur", true, onChangeB)
    myMesh.shader.conWeight = 1 / 9   
end

function onChangeA()
    if isSmooth then
        smooth()
    else
        noSmooth()
    end
end

function onChangeB()
    if isBlur then
        myMesh.shader.conPixel = vec2(1/w, 1/h)
    else
        myMesh.shader.conPixel = vec2()
    end
end

function draw()
    background(255, 255, 0)
    myMesh:draw()
end

Updated