Created
August 28, 2015 00:50
-
-
Save dermotbalson/190141f07a5e73bc03a1 to your computer and use it in GitHub Desktop.
SBS Lighting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Notes | |
--This project shows how to add different types of lighting to 3D scenes (in this case, a cube) | |
--The original code was written by spacemonkey. This explanation is by ignatz. | |
--HOW TO USE THIS PROJECT | |
--There are a number of tabs at the top. Press on a tab to see its code. | |
--Work through the tabs from left to right, to see the project develop | |
--You can run the code in any of the project tabs, by | |
--1. running the program, and | |
--2. selecting the tab number using the controls at the upper left of the screen | |
--The program will remember your selection after that. | |
--This enables you to work with one tab at a time, make changes and see the effects by running the program | |
--# Main | |
--Project: Step by step 3D lighting | |
--Version: 1.0 | |
--Comments: | |
--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 | |
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 | |
SetupParameters() | |
RunCode() | |
end | |
function SetupParameters() | |
LastCode=readProjectData("Code") or 1 --load stored tab number | |
parameter.integer("Choose_a_tab",1,#tabs,LastCode,ShowList) --tab selector | |
parameter.action("Run selected tab", 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 | |
return t | |
end | |
--change tabs | |
function RunCode() | |
output.clear() | |
saveProjectData("Code",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() | |
end | |
--# Cube3D | |
--1 | |
if localise then _ENV=localise(1,"Create cube") end --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--All we'll do in this tab is set up a 3D cube, based on the code from 3D lab demo | |
function setup() | |
cube=CreateCube() | |
--allow user to choose colour, set chosen colour | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
end | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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 | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) --choose viewing angle so we can see it is 3D | |
cube:draw() | |
end | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end | |
--# Textures | |
--2 | |
if localise then _ENV=localise(2,"Add textures") end --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--Now you can choose the cube texture | |
function setup() | |
cube=CreateCube() | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
readImage("Cargo Bot:Starry Background") | |
-- ******* Add some optional textures for cube | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Cargo Bot:Starry Background" | |
} | |
cameraSource(CAMERA_FRONT) | |
parameter.integer("Texture",0,#allTextures,3,changeTexture) --allow user to change texture | |
end | |
--this runs when the texture changes | |
function changeTexture() | |
if Texture > 0 then | |
cube.texture = allTextures[Texture] | |
cube:setColors(color(255)) | |
else | |
cube.texture=nil | |
cube:setColors(surfaceColor) | |
end | |
end | |
--EVERYTHING BELOW IS UNCHANGED -- | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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], | |
} | |
if c then m:setColors(c) end | |
return m | |
end | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) --choose viewing angle so we can see it is 3D | |
cube:draw() | |
end | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end | |
--# Rotate | |
--3 | |
if localise then _ENV=localise(3,"Rotate our cube") end --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--This is an interesting way to rotate our cube with our fungers | |
--it uses modelMatrix, which stores the current world position and rotation settings | |
--we store these to start with, and every time the user drags across the screen, | |
--we rotate by the change in x and y, and then store the modelMatrix ready for the next redraw | |
function setup() | |
cube=CreateCube() | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Cargo Bot:Starry Background" | |
} | |
cameraSource(CAMERA_FRONT) | |
parameter.integer("Texture",0,#allTextures,0,changeTexture) | |
currentModelMatrix=modelMatrix() -- store the initial settings ********* NEW | |
end | |
function draw() | |
background(220) | |
fontSize(24) | |
text("Use your fingers to rotate the cube",WIDTH/2,HEIGHT-50) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
modelMatrix(currentModelMatrix) --apply the stored settings **** NEW | |
--do rotation for touch | |
if CurrentTouch.state == MOVING then --only rotate while fingers are moving on the screen | |
rotate(CurrentTouch.deltaX,0,1,0) --rotate by the x change, on the y axis (see note below) | |
rotate(CurrentTouch.deltaY,1,0,0) --and by the y change, on the x axis (see note below) | |
currentModelMatrix = modelMatrix() --store the resulting settings for next time | |
end | |
cube:draw() | |
ortho() | |
fill(0) | |
text("Use your fingers to rotate the cube",50,HEIGHT-50) | |
end | |
--NOTE - when we rotate by the x changes, why do we rotate on the y axis (and vice versa)? | |
-- The reason is that when you drag your finger left or right, you want the cube to spin left or right. | |
-- This is the same as if you are standing, and then turn around left or right. You turn around your spine | |
-- which is vertical, so you are turning around the y axis. | |
-- Similarly, if we move our finger up or down the screen, we want the cube to spin forward or back | |
-- imagine a gymnast on the parallel bars, holding the bar with both hands and swinging round the bar | |
-- think about which way the bar runs - it runs on each side of us, ie along the x axis | |
-- Another way to think about it is that the x and y axis have sails attached, and | |
-- the finger movement is like a gust of wind. When it blows left or right along the x axis, | |
-- it catches the y axis, and turns it round. | |
-- When it blows up or down, it similarly catches the wind on the x axis, and turns it round | |
--EVERYTHING BELOW IS UNCHANGED -- | |
--this runs when the texture changes | |
function changeTexture() | |
if Texture > 0 then | |
cube.texture = allTextures[Texture] | |
cube:setColors(color(255)) | |
else | |
cube.texture=nil | |
cube:setColors(surfaceColor) | |
end | |
end | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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], | |
} | |
if c then m:setColors(c) end | |
if t then m.texture=t end | |
return m | |
end | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end | |
--# Shader | |
--4 | |
if localise then _ENV=localise(4,"Add a simple shader") end --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--Now we'll add a basic shader that does nothing for the moment except choose between using a texture image | |
--or just a colour (which isn't any different from what we've been doing) | |
--so we should get the same result as for the previous step | |
--If you don't understand shaders, look for tutorials on them, because you can't go any further without them | |
function setup() | |
cube=CreateCube() | |
cube.shader=shader(ADSLighting.vertexShader,ADSLighting.fragmentShader) --*** attach shader to mesh | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Cargo Bot:Starry Background" | |
} | |
cameraSource(CAMERA_FRONT) | |
parameter.integer("Texture",0,#allTextures,0,changeTexture) | |
currentModelMatrix=modelMatrix() | |
end | |
--this runs when the texture changes | |
function changeTexture() | |
if Texture > 0 then | |
cube.texture = allTextures[Texture] | |
cube:setColors(color(255)) | |
cube.shader.useTexture = true | |
else | |
cube.shader.useTexture = false | |
cube:setColors(surfaceColor) | |
end | |
end | |
--this is a very simple shader that does nothing special - yet | |
ADSLighting = { | |
vertexShader = [[ | |
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 lowp sampler2D texture; | |
uniform bool useTexture; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
//choose between using a texture or just colours | |
if (useTexture) { | |
lowp vec4 curCol = texture2D( texture, vTexCoord); | |
gl_FragColor =curCol; | |
} | |
else gl_FragColor=vColor; | |
} | |
]] | |
} | |
--EVERYTHING BELOW IS UNCHANGED -- | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
modelMatrix(currentModelMatrix) --apply the stored settings | |
--do rotation for touch | |
if CurrentTouch.state == MOVING then --only rotate while fingers are moving on the screen | |
rotate(CurrentTouch.deltaX,0,1,0) --rotate by the x change, on the y axis (see note below) | |
rotate(CurrentTouch.deltaY,1,0,0) --and by the y change, on the x axis (see note below) | |
currentModelMatrix = modelMatrix() --store the resulting settings for next time | |
end | |
cube:draw() | |
end | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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], | |
} | |
if c then m:setColors(c) end | |
if t then m.texture=t end | |
return m | |
end | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end | |
--# Ambient | |
--5 | |
if localise then _ENV=localise(5,"Add Ambient light") end--DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--Here we go with the lighting! | |
--Ambient light is the general lighting level | |
--You could call it the minimum light that falls on every surface | |
--if it is 0, then anything that is not lit will be pitch black | |
--if it is 1, then everything is fully lit all the time | |
--As you might guess, it is pretty simple - you just multiply the light level by the ambient factor | |
--There's just one thing - the ambient light doesn't have to be white, so we specify the light colour | |
--and everything will be tinted by this colour (see the extra parameter provided for this) | |
function setup() | |
cube=CreateCube() | |
cube.shader=shader(ADSLighting.vertexShader,ADSLighting.fragmentShader) | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Cargo Bot:Starry Background" | |
} | |
cameraSource(CAMERA_FRONT) | |
parameter.integer("Texture",0,#allTextures,0,changeTexture) | |
parameter.number("ambient", 0, 1, 0.6) -- level of ambient light (0=dark, 1=light) **** NEW | |
parameter.color("lightColor", color(255,255,255,255)) --- colour of ambient light ***** NEW | |
currentModelMatrix=modelMatrix() | |
end | |
--this runs when the texture changes | |
function changeTexture() | |
if Texture > 0 then | |
cube.texture = allTextures[Texture] | |
cube:setColors(color(255)) | |
cube.shader.useTexture = true | |
else | |
cube.shader.useTexture = false | |
cube:setColors(surfaceColor) | |
end | |
end | |
--this is a very simple shader that does nothing special - yet | |
ADSLighting = { | |
vertexShader = [[ | |
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 lowp sampler2D texture; | |
uniform bool useTexture; | |
uniform float vAmbientMaterial; // ******* NEW | |
uniform vec4 lightColor; // ******* NEW | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
// Ambient color component of vertex ******** NEW FUNCTION | |
//Ambient light multiplies the normal light by the brightness (vAmbientMaterial) | |
//and also by the colour of that light (lightColor) | |
vec4 GetAmbientColor(vec4 texCol) | |
{ | |
vec4 vAmbientColor; | |
vAmbientColor.xyz = texCol.rgb * lightColor.rgb * vAmbientMaterial; | |
vAmbientColor.a = 1.0; | |
return vAmbientColor; | |
} | |
void main() | |
{ | |
lowp vec4 curCol; | |
//choose between using a texture or just colours | |
if (useTexture) { | |
curCol = texture2D( texture, vTexCoord); | |
} | |
else curCol=vColor; | |
gl_FragColor = GetAmbientColor(curCol); | |
} | |
]] | |
} | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
modelMatrix(currentModelMatrix) --apply the stored settings | |
--do rotation for touch | |
if CurrentTouch.state == MOVING then --only rotate while fingers are moving on the screen | |
rotate(CurrentTouch.deltaX,0,1,0) --rotate by the x change, on the y axis (see note below) | |
rotate(CurrentTouch.deltaY,1,0,0) --and by the y change, on the x axis (see note below) | |
currentModelMatrix = modelMatrix() --store the resulting settings for next time | |
end | |
cube.shader.vAmbientMaterial = ambient --- ****** NEW | |
cube.shader.lightColor = lightColor --- ****** NEW | |
cube:draw() | |
end | |
--EVERYTHING BELOW IS UNCHANGED -- | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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], | |
} | |
if c then m:setColors(c) end | |
if t then m.texture=t end | |
return m | |
end | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end | |
--# Diffuse | |
--6 | |
if localise then _ENV=localise(6,"Add Diffuse light") end --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--There are lots of code changes | |
--The main changes are to calculate "normals" (see end of CreateCube) | |
--and in the fragment shader, which has a function to calculate diffuse light | |
function setup() | |
cube=CreateCube() | |
cube.shader=shader(ADSLighting.vertexShader,ADSLighting.fragmentShader) | |
--set position of light source | |
cube.shader.vLightPosition = vec4(-.5,1,3,1) -- ****** NEW | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Cargo Bot:Starry Background" | |
} | |
cameraSource(CAMERA_FRONT) | |
parameter.integer("Texture",3,#allTextures,0,changeTexture) | |
parameter.number("ambient", 0, 1, 0.6) | |
parameter.number("diffuse", 0, 1, 1.0) --brightness of light source -- ***** NEW | |
parameter.color("lightColor", color(255,255,255,255)) | |
currentModelMatrix=modelMatrix() | |
end | |
--this runs when the texture changes | |
function changeTexture() | |
if Texture > 0 then | |
cube.texture = allTextures[Texture] | |
cube:setColors(color(255)) | |
cube.shader.useTexture = true | |
else | |
cube.shader.useTexture = false | |
cube:setColors(surfaceColor) | |
end | |
end | |
--shader follows | |
ADSLighting = { | |
vertexShader = [[ | |
uniform mat4 modelViewProjection; | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
attribute vec3 normal; // **** NEW | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying highp vec3 vNormal; | |
void main() | |
{ | |
vColor = color; | |
vNormal = normal; // **** NEW | |
vTexCoord = texCoord; | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
fragmentShader = [[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform bool useTexture; | |
uniform mat4 mModel; // ****** NEW | |
uniform float vAmbientMaterial; | |
uniform float vDiffuseMaterial; // **** NEW | |
uniform vec4 lightColor; | |
uniform vec4 vLightPosition; // ****** NEW | |
varying highp vec3 vNormal; // ***** NEW | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
vec4 GetAmbientColor(vec4 texCol) | |
{ | |
vec4 vAmbientColor; | |
vAmbientColor.xyz = texCol.rgb * lightColor.rgb * vAmbientMaterial; | |
vAmbientColor.a = 1.0; | |
return vAmbientColor; | |
} | |
// Diffuse Color component of vertex ***** NEW | |
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() | |
{ | |
lowp vec4 curCol; | |
//choose between using a texture or just colours | |
if (useTexture) { | |
curCol = texture2D( texture, vTexCoord); | |
} | |
else curCol=vColor; | |
vec4 ambientColor = GetAmbientColor(curCol); | |
vec4 diffuseColor = GetDiffuseColor(vNormal, curCol); // **** NEW | |
gl_FragColor = ambientColor + diffuseColor; // **** NEW | |
} | |
]] | |
} | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
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.vAmbientMaterial = ambient | |
cube.shader.vDiffuseMaterial = diffuse -- **** NEW | |
cube.shader.lightColor = lightColor | |
cube:draw() | |
end | |
function CreateCube() | |
local m = mesh() | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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], | |
} | |
--calculate normals for vertices --- ******* NEW below | |
--this assumes flat surfaces, and hard edges between triangles (which is good for cubes) | |
local normals = {} | |
for i=1, #m.vertices,3 do --calculate normal for each set of 3 vertices | |
local n = (m.vertices[i+1] - m.vertices[i]):cross(m.vertices[i+2] - m.vertices[i]) | |
normals[i] = n --then apply it to all 3 | |
normals[i+1] = n | |
normals[i+2] = n | |
end | |
m.normals=normals --attach to mesh | |
if c then m:setColors(c) end | |
if t then m.texture=t end | |
return m | |
end | |
--EVERYTHING BELOW IS UNCHANGED -- | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end | |
--# Specular | |
--7 | |
if localise then _ENV=localise(7,"Add Specular light") end --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--Specular light is the reflection from a light source (the bright spot!) | |
function setup() | |
cube=CreateCube() | |
cube.shader=shader(ADSLighting.vertexShader,ADSLighting.fragmentShader) | |
--set position of light source | |
cube.shader.vLightPosition = vec4(-.5,1,3,1) | |
cube.shader.vEyePosition = vec4(0,0,3,1) --- **** NEW | |
parameter.color("surfaceColor", color(191,41,85,255),function(c) cube:setColors(c) end) | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Cargo Bot:Starry Background" | |
} | |
cameraSource(CAMERA_BACK) | |
parameter.integer("Texture",3,#allTextures,0,changeTexture) | |
parameter.number("ambient", 0, 1, 0.6) | |
parameter.number("diffuse", 0, 1, 1.0) | |
parameter.number("specular", 0, 1, .8) -- ***** NEW | |
parameter.color("lightColor", color(255,255,255,255)) | |
currentModelMatrix=modelMatrix() | |
end | |
function changeTexture() | |
if Texture > 0 then | |
cube.texture = allTextures[Texture] | |
cube:setColors(color(255)) | |
cube.shader.useTexture = true ---NEW | |
else | |
cube.shader.useTexture = false ---NEW | |
cube:setColors(surfaceColor) | |
end | |
end | |
--shader follows | |
ADSLighting = { | |
vertexShader = [[ | |
uniform mat4 modelViewProjection; | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
attribute vec3 normal; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying highp vec3 vNormal; | |
varying highp vec4 vPosition; // *** NEW | |
void main() | |
{ | |
vColor = color; | |
vNormal = normal; | |
vTexCoord = texCoord; | |
vPosition = position; // ---NEW | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
fragmentShader = [[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform bool useTexture; | |
uniform mat4 mModel; | |
uniform float vAmbientMaterial; | |
uniform float vDiffuseMaterial; | |
uniform vec4 lightColor; | |
uniform vec4 vLightPosition; | |
uniform vec4 vEyePosition; // *** NEW | |
uniform float vSpecularMaterial; // **** NEW | |
varying highp vec3 vNormal; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying highp vec4 vPosition; // *** NEW | |
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; | |
} | |
// Returns the specular component of the color ******* NEW | |
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; | |
} | |
void main() | |
{ | |
lowp vec4 curCol; | |
//choose between using a texture or just colours | |
if (useTexture) { | |
curCol = texture2D( texture, vTexCoord); | |
} | |
else curCol=vColor; | |
vec4 ambientColor = GetAmbientColor(curCol); | |
vec4 diffuseColor = GetDiffuseColor(vNormal, curCol); | |
vec4 specularColor = GetSpecularColor(vNormal, vPosition); // ***** NEW | |
gl_FragColor = ambientColor + diffuseColor + specularColor; // **** NEW | |
} | |
]] | |
} | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
modelMatrix(currentModelMatrix) --apply the stored settings | |
--do rotation for touch | |
if CurrentTouch.state == MOVING then --only rotate while fingers are moving on the screen | |
rotate(CurrentTouch.deltaX,0,1,0) --rotate by the x change, on the y axis (see note below) | |
rotate(CurrentTouch.deltaY,1,0,0) --and by the y change, on the x axis (see note below) | |
currentModelMatrix = modelMatrix() --store the resulting settings for next time | |
end | |
cube.shader.mModel = modelMatrix() | |
cube.shader.vAmbientMaterial = ambient | |
cube.shader.vDiffuseMaterial = diffuse | |
cube.shader.vSpecularMaterial = specular -- **** NEW | |
cube.shader.lightColor = lightColor | |
cube:draw() | |
end | |
--EVERYTHING BELOW IS UNCHANGED -- | |
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 texvertices = { vec2(0,0), | |
vec2(1,0), | |
vec2(0,1), | |
vec2(1,1) } | |
-- 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], | |
} | |
--calculate normals for vertices | |
--this assumes flat surfaces, and hard edges between triangles (which is good for cubes) | |
local normals = {} | |
for i=1, #m.vertices,3 do --calculate normal for each set of 3 vertices | |
local n = (m.vertices[i+1] - m.vertices[i]):cross(m.vertices[i+2] - m.vertices[i]) | |
normals[i] = n --then apply it to all 3 | |
normals[i+1] = n | |
normals[i+2] = n | |
end | |
m.normals=normals --attach to mesh | |
if c then m:setColors(c) end | |
if t then m.texture=t end | |
return m | |
end | |
function cleanup() | |
parameter.clear() | |
SetupParameters() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment