Buffers are a new feature in Codea version 1.5 that allow per-vertex data to be associated with a mesh and passed to a shader as an attribute. Shaders can be used to manipulate the vertices of a mesh, as well as manipulate how pixels are coloured. The code below shows a simple application.
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’).
I believe that, in Codea version 1.5, it is not yet possible to pass a Lua number
directly to a GLSL ES float
attribute using a buffer
. It is, however, possible to pass a Codea vec2
userdata value to a GLSL ES vec2
attribute and this code uses the x
coordinate of two-dimensional vectors to achieve its objective in passing data.
The vertex and fragment shaders were developed in the new Shader Lab. Here, they are stored as strings in table Undulate
to make the code easier to share on the Forum.
--# Main
--
-- Undulate
--
supportedOrientations(LANDSCAPE_ANY)
function setup()
local default = 40
local ti = table.insert -- Cache the function for speed
function reset()
local halfN = n/2 - 0.5
m = mesh()
m.shader = shader(Undulate.vertexShader,
Undulate.fragmentShader)
local dBuffer = m:buffer("d")
dBuffer:resize(n * n * 6)
local ver = {}
local col = {}
local len = math.min(WIDTH, HEIGHT) / n
p = n / 2 * len
for j = 0, n - 1 do
local y1 = j - halfN
local ySqr = y1 * y1
for i = 0, n - 1 do
local x1 = i - halfN
local d = math.sqrt(x1 * x1 + ySqr) * default / n
local x = i * len
local y = j * len
local c = rCol()
ti(ver, vec3(x, y, 0))
ti(ver, vec3(x + len, y, 0))
ti(ver, vec3(x, y + len, 0))
ti(ver, vec3(x, y + len, 0))
ti(ver, vec3(x + len, y, 0))
ti(ver, vec3(x + len, y + len, 0))
for k = 1, 6 do
ti(col, c)
-- Needs to be a vec2 to work in Codea beta 1.5(16)
dBuffer[(i + j * n) * 6 + k] = vec2(d, 0)
end
end
end
m.vertices = ver
m.colors = col
end
parameter.integer("n", 1, 100, default, reset)
end
function draw()
background(0)
perspective()
camera(p, -200, 1000, p, p, 0, 0, 1, 0)
m.shader.t = ElapsedTime * 3
m:draw()
end
function rCol()
return color(
math.random(255),
math.random(255),
math.random(255))
end
--# ShaderUndulate
Undulate = {
vertexShader = [[
//
// Vertex shader: Undulate
//
uniform mat4 modelViewProjection;
uniform float t;
attribute vec4 position;
attribute vec4 color;
attribute vec2 d; // Needs to be vec2 to work in Codea 1.5(16)
varying lowp vec4 vColor;
void main() {
float z = 50.0 * sin(d.x + t);
vec4 p = vec4(position.x, position.y, z, position.w);
vColor = color;
gl_Position = modelViewProjection * p;
}
]],
fragmentShader = [[
//
// Fragment shader: Undulate
//
varying lowp vec4 vColor;
void main() {
gl_FragColor = vColor;
}
]]
}