right, sorry…
it goes like this: OpenGL uses a 4x4 matrix of numbers to do all the heavy lifting of rotating, translating, and scaling vertices. Every single vertex in your object has to be rotated and translated at least 3 times: you have to put it in the right place in the world, move the world around the camera, and then convert the 3D point to 2D screen coordinates.
The model matrix is what we use to move models around in the world. Every time you use the rotate() or translate() command, you’re manipulating the model matrix.
So what I’m doing is taking advantage of the model matrix to get the relative angle of the object I’m drawing and the light that’s illuminating it.
boxMesh.shader.lightAngle = vec4(0,1,0,0) -- light comes from straight up
rotate(rx,1,0.0) -- this tips the box forward by rx degrees
boxMesh.shader.modelMatrix = modelMatrix() -- tells the shader what the box's orientation is
This saves the current model matrix to the shader. The shader then takes the matrix and uses it to rotate the light angle. I then compare the light and the normal of each vertex. When the normal is exactly the same as the light angle, the face is 100% illuminated. When the normal faces 90 degrees away from the light, the face is dark.
//
// A basic vertex shader
//
//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;
uniform mat4 modelMatrix;
uniform vec4 lightAngle;
//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying highp vec3 vNormal;
void main()
{
//Pass the mesh color to the fragment shader
vColor = color;
vTexCoord = texCoord;
vNormal = normal;
vec3 l = vec3(lightAngle * modelMatrix);
l=normalize(l);
vLightLevel=dot(normal,l);
vColor = vColor * vLightLevel;
vColor.a = 1.0;
//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
notice the modelMatrix and lightAngle variables at the top. You have to set both of those for each mesh in every draw() cycle.
Again, I’ve been away from 3D programming for a while, and I’ve never used shaders for lighting - I’ve always had OpenGL’s built in lighting engine to do the work for me. So this is kind of new to me. There may be a simpler way to do what I’m doing… I’d love if someone showed me how.