Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Superficial: an experiment with discard in fragment shaders (Codea 1.5)

edited February 2013 in Code Sharing Posts: 489

The code below illustrates the use of discard in a fragment shader. The creation of the surface mesh takes a few seconds.

image

The code uses the '--#' convention that allows it to be pasted into a new project with the Codea tab structure preserved (by a long touch on 'Add New Project' and then 'Paste Into Project').

The vertex and fragment shaders were developed in the new Shader Lab. Here, they are stored as strings in table Grid to make the code easier to share on the Forum.

--# Main
--
-- Superficial
--

supportedOrientations(LANDSCAPE_ANY)
function setup()
    parameter.boolean("displayFloor", false)
    parameter.integer("angle", 0, 720, 180)
    sx, sy = 500, 500
    local dx, dy = 5, 5
    local xn, yn = math.floor(2 * sx / dx), math.floor(2 * sy / dy)
    local col = {color(127, 127, 0), color(63, 63, 0)}
    local v1 = {}
    local c1 = {}
    local v2 = {}
    local append = table.append
    local vec3 = vec3 -- cache function for speed
    local f = f -- cache function for speed
    for ix = 0, xn - 1 do
        local x = ix * dx
        for iy = 0, yn - 1 do
            local y = iy * dx
            local z00 = f(x, y)
            local z10 = f(x + dx, y)
            local z01 = f(x, y + dy)
            local z11 = f(x + dx, y + dy)
            local tri1 = {
                vec3(x, 0, y),
                vec3(x, 0, y + dy),
                vec3(x + dx, 0, y + dy),
                vec3(x + dx, 0, y + dy),
                vec3(x, 0, y),
                vec3(x + dx, 0, y)
            }
            local c = col[(ix + iy % 2) % 2 + 1]
            local col1 = {c, c, c, c, c, c}
            local tri2 = {
                vec3(x, z00, y),
                vec3(x, z01, y + dy),
                vec3(x + dx, z11, y + dy),
                vec3(x + dx, z11, y + dy),
                vec3(x, z00, y),
                vec3(x + dx, z10, y)
            }
            append(v1, tri1)
            append(c1, col1)
            append(v2, tri2)
        end
    end
    m1 = mesh()
    m1.vertices = v1
    m1.colors = c1
    m2 = mesh()
    m2.vertices = v2
    m2.shader = shader(Grid.vertexShader, Grid.fragmentShader)
    fill(255)
end

local sqrt = math.sqrt
local cos = math.cos
local exp = math.exp
function f(x, y)
    local x1, y1 = x - sx, y - sy
    local r = sqrt(x1 * x1 + y1 * y1)
    local s = cos(r / sx * 8)
    local z = exp(-r / sx) * s * s * 300
    return z
end

function table.append(t1, t2)
    local n = #t1
    for i = 1, #t2 do
        t1[n + i] = t2[i]
    end
end

function draw()
    background(0)
    perspective()
    local a = math.rad(angle)
    camera(1000 * math.cos(a) + sx, 1000, 1000 * math.sin(a) + sy,
        sx, 0, sy, 0, 1, 0)
    if displayFloor then m1:draw() end
    m2:draw()
end

--# ShaderGrid
Grid = {

vertexShader = [[
//
// Vertex shader: Grid
//
uniform mat4 modelViewProjection;
attribute vec4 position;
varying highp vec4 vPos;

void main() {   
    gl_Position = modelViewProjection * position;
    vPos = position;
}
]],

fragmentShader = [[
//
// Grid: Fragment shader
//
precision highp float;
varying vec4 vPos;

void main() {
    const float p = 50.0; // Periodicity of grid
    const float w = 10.0; // Width of grid lines
    const float fade = 0.2 * w; // Anti-aliasing zone width
    const float threshold = 0.05; // Threshold for discard
    const float wMin = fade;
    const float wMax = w - fade;
    
    vec3 d = mod(vPos.xyz, p);
    
    // Set the red channel:
    // if (d.x < w)
    //     r = 1.0;
    // else
    //     r = 0.0;
    float r = d.x < w ? 1.0 : 0.0;
    float g = d.y < w ? 1.0 : 0.0;
    float b = d.z < w ? 1.0 : 0.0;

    // Set the alpha for the red channel:
    // if (d.x < wMin)
    //     ar = d.x / fade;
    // elseif (d.x < wMax)
    //     ar = 1.0;
    // elseif (d.x < w)
    //     ar = 1.0 - (d.x - wMax) / fade;
    // else
    //     ar = 0.0;
    float ar = d.x < wMin ? d.x / fade :
        (d.x < wMax ? 1.0 :
        (d.x < w ? 1.0 - (d.x - wMax) / fade : 0.0));
    float ag = d.y < wMin ? d.y / fade :
        (d.y < wMax ? 1.0 :
        (d.y < w ? 1.0 - (d.y - wMax) / fade : 0.0));
    float ab = d.z < wMin ? d.z / fade :
        (d.z < wMax ? 1.0 :
        (d.z < w ? 1.0 - (d.z - wMax) / fade : 0.0));
    
    float a = 1.0 - (1.0 - ar) * (1.0 - ag) * (1.0 - ab);
    if (a < threshold) discard;
    //Set the output color to the texture color
    gl_FragColor = vec4(r * ar, g * ag, b * ab, a);
}
]]
}
Tagged:

Comments

Sign In or Register to comment.