Wiki
Clone wikiCore / BricksShader
Bricks Shader
Introduction
'Bricks' is an example shader provided in Codea's 'Patterns' Shaders Pack.
Vertex shader
The vertex shader simply passes the 'attribute' variables position
and color
on to the accompanying fragment shader as 'varying' variables vPos
and vColor
:
void main()
{
...
vColor = color;
vPos = position;
...
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 an opaque colour constructed from color
(of type vec3
) and a final component (the alpha channel) of 1.0
:
gl_FragColor = vec4(color, 1.0);
color
is calculated based on the 'varying' variable vPos
and four 'uniform' variables: brickColor
, mortarColor
, brickSize
and brickPct
.
Only the xyz
components of vPos
(of type vec4
) are used. Those components are scaled by the corresponding components of brickSize
(of type vec3
) and the result held in variable position
:
position = vPos.xyz / brickSize.xyz; // Equivalent to: vPos.xyz / brickSize;
Only the rgb
components of the two 'colour' variables are used.
color
is also tinted by multiplying it, component-by-component, by the rgb
components of vColor
.
color = mix(mortarColor.rgb, brickColor.rgb, useBrick.x * useBrick.y * useBrick.z);
color *= vColor.rgb;
The built-in mix()
function (see Section 8.3 'Common Functions' of the GLSL ES specification) is used to set color
to either the mortarColor
or the brickColor
. The brickColor
is selected only if all of the components of useBrick
are 1.0
.
useBrick
is set using the built-in step()
function (see Section 8.3 'Common Functions' of the GLSL ES specification):
position = fract(position);
useBrick = step(position, brickPct.xyz);
Example of use
The code below is a simple example of the use of the shader:
supportedOrientations(LANDSCAPE_LEFT)
function setup()
if deviceMetrics().platformName == "iPad 1G" then
print("This code needs a gyroscope."..
" An iPad 1 does not have one.")
else
print("Rotate the Viewer about the stack of bricks.")
end
local size = math.min(HEIGHT, WIDTH) / 2
d = size * 3
m = cubeMesh(size)
dirz = vec3(0, 0, 1)
diry = vec3(0, 1, 0)
dirx = vec3(1, 0, 0)
fill(255)
end
function draw()
background(0)
perspective()
local mat = matrix()
local dxa = RotationRate.x
local dya = RotationRate.y
local dza = RotationRate.z
mat = mat:rotate(dza, dirz.x, dirz.y, dirz.z)
mat = mat:rotate(dya, diry.x, diry.y, diry.z)
mat = mat:rotate(dxa, dirx.x, dirx.y, dirx.z)
dirx = mult(mat, dirx)
diry = mult(mat, diry)
dirz = mult(mat, dirz)
local x = dirz.x * d
local y = dirz.y * d
local z = dirz.z * d
camera(x, y, z, 0, 0, 0, diry.x, diry.y, diry.z)
m:draw()
end
function cubeMesh(size)
local v = {}
for i = 0, 7 do
local x = (i % 2) * 2 - 1
local y = (math.floor(i / 2) % 2) * 2 - 1
local z = (math.floor(i / 4) % 2) * 2 - 1
v[i] = vec3(x, y, z) * size / 2
end
local ver = {}
for v1 = 1, 3 do
local v2 = v1 * 3 % 7
local v3 = 7 - v1
local v4 = 7 - v2
local vt = {v[0], v[v1], v[v2],
v[0], v[v3], v[v4],
v[7], v[v2], v[v1],
v[7], v[v4], v[v3]}
for i = 1, #vt do
ver[(v1 - 1) * #vt + i] = vt[i]
end
end
local m = mesh()
m.vertices = ver
m:setColors(255, 255, 255)
m.shader = shader("Patterns:Bricks")
m.shader.brickColor = color(187, 57, 41, 255)
m.shader.mortarColor = color(150, 131, 131, 255)
m.shader.brickSize = vec3(225, 75, 112)
m.shader.brickPct = vec3(215/225, 65/75, 102/112)
return m
end
function mult(mat, vec)
local v1 = mat[1] * vec.x + mat[5] * vec.y + mat[9] * vec.z
local v2 = mat[2] * vec.x + mat[6] * vec.y + mat[10] * vec.z
local v3 = mat[3] * vec.x + mat[7] * vec.y + mat[11] * vec.z
return vec3(v1, v2, v3)
end
Updated