OK, here is a new version.
Make sure you check out all the parameters especially the texture ones.
-- Cube
function setup()
parameter.number("ambient", 0, 1, 0.1)
parameter.number("diffuse", 0, 1, 1.0)
parameter.number("specular", 0, 1, 1)
parameter.color("lightColor", color(255,255,255,255))
parameter.color("surfaceColor", color(191,41,85,255))
allTextures = {
CAMERA,
"Cargo Bot:Codea Icon",
"Small World:Store Extra Large",
"Small World:Windmill",
"Tyrian Remastered:Boss D",
}
cameraSource(CAMERA_FRONT)
cube = mesh()
--vertices for the corners of the cube (stolen from 3d lab)
local vertices = {
vec3(-0.5, -0.5, 0.5), -- Left bottom front
vec3( 0.5, -0.5, 0.5), -- Right bottom front
vec3( 0.5, 0.5, 0.5), -- Right top front
vec3(-0.5, 0.5, 0.5), -- Left top front
vec3(-0.5, -0.5, -0.5), -- Left bottom back
vec3( 0.5, -0.5, -0.5), -- Right bottom back
vec3( 0.5, 0.5, -0.5), -- Right top back
vec3(-0.5, 0.5, -0.5), -- Left top back
}
-- now construct a cube out of the vertices above
cube.vertices = {
-- Front
vertices[1], vertices[2], vertices[3],
vertices[1], vertices[3], vertices[4],
-- Right
vertices[2], vertices[6], vertices[7],
vertices[2], vertices[7], vertices[3],
-- Back
vertices[6], vertices[5], vertices[8],
vertices[6], vertices[8], vertices[7],
-- Left
vertices[5], vertices[1], vertices[4],
vertices[5], vertices[4], vertices[8],
-- Top
vertices[4], vertices[3], vertices[7],
vertices[4], vertices[7], vertices[8],
-- Bottom
vertices[5], vertices[6], vertices[2],
vertices[5], vertices[2], vertices[1],
}
--now texture it
-- all the unique texture positions needed
local texvertices = { vec2(0,0),
vec2(1,0),
vec2(0,1),
vec2(1,1) }
-- apply the texture coordinates to each triangle
cube.texCoords = {
-- Front
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Right
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Back
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Left
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Top
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Bottom
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
}
--setup vertex normals
createNormalsFromSurfaceNormals()
cube.texture = "Cargo Bot:Codea Icon"
cube.shader = shader(ADSLighting.vertexShader, ADSLighting.fragmentShader)
cube.shader.vLightPosition = vec4(-2,2,-3,1)
cube.shader.vEyePosition = vec4(0,0,-3,1)
cube.shader.useTexture = false
cube.shader.useBumpMap = false
currentModelMatrix = matrix(0.97, 0.15, -0.19, 0.00, -0.09, 0.96, 0.28, 0.00, 0.22, -0.26, 0.94, 0.00, 0.00, 0.00, 0.00, 1.00)
parameter.integer("Texture",0,5,0,changeTexture)
end
function changeTexture()
if Texture == 0 then
cube.shader.useTexture = false
else
cube.shader.useTexture = true
cube.texture = allTextures[Texture]
end
end
function createNormalsFromSurfaceNormals()
--this assumes flat surfaces, and hard edges between triangles (which is good for cubes)
normalBuffer = cube:buffer("normal")
normalBuffer:resize(cube.size)
for i=1, cube.size/3 do
--determine the surfacenormal for the triangle
normal = (cube:vertex(i*3-1) - cube:vertex(i*3-2)):cross(cube:vertex(i*3) - cube:vertex(i*3-2))
normalBuffer[i*3-2] = normal
normalBuffer[i*3-1] = normal
normalBuffer[i*3] = normal
end
end
function draw()
background(40, 40, 50)
camera(0,0,-3,0,0,0)
perspective()
modelMatrix(currentModelMatrix)
--do rotation for touch
if CurrentTouch.state == MOVING then
rotate(CurrentTouch.deltaX,0,1,0)
rotate(CurrentTouch.deltaY,1,0,0)
currentModelMatrix = modelMatrix()
end
cube.shader.mModel = modelMatrix()
cube.shader.mView = viewMatrix()
cube.shader.mProjection = projectionMatrix()
cube.shader.vAmbientMaterial = ambient
cube.shader.vDiffuseMaterial = diffuse
cube.shader.vSpecularMaterial = specular
cube.shader.lightColor = lightColor
cube:setColors(surfaceColor)
cube:draw()
end
ADSLighting = {
vertexShader = [[
//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;
//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;
varying highp vec3 vNormal;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying highp vec4 vPosition;
void main()
{
//Pass the mesh color to the fragment shader
vNormal = normal;
vColor = color;
vTexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
vPosition = position;
//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
//
// A basic fragment shader
//
//Default precision qualifier
precision highp float;
//This represents the current texture on the mesh
uniform lowp sampler2D texture;
uniform lowp sampler2D bumpMap;
uniform bool useTexture;
uniform bool useBumpMap;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;
varying highp vec3 vNormal;
varying lowp vec4 vColor;
varying highp vec4 vPosition;
//****new attributes
// Our Model, View and Projection matrices
// we need them to transform the incoming vertices and for lighting
// calculation
uniform mat4 mModel;
// Position of the "Camera" and the Light
// in Model space
uniform vec4 vEyePosition;
uniform vec4 vLightPosition;
// The Colors of the material
uniform float vAmbientMaterial;
uniform float vDiffuseMaterial;
uniform float vSpecularMaterial;
uniform vec4 lightColor;
// Returns the specular component of the color
vec4 GetSpecularColor(vec3 vVertexNormal, vec4 vVertexPosition)
{
// Transform the Vertex and corresponding Normal into Model space
vec4 vTransformedNormal = mModel * vec4( vVertexNormal, 1 );
vec4 vTransformedVertex = mModel * vVertexPosition;
// Get the directional vector to the light and to the camera
// originating from the vertex position
vec4 vLightDirection = normalize( vLightPosition - vTransformedVertex );
vec4 vCameraDirection = normalize( vEyePosition - vTransformedVertex );
// Calculate the reflection vector between the incoming light and the
// normal (incoming angle = outgoing angle)
// We have to use the invert of the light direction because "reflect"
// expects the incident vector as its first parameter
vec4 vReflection = reflect( -vLightDirection, vTransformedNormal );
// Calculate specular component
// Based on the dot product between the reflection vector and the camera
// direction.
//
// hint: The Dot Product corresponds to the angle between the two vectors
// hint: if the angle is out of range (0 ... 180 degrees) we use 0.0
float spec = pow( max( 0.0, dot( vCameraDirection, vReflection )), 32.0 );
return vec4( lightColor.r * spec, lightColor.g * spec, lightColor.b * spec, 1.0 ) * vSpecularMaterial;
}
// Ambient color component of vertex
vec4 GetAmbientColor(vec4 texCol)
{
vec4 vAmbientColor;
vAmbientColor.xyz = texCol.rgb * lightColor.rgb * vAmbientMaterial;
vAmbientColor.a = 1.0;
return vAmbientColor;
}
// Diffuse Color component of vertex
vec4 GetDiffuseColor(vec3 vVertexNormal, vec4 texCol)
{
// Transform the normal from Object to Model space
// we also normalize the vector just to be sure ...
vec4 vTransformedNormal = normalize( mModel * vec4( vVertexNormal, 1 ));
// Get direction of light in Model space
vec4 vLightDirection = normalize( vLightPosition - vTransformedNormal );
// Calculate Diffuse intensity
float fDiffuseIntensity = max( 0.0, dot( vTransformedNormal, vLightDirection ));
// Calculate resulting Color
vec4 vDiffuseColor;
vDiffuseColor.xyz = texCol.rgb * lightColor.rgb * fDiffuseIntensity * vDiffuseMaterial;
vDiffuseColor.a = 1.0;
return vDiffuseColor;
}
void main()
{
//Sample the texture at the interpolated coordinate
vec3 curNormal;
if (useBumpMap) {
lowp vec4 bump = texture2D( bumpMap, vTexCoord );
if (bump.x == 0.0 && bump.y == 0.0 && bump.z == 0.0) discard;
curNormal = normalize(vec3(bump.x, bump.y, bump.z)*2.0-vec3(1.0,1.0,1.0));
}
else {
curNormal = vNormal;
}
lowp vec4 curCol;
if (useTexture) {
curCol = texture2D( texture, vTexCoord);
if (curCol.a == 0.0) discard;
}
else {
curCol = vColor;
}
vec4 ambientColor = GetAmbientColor(curCol);
vec4 diffuseColor = GetDiffuseColor(curNormal, curCol);
vec4 specularColor = GetSpecularColor(curNormal, vPosition);
// Combine into final color
vec4 outColor;
outColor = ambientColor + diffuseColor + specularColor;
//Set the output color to the texture color
gl_FragColor = outColor;
}
]]
}