When investigating co-ordinate systems used by the app I noticed variables interpolated between the vertex and fragment shader have an unusual implicit conversion.
Let w and h denote the built-in Codea variables WIDTH
and HEIGHT
, respectively.
gl_Position
is (-w, -h) at the bottom left corner, (w, h) at the top right corner, and (0, 0) in the centre. I expected this to be (-1.0, -1.0), (1.0, 1.0), and (0.0, 0.0) (a.k.a. normalised device co-ordinates) respectively, but it’s not a concern - it’s quite sensible.
The thing I find troubling is that there is an implicit conversion from these ‘semi-window’ co-ordinates to normalised device co-ordinates between the vertex and fragment stages on variables that are not gl_Position
. The implication is that, for example, if I want to interpolate a 100% red vertex in the fragment shader, I have to set the color variable to (w, 0, 0) and, if I want to pass a 100% green vertex to the fragment shader, I have to set the color variable to (0, h, 0) so that the conversion maps the color values to unit range. This is totally surprising and unintuitive!
The following program demonstrates:
Main
function setup()
displayMode(STANDARD)
parameter.number("x", 1.0, 1024.0)
m = mesh()
m.shader = shader("Project:Foo")
m:addRect(0.5 * WIDTH, 0.5 * HEIGHT, WIDTH, HEIGHT)
print(WIDTH, HEIGHT)
local vertices = m:buffer("position")
for i = 1, 4 do
print(vertices[i])
end
end
function draw()
background(40, 40, 50)
m.shader.uColorScale = x
m.shader.uDimensions = vec2(WIDTH, HEIGHT)
m:draw()
end
Vertex shader
attribute vec4 position;
uniform vec2 uDimensions;
uniform highp float uColorScale;
varying lowp vec4 vColor;
void main()
{
vColor = uColorScale * vec4(position.x / uDimensions.x, position.y / uDimensions.y, 0.0, 1.0);
gl_Position = position;
}
Fragment shader
precision highp float;
uniform vec2 uDimensions;
varying lowp vec4 vColor;
void main()
{
if (vColor.x > 1.0 || vColor.y > 1.0) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
} else {
gl_FragColor = vColor;
}
}
See attached screenshots for output.
I’d like to know whether there is a way around this that doesn’t involve scaling by the window size.