Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Lighting tutorials
--# Main
--Main
--This code manages which Code tab is run
--it remembers your last choice, and if you select a different one, it runs that instead
--This has nothing to do with 3D lighting and you can ignore it completely
local tabs = {}
local fnames = {"setup","draw","touched","collide","orientationChanged","close","restart","keyboard","cleanup"}
local fns = {}
local tabDesc={}
function setup()
for k,v in ipairs(fnames) do --store addresses of key event functions
fns[v] = _G[v]
end
LastCode=readProjectData("Code") or 1 --load stored tab number
parameter.integer("Choose_a_tab",1,#tabs,LastCode,ShowList) --tab selector
RunCode()
end
function ShowList()
output.clear()
for i=1,#tabs do
print(i,tabDesc[i])
end
end
--these two functions do all the tab switching magic (thanks to Andrew_Stacey)
function localise(n,d)
if d then tabDesc[n]=d end
local t= {}
setmetatable(t,{__index = _G})
setfenv(2,t)
tabs[n] = t
end
--change tabs
function RunCode()
output.clear()
saveProjectData("Code",Choose_a_tab)
LastCode=Choose_a_tab
cleanup()
local t = tabs[Choose_a_tab]
for k,v in ipairs(fnames) do
if t[v] then _G[v] = t[v] else _G[v] = fns[v] end -- overwrite with the new code
end
setup()
end
--default empty function to avoid errors for tabs that don't have it
function cleanup()
parameter.clear()
parameter.integer("Choose_a_tab",1,#tabs,LastCode,ShowList) --tab selector
parameter.action("Run selected tab", RunCode)
end
--# Ambient
--Ambient
if localise then localise(1,"Ambient") end
function setup()
m=mesh() --Define a test mesh
m:addRect(0, 0, 2,3)
m.shader=shader(ambientShader.vertexShader,ambientShader.fragmentShader)
rot={a=0} --tween to rotate rectangle
tween(5, rot, {a=180}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
parameter.color("SurfaceColour",color(255,255,0))
parameter.color("AmbientColour",color(255,0,0))
parameter.number("Strength",0,1,0.5)
end
function draw()
background(0)
perspective()
camera(0, 0, 0, 0, 0, -10)
pushMatrix()
translate(0, 0, -7)
rotate(rot.a, 0, 1, 0)
m:setColors(SurfaceColour)
--now combine the ambient colour and strength to reduce work for the shader
--I'm setting the ambient colour here, because you can change it with parameters
--I'll move it up into setup when I take those parameters away and the ambient settings become fixed
m.shader.ambientLight = color(AmbientColour.r*Strength,AmbientColour.g*Strength,AmbientColour.b*Strength)
m:draw()
popMatrix()
end
ambientShader = {
vertexShader = [[ //-- This is a standard vertex shader, nothing added
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
vColor = color;
vTexCoord = texCoord;
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
precision highp float;
uniform vec4 ambientLight; // --ambient light colour
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
vec4 pixel = vColor; //--get colour of this pixel
//--note - we are ignoring textures for now
//--but when we do include them, we will set pixel based on texture lookup instead
gl_FragColor= pixel * ambientLight; //--apply ambient light
}
]]
}
--# Diffuse
--Diffuse
--look for the lines marked NEW
if localise then localise(2,"Diffuse") end
function setup()
--mesh and shader
m=CreateCube() --NEW cube shows light better than a rectangle
m.shader=shader(diffuseShader.vertexShader,diffuseShader.fragmentShader)
m.normals=CalculateNormals(m.vertices) --NEW calculate normals, send to shader
--visual effects
rot={x=0,y=0,z=0} --rotation of cube
tween(15, rot, {x=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(7, rot, {y=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(17, rot, {z=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
--user parameters and fixed light settings
SurfaceColour=color(255)
AmbientColour=color(255,255,0)
AmbientStrength=0.2
m:setColors(SurfaceColour)
m.shader.ambientLight = color(AmbientColour.r*AmbientStrength,AmbientColour.g*AmbientStrength,
AmbientColour.b*AmbientStrength)
parameter.color("DirectColour",color(255,0,0)) --NEW two new parameters, the colour and strength
parameter.number("DirectStrength",0,1,0.5) -- of the directional light
end
function draw()
background(0)
perspective()
camera(0, 0, 0, 0, 0, -10)
pushMatrix()
--move and draw cube
translate(0, 0, -3)
rotate(rot.x, 1, 0, 0) rotate(rot.y,0,1,0) rotate(rot.z,0,0,1)
--NEW now combine the directional colour and strength to reduce work for the shader
m.shader.directColor=color(DirectColour.r*DirectStrength,DirectColour.g*DirectStrength,
DirectColour.b*DirectStrength)
m.shader.directDirection=vec4(-1, 0, 1,0):normalize()
m.shader.mModel = modelMatrix() --NEW see ebook
m:draw()
popMatrix()
end
function CalculateNormals(vertices) --NEW
--this assumes flat surfaces, and hard edges between triangles
local norm = {}
for i=1, #vertices,3 do --calculate normal for each set of 3 vertices
local n = ((vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])):normalize()
norm[i] = n --then apply it to all 3
norm[i+1] = n
norm[i+2] = n
end
return norm
end
diffuseShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
uniform mat4 mModel; //--matrix to convert from object to world space
uniform vec4 directColor; //--NEW directional light colour
uniform vec4 directDirection; //--NEW directional light direction
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse; //--NEW diffuse reflection, send to fragment shader
void main()
{
vColor = color;
vTexCoord = texCoord;
vec4 norm = normalize(mModel * vec4( normal, 0.0 )); //--NEW convert normal to eye space
//--NEW diffuse light is based on angle between light direction and normal direction
vDirectDiffuse = directColor * max( 0.0, dot( norm, directDirection ));
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
precision highp float;
uniform vec4 ambientLight;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse; // --NEW diffuse light
void main()
{
vec4 pixel = vColor;
vec4 ambient = pixel * ambientLight;
vec4 diffuse = pixel * vDirectDiffuse; //-- NEW
vec4 totalColor = clamp(ambient + diffuse,0.,1.); //--NEW add ambient and diffuse,can't exceed 1
totalColor.a=1.; //--NEW set alpha to 1, ie opaque
gl_FragColor=totalColor;
}
]]
}
function CreateCube() --NEW
local m = 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
m.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 q=.03
local texvertices = { vec2(q,q),
vec2(1-q,q),
vec2(q,1-q),
vec2(1-q,1-q) }
-- apply the texture coordinates to each triangle
m.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],
}
return m
end
--# Specular
--Specular
--look for the lines marked NEW
if localise then localise(3,"Specular") end
function setup()
--mesh and shader
m=CreateCube()
m.shader=shader(specularShader.vertexShader,specularShader.fragmentShader)
m.normals=CalculateNormals(m.vertices)
--visual effects
rot={x=0,y=0,z=0} --rotation of cube
tween(15, rot, {x=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(7, rot, {y=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(17, rot, {z=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
--user parameters and fixed light settings
SurfaceColour=color(255)
AmbientColour=color(255,255,0)
AmbientStrength=0.2
m:setColors(SurfaceColour)
m.shader.ambientLight = color(AmbientColour.r*AmbientStrength,AmbientColour.g*AmbientStrength,
AmbientColour.b*AmbientStrength)
DirectColour=color(255,0,0)
DirectStrength=0.8
m.shader.directColor=color(DirectColour.r*DirectStrength,DirectColour.g*DirectStrength,
DirectColour.b*DirectStrength)
m.shader.directDirection=vec4(-1, 0, 1,0):normalize()
m.shader.specularColor=color(255) --NEW specular setting
m.shader.reflec=1 --NEW applies to all reflections, set for full reflection
m.shader.shiny=0.6 --NEW, applies only to specular, mostly shiny
camPos=vec3(0, 0, 0)
m.shader.eyePosition=vec4(camPos.x, camPos.y, camPos.z,1)
end
function draw()
background(0)
perspective()
camera(camPos.x, camPos.y, camPos.z, 0, 0, -10)
pushMatrix()
--move and draw cube
translate(0, 0, -3)
rotate(rot.x, 1, 0, 0) rotate(rot.y,0,1,0) rotate(rot.z,0,0,1)
m.shader.mModel = modelMatrix()
m:draw()
popMatrix()
end
function CalculateNormals(vertices)
local norm = {}
for i=1, #vertices,3 do
local n = ((vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])):normalize()
norm[i] = n
norm[i+1] = n
norm[i+2] = n
end
return norm
end
specularShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
uniform mat4 mModel;
uniform vec4 directColor;
uniform vec4 directDirection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse;
varying lowp vec4 vPosition; //--NEW (x,y,z) position of vertex in eye space
varying lowp vec4 vNormal; //--NEW normal of vertex in eye space
void main()
{
vColor = color;
vTexCoord = texCoord;
vPosition = mModel * position;
vNormal = mModel * vec4( normal, 0.0 );
vec4 norm = normalize(vNormal);
vDirectDiffuse = directColor * max( 0.0, dot( norm, directDirection ));
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[ //--NEW almost all the changes are in here
precision highp float;
uniform vec4 ambientLight;
uniform vec4 directDirection;
uniform float reflec; //--NEW
uniform float shiny; //--NEW
uniform vec4 specularColor; //--NEW
uniform vec4 eyePosition;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
vec4 normalizedNormal = normalize(vNormal);
// --NEW specular light, uses Blinn-Phong half vector approach, faster than Phong
vec4 GetSpecularColor(vec4 lightPosition)
{
vec4 cameraDirection = normalize( eyePosition - vPosition );
vec4 halfAngle = normalize( cameraDirection + lightPosition );
vec4 specularColor = min(specularColor + 0.5, 1.0);
float spec = pow( max( 0.0, dot( normalizedNormal, halfAngle)), 32.0 );
return specularColor * spec;
}
void main()
{
vec4 pixel = vColor;
vec4 ambient = ambientLight;
vec4 diffuse = vDirectDiffuse;
vec4 specular = GetSpecularColor( directDirection ); //--NEW
vec4 totalColor = clamp(pixel * reflec * (ambient + diffuse + specular * shiny),0.,1.);
totalColor.a=1.;
gl_FragColor=totalColor;
}
]]
}
function CreateCube()
local m = 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
m.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 q=.03
local texvertices = { vec2(q,q),
vec2(1-q,q),
vec2(q,1-q),
vec2(1-q,1-q) }
-- apply the texture coordinates to each triangle
m.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],
}
return m
end
--# Point
--Point
--look for the lines marked NEW
if localise then localise(4,"Point") end
function setup()
--mesh and shader
m=CreateCube()
m.shader=shader(pointShader.vertexShader,pointShader.fragmentShader)
m.normals=CalculateNormals(m.vertices)
--visual effects
rot={x=0,y=0,z=0} --rotation of cube
tween(15, rot, {x=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(7, rot, {y=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(17, rot, {z=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
--move cube back and forwards
cubePos={x=0,y=0,z=-10}
tween(9, cubePos, {z=-2}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
--user parameters and fixed light settings
SurfaceColour=color(255)
AmbientColour=color(255,255,0)
AmbientStrength=0.2
m:setColors(SurfaceColour)
m.shader.ambientLight = color(AmbientColour.r*AmbientStrength,AmbientColour.g*AmbientStrength,
AmbientColour.b*AmbientStrength)
DirectColour=color(255,0,0)
DirectStrength=0.8
m.shader.directColor=color(DirectColour.r*DirectStrength,DirectColour.g*DirectStrength,
DirectColour.b*DirectStrength)
m.shader.directDirection=vec4(-1, 0, 1, 1)
m.shader.specularColor=color(255)
m.shader.reflec=1
m.shader.shiny=0.6
camPos=vec3(0, 0, 0)
m.shader.eyePosition=vec4(camPos.x, camPos.y, camPos.z,1)
parameter.integer("Point_Range",0,20,10) --NEW set range of the light
end
function draw()
background(0)
perspective()
camera(camPos.x, camPos.y, camPos.z, 0, 0, -10)
pushMatrix()
--move and draw cube
translate(cubePos.x, cubePos.y, cubePos.z)
rotate(rot.x, 1, 0, 0) rotate(rot.y,0,1,0) rotate(rot.z,0,0,1)
m.shader.mModel = modelMatrix()
m.shader.pointRange=Point_Range --NEW
m:draw()
popMatrix()
end
function CalculateNormals(vertices)
local norm = {}
for i=1, #vertices,3 do
local n = ((vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])):normalize()
norm[i] = n
norm[i+1] = n
norm[i+2] = n
end
return norm
end
pointShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
uniform mat4 mModel; //matrix to convert from object to world space
uniform vec4 directColor;
uniform vec4 directDirection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
void main()
{
vColor = color;
vTexCoord = texCoord;
vPosition = mModel * position;
vNormal = mModel * vec4( normal, 0.0 );
vec4 norm = normalize(vNormal);
vec4 d = normalize( directDirection - vPosition );
vDirectDiffuse = directColor * max( 0.0, dot( norm, d ));
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
precision highp float;
uniform vec4 ambientLight;
uniform vec4 directDirection;
uniform float pointRange; //--NEW
uniform float reflec;
uniform float shiny;
uniform vec4 specularColor;
uniform vec4 eyePosition;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
vec4 normalizedNormal = normalize(vNormal);
vec4 GetSpecularColor(vec4 lightPosition)
{
vec4 lightDirection = normalize( lightPosition - vPosition );
vec4 cameraDirection = normalize( eyePosition - vPosition );
vec4 halfAngle = normalize( cameraDirection + lightDirection );
vec4 specularColor = min(specularColor + 0.5, 1.0);
float spec = pow( max( 0.0, dot( normalizedNormal, halfAngle)), 32.0 );
return specularColor * spec;
}
void main()
{
vec4 pixel = vColor;
vec4 ambient = ambientLight;
vec4 diffuse = vDirectDiffuse;
vec4 specular = GetSpecularColor( directDirection );
//--NEW now calculate attenuation
float attenuation = max( 0.0, 1.0 - length( directDirection - vPosition ) / pointRange );
vec4 totalColor = clamp(pixel * reflec * attenuation * (ambient + diffuse + specular * shiny),0.,1.);
totalColor.a=1.;
gl_FragColor=totalColor;
}
]]
}
function CreateCube()
local m = 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
m.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 q=.03
local texvertices = { vec2(q,q),
vec2(1-q,q),
vec2(q,1-q),
vec2(1-q,1-q) }
-- apply the texture coordinates to each triangle
m.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],
}
return m
end
--# Spot
--Point
--look for the lines marked NEW
if localise then localise(5,"Spot") end
function setup()
--mesh and shader
m=CreateCube()
m.shader=shader(spotShader.vertexShader,spotShader.fragmentShader)
m.normals=CalculateNormals(m.vertices)
--visual effects
rot={x=0,y=0,z=0} --rotation of cube
tween(15, rot, {x=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(7, rot, {y=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
tween(17, rot, {z=360}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
--move cube back and forwards
cubePos={x=0,y=0,z=-10}
tween(9, cubePos, {z=-2}, { easing = tween.easing.linear, loop = tween.loop.pingpong })
--user parameters and fixed light settings
SurfaceColour=color(255)
AmbientColour=color(255,255,0)
AmbientStrength=0.2
m:setColors(SurfaceColour)
m.shader.ambientLight = color(AmbientColour.r*AmbientStrength,AmbientColour.g*AmbientStrength,
AmbientColour.b*AmbientStrength)
DirectColour=color(255,0,0)
DirectStrength=0.8
m.shader.directColor=color(DirectColour.r*DirectStrength,DirectColour.g*DirectStrength,
DirectColour.b*DirectStrength)
m.shader.directDirection=vec4(-1, 0, 1, 1)
m.shader.specularColor=color(255)
m.shader.reflec=1
m.shader.shiny=0.6
camPos=vec3(0, 0, 0)
m.shader.eyePosition=vec4(camPos.x, camPos.y, camPos.z,1)
m.shader.spotDirection=vec4(0.5,0,-2,0):normalize() --NEW a spotlight points in a certain direction
parameter.integer("Point_Range",0,20,10) --NEW a spotlight has a range
parameter.integer("Spot_Radius",0,40,5) --NEW and its light beam has a radius
end
function draw()
background(0)
perspective()
camera(camPos.x, camPos.y, camPos.z, 0, 0, -10)
pushMatrix()
--move and draw cube
translate(cubePos.x, cubePos.y, cubePos.z)
rotate(rot.x, 1, 0, 0) rotate(rot.y,0,1,0) rotate(rot.z,0,0,1)
m.shader.mModel = modelMatrix()
m.shader.pointRange=Point_Range --NEW
--calculate the cos value which tells us if a pixel is within the light beam
m.shader.pointCos=math.cos(math.rad(Spot_Radius)) --NEW
m:draw()
popMatrix()
end
function CalculateNormals(vertices)
local norm = {}
for i=1, #vertices,3 do
local n = ((vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])):normalize()
norm[i] = n
norm[i+1] = n
norm[i+2] = n
end
return norm
end
spotShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
uniform mat4 mModel;
uniform vec4 directColor;
uniform vec4 directDirection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
attribute vec3 normal;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
void main()
{
vColor = color;
vTexCoord = texCoord;
vPosition = mModel * position;
vNormal = mModel * vec4( normal, 0.0 );
vec4 norm = normalize(vNormal);
vec4 d = normalize( directDirection - vPosition );
vDirectDiffuse = directColor * max( 0.0, dot( norm, d ));
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
precision highp float;
uniform vec4 ambientLight;
uniform vec4 directDirection;
uniform vec4 spotDirection;
uniform float pointRange;
uniform float pointCos;
uniform float reflec;
uniform float shiny;
uniform vec4 specularColor;
uniform vec4 eyePosition;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying vec4 vDirectDiffuse;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
vec4 normalizedNormal = normalize(vNormal);
vec4 GetSpecularColor(vec4 lightPosition)
{
vec4 lightDirection = normalize( lightPosition - vPosition );
vec4 cameraDirection = normalize( eyePosition - vPosition );
vec4 halfAngle = normalize( cameraDirection + lightDirection );
vec4 specularColor = min(specularColor + 0.5, 1.0);
float spec = pow( max( 0.0, dot( normalizedNormal, halfAngle)), 32.0 );
return specularColor * spec;
}
lowp float GetSpotValue() //--NEW
{
//--get vector from light to current pixel
vec4 lightToPixel = normalize( vPosition - directDirection );
//--calculate cos of angle
float cos = dot( spotDirection, lightToPixel );
//---compare with max cos of spotlight, interpolate if within its beam
if ( cos >= pointCos && cos <= 1.0 ) {
return max( 0.0, 1.0 - ( 1.0 - cos ) / ( 1.0 - pointCos ));
}
else return 0.0;
}
void main()
{
vec4 pixel = vColor;
vec4 ambient = ambientLight;
vec4 diffuse = vDirectDiffuse;
vec4 specular = GetSpecularColor( directDirection );
float attenuation = max( 0.0, 1.0 - length( directDirection.xyz - vPosition.xyz ) / pointRange );
vec4 totalColor = clamp(pixel * reflec * attenuation *
GetSpotValue() * (ambient + diffuse + specular * shiny),0.,1.);
totalColor.a=1.;
gl_FragColor=totalColor;
}
]]
}
function CreateCube()
local m = 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
m.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 q=.03
local texvertices = { vec2(q,q),
vec2(1-q,q),
vec2(q,1-q),
vec2(1-q,1-q) }
-- apply the texture coordinates to each triangle
m.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],
}
return m
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment