Barrel Distortion Shader

I converted a simple barrel distortion shader from Shadertoy for use in Codea. Barrel distortion is commonly used to produce the curved look of a CRT monitor (see the attached image).

EDITED 09-20-17: The shader is now updated and embedded in code which allows you to adjust the distortion amount to produce a barrel or pincushion effect.

-- Barrel Distortion Shader

function setup()
    
    print("Set positive distortion for barrel effect, negative distortion for pincushion effect.")
    print("Adapted from https://www.shadertoy.com/view/lddGDN")
    
    parameter.number("Distortion", -0.1, 0.5, 0.25)
    parameter.boolean("Original", false)
    
    myMesh = mesh()
    local rIdx = myMesh:addRect(0, 0, 0, 0)
    myMesh.texture = "Cargo Bot:Codea Icon"
    meshWidth, meshHeight = spriteSize(myMesh.texture)
    myMesh:setRect(rIdx, 0, 0, meshWidth, meshHeight)
    myMesh.shader = shader(barrelShader.vert, barrelShader.frag)
    myMesh.shader.resolution = 32.0
    myMesh.shader.size = 1.0
    
end

function draw()
    
    background(0)
    
    if Original then
        pushMatrix()
            translate(WIDTH/2, HEIGHT/2)
            sprite(myMesh.texture)
        popMatrix()
    else
        myMesh.shader.distortion = Distortion
        pushMatrix()
            translate(WIDTH/2, HEIGHT/2)
            myMesh:draw()
        popMatrix()
    end
    
end

barrelShader = {
vert = [[
    uniform mat4 modelViewProjection;
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texCoord;

    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;

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

frag = [[    
    // Adapted from https://www.shadertoy.com/view/lddGDN

    precision highp float;

    uniform lowp sampler2D texture;

    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;

    uniform highp float distortion;

    void main()
    {
        //Sample the texture at the interpolated coordinate
        lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
    
        //Set the output color to the texture color
        gl_FragColor = col;
    
        vec2 uv = vTexCoord;
        uv = uv * 2.0 - 1.0;
        float r = uv.x*uv.x + uv.y*uv.y;
        uv *= 1.6 + distortion * r + distortion * r * r;
        uv = 0.5 * (uv * 0.5 + 1.0);
        gl_FragColor = texture2D(texture, uv);
    }
    ]]
}

Nice job. It’s good to have more shader examples for learning how to use them. It’s also a good idea to include the setup and draw functions so it’s ready to run when copied and pasted into a project to see it.

@dave1707 I can add setup & draw to future code posts. I wasn’t sure if it was better to include it or leave it out. Thanks!

@mindless Anytime I show an example of anything, I include everything so whoever looks at it can just copy it, paste it, and then run it. I guess I’m just lazy because I don’t try anyone’s code unless it’s runnable and then I just run it to see what it does and then delete it.

I updated the shader code and included setup() and draw() functions along with some parameters. See the attached screenshot for an example.

Another nice shader example. I like that you added the parameter slider and the option to show the original Sprite.