Created
September 30, 2015 02:04
-
-
Save dermotbalson/07e5632074ddbf105d6c to your computer and use it in GitHub Desktop.
SBS Lighting v1
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) | |
--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 | |
Each tab has all the code for that demo, so you can copy the code in any tab to your own project and adapt it | |
IMPORTANT NOTES | |
1. Lighting requires the use of shaders. While you can use this code as a black box, it is | |
preferable that you understand how it works, so you can make changes or fix problems yourself. | |
2. It may be difficult to learn how lighting works just from looking at these demos. Ideally, you should | |
try to learn the basics of diffuse and specular light first. | |
--]] | |
--# Ambient | |
--Ambient light | |
--[[ | |
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) | |
You are unlikely ever to use just ambient light on its own. | |
--]] | |
function setup() | |
block=CreateBlock(1,0.5,0.75,"Cargo Bot:Starry Background") | |
currentModelMatrix=modelMatrix() --this is used for touches, not lighting | |
SetupShader() | |
end | |
--All the lighting code is kept in these two functions to make it easier for you to see it and use it yourself | |
function SetupShader() --set up the lighting | |
--in these demos, you get to change some of the lighting options using parameters | |
--in your own apps, you will probably just set the lighting values yourself | |
parameter.number("ambientStrength", 0, 1, 0.6) -- level of ambient light (0=dark, 1=light) | |
parameter.color("ambientColor", color(255,255,255,255)) --- colour of ambient light | |
block.shader=shader(AmbientShader.vertexShader,AmbientShader.fragmentShader) | |
end | |
function UpdateShader() --update the lighting details before drawing | |
--if you aren't going to be changing ambient colour or strength, you can put this line in setup | |
block.shader.ambient = ambientColor*ambientStrength | |
end | |
--this shader has ambient lighting | |
AmbientShader = { | |
vertexShader = [[ | |
uniform mat4 modelViewProjection; | |
uniform vec4 ambient; // ambient light | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
vColor = color*ambient; // apply ambient light to object colour and pass to fragment shader | |
vTexCoord = texCoord; | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
fragmentShader = [[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
lowp vec4 col = texture2D( texture, vTexCoord) * vColor; //apply ambient light to texture | |
col.a = 1.0; | |
gl_FragColor = col; | |
} | |
]] | |
} | |
--UTILITY CODE - IT WILL NOT CHANGE FROM HERE ON -- | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
HandleTouches() --allows you to rotate the cube with your fingers | |
UpdateShader() | |
block:draw() | |
end | |
--this code manages touches so you can rotate the cube | |
function HandleTouches() | |
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 | |
end | |
--this function creates a cube | |
function CreateBlock(w,h,d,tex,col,pos,ms) --width,height,depth,texture,colour,position,mesh (if existing already) | |
pos=pos or vec3(0,0,0) | |
local x,X,y,Y,z,Z=pos.x-w/2,pos.x+w/2,pos.y-h/2,pos.y+h/2,pos.z-d/2,pos.z+d/2 | |
local v={vec3(x,y,Z),vec3(X,y,Z),vec3(X,Y,Z),vec3(x,Y,Z),vec3(x,y,z),vec3(X,y,z),vec3(X,Y,z),vec3(x,Y,z)} | |
local vert={v[1],v[2],v[3],v[1],v[3],v[4],v[2],v[6],v[7],v[2],v[7],v[3],v[6],v[5],v[8],v[6],v[8],v[7], | |
v[5],v[1],v[4],v[5],v[4],v[8],v[4],v[3],v[7],v[4],v[7],v[8],v[5],v[6],v[2],v[5],v[2],v[1]} | |
local texCoords | |
if tex then | |
local t={vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1)} | |
texCoords={t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3], | |
t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3]} | |
end | |
local norm={} --calculate normals | |
for i=1,#vert,3 do | |
local n=GetNormal(vert[i],vert[i+1],vert[i+2]) | |
norm[i],norm[i+1],norm[i+2]=n,n,n | |
end | |
if not ms then ms=mesh() end | |
if ms.size==0 then | |
ms.vertices=vert | |
ms.normals=norm | |
ms.texture,ms.texCoords=tex,texCoords | |
else | |
for i=1,#vert do | |
table.insert(ms.vertices,vert[i]) | |
table.insert(ms.normals,norm[i]) | |
if tex then table.insert(ms.texCoords,texCoords[i]) end | |
end | |
end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
function GetNormal(v1,v2,v3) | |
return ((v1-v3):cross(v2-v3)):normalize() | |
end | |
function PrintExplanation() | |
output.clear() | |
print("Ambient light is the general background light that shines equally on all sides of an object") | |
print("Use a finger to rotate the cube") | |
end | |
--# Diffuse | |
--Diffuse | |
--[[ | |
The sun is so far away that its light comes from the same direction for every part of your scene, and the | |
strength of the light is also the same across your scene. This is diffuse light - coming from a single direction | |
with a constant colour strength. | |
Diffuse light can have any colour, but because it is added to ambient light, the total of the two should not | |
generally exceed 255. In other words, ambient + diffuse <= color(255) | |
For example, you might use | |
ambient = color(255) * 0.3 --dim white light | |
diffuse = color(255,0,0) * 0.7 --red light | |
When you add these together, the maximum light is color(255,76,76) | |
Diffuse light is caused by reflection, and is brightest for any object directly facing the light, reducing if the | |
light hits the object at an angle. | |
Our objects are made from triangles of vertices. These triangles are flat surfaces, and the direction they are | |
facing is at right angles to that surface. This direction is called a "normal" (based on a latin word meaning 'at right angles'). So if you imagine lying flat on your back on a triangle of vertices, you are looking in the | |
'normal' direction - and if that is facing the diffuse light source, the light will be brightest. | |
You need two things to calculate the amount of diffuse light for any triangle | |
1. its 'normal' direction | |
2. a way of measuring how similar this is to the direction that the diffuse light is coming from | |
This demo provides a function for calculating the normal of any set of three vertices, and Codea meshes have a | |
normals property, so if you have a mesh m and a table of normals n, you can write | |
m.normals = n | |
(see the CreateBlock function below for an example) | |
The dot function is a convenient way of measuring the similarity of two directions, and that is used in the | |
shader to calculate the amount of reflection. | |
Note that because the normals are the same for all the vertices in each triangle, they will be the same for each | |
point in that triangle. So we can calculate diffuse light in the vertex shader, rather than the fragment shader, | |
which is much more efficient. | |
To set the direction the diffuse light is coming from, imagine a line running from (0,0,0) towards the diffuse | |
light. Take any point on that line, and "normalise" it to give it a length of 1. So if I am facing toward -z as | |
usual, here are some examples | |
vec3(-1,0,0) --a light that shines from left to right (no need to normalize, it already has length 1) | |
vec3(0,1,0) --a light that shines down vertically (again, no need to normalise) | |
vec3(-1,0.5,1):normalize() --a light that comes from behind me over my left shoulder | |
The absolute size of the numbers you use for x,y,z doesn't matter, since | |
vec3(1,2,-3):normalize() = vec3(10,20,-30):normalize() | |
but of course the relative size (how big x is, relative to y and z, for example) does matter.. | |
--]] | |
function setup() | |
block=CreateBlock(1,0.5,0.75,"Cargo Bot:Starry Background") | |
currentModelMatrix=modelMatrix() | |
SetupShader() | |
end | |
--All the lighting code is kept in these two functions to make it easier for you to see it and use it yourself | |
function SetupShader() --set up the lighting | |
--in your own apps, you will probably just set these lighting values yourself instead of using parameters | |
parameter.number("diffuseStrength", 0, 1, 0.7) --brightness of light source -- ***** NEW | |
parameter.color("lightColor", color(255)) -- ***** NEW | |
block.shader=shader(DiffuseShader.vertexShader,DiffuseShader.fragmentShader) | |
block.shader.ambientColor = color(255)*0.5 | |
block.shader.directDirection = vec3(-1,0,1):normalize() -- ****** NEW | |
end | |
function UpdateShader() --update the lighting details before drawing | |
--if you aren't going to be changing colours or light strength, you can put the next line in setup | |
block.shader.directColor=diffuseStrength*lightColor -- ****** NEW | |
block.shader.mModel=modelMatrix() --this must be updated each time you draw | |
end | |
--shader follows | |
DiffuseShader = { | |
vertexShader = [[ | |
uniform mat4 modelViewProjection; | |
uniform vec4 ambientColor; | |
uniform vec3 directDirection; // ****** NEW | |
uniform vec4 directColor; // ****** NEW | |
uniform mat4 mModel; // ****** NEW | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
attribute vec3 normal; // **** NEW | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
vec4 norm = normalize(mModel * vec4( normal, 0.0 )); // ****** NEW | |
float diffuse = max( 0.0, dot( norm.xyz, directDirection )); // ****** NEW | |
vColor = ambientColor + diffuse * directColor; // ****** NEW | |
vColor.a = 1.0; | |
vTexCoord = texCoord; | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
fragmentShader = [[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
gl_FragColor = texture2D( texture, vTexCoord) * vColor; | |
} | |
]] | |
} | |
--EVERYTHING BELOW IS UNCHANGED -- | |
function draw() | |
background(220) | |
perspective() | |
camera(-1,1,2,0,0,0) | |
HandleTouches() | |
UpdateShader() | |
block:draw() | |
end | |
function HandleTouches() | |
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 | |
end | |
function CreateBlock(w,h,d,tex,col,pos,ms) --width,height,depth,texture,colour,position,mesh (if existing already) | |
pos=pos or vec3(0,0,0) | |
local x,X,y,Y,z,Z=pos.x-w/2,pos.x+w/2,pos.y-h/2,pos.y+h/2,pos.z-d/2,pos.z+d/2 | |
local v={vec3(x,y,Z),vec3(X,y,Z),vec3(X,Y,Z),vec3(x,Y,Z),vec3(x,y,z),vec3(X,y,z),vec3(X,Y,z),vec3(x,Y,z)} | |
local vert={v[1],v[2],v[3],v[1],v[3],v[4],v[2],v[6],v[7],v[2],v[7],v[3],v[6],v[5],v[8],v[6],v[8],v[7], | |
v[5],v[1],v[4],v[5],v[4],v[8],v[4],v[3],v[7],v[4],v[7],v[8],v[5],v[6],v[2],v[5],v[2],v[1]} | |
local texCoords | |
if tex then | |
local t={vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1)} | |
texCoords={t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3], | |
t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3]} | |
end | |
local norm={} --calculate normals | |
for i=1,#vert,3 do | |
local n=GetNormal(vert[i],vert[i+1],vert[i+2]) | |
norm[i],norm[i+1],norm[i+2]=n,n,n | |
end | |
if not ms then ms=mesh() end | |
if ms.size==0 then | |
ms.vertices=vert | |
ms.normals=norm | |
ms.texture,ms.texCoords=tex,texCoords | |
else | |
for i=1,#vert do | |
table.insert(ms.vertices,vert[i]) | |
table.insert(ms.normals,norm[i]) | |
if tex then table.insert(ms.texCoords,texCoords[i]) end | |
end | |
end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
function GetNormal(v1,v2,v3) | |
return ((v1-v3):cross(v2-v3)):normalize() | |
end | |
function PrintExplanation() | |
output.clear() | |
print("Diffuse light comes from a specific direction, so far away that it is in the same direction (and has the same strength) for every part of the object you are lighting.\n\nExample - the sun") | |
print("The part of the object facing the light direction will be lit the most") | |
print("Use a finger to rotate the cube") | |
end | |
--# Specular | |
--Specular | |
--[[ | |
Specular light is the reflection from a light source into your eye (the bright spot!) | |
It is too complex to explain fully here, but it needs the camera position | |
The extra shader settings below are | |
* specularPower = how focussed and concentrated the light is. Use a power of 2, eg 1,2,4,8,16,32,64,... | |
* shine - how shiny the object is (0 to 1) | |
* eyePosition - (vec3(x,y,z) position of camera | |
--]] | |
function setup() | |
block=CreateBlock(1,0.5,0.75,"Cargo Bot:Starry Background") | |
currentModelMatrix=modelMatrix() | |
camPos=vec3(0,0,2) -- ***** NEW | |
z,zd=0,-.01 --to move block back and forward | |
SetupShader() | |
end | |
--All the lighting code is kept in these two functions to make it easier for you to see it and use it yourself | |
function SetupShader() --set up the lighting | |
--in your own apps, you will probably just set the specular power yourself instead of using parameters | |
parameter.integer("Focus",1,10,5) --this will be a power of 2, eg we will convert 3 to 2^3 = 8 | |
--set position of light source | |
block.shader=shader(SpecularShader.vertexShader,SpecularShader.fragmentShader) | |
block.shader.ambientColor = color(255) *0.5 | |
block.shader.directColor=color(255) *0.7 | |
block.shader.directDirection = vec3(1,0,1):normalize() | |
block.shader.shine=1 -- ***** NEW | |
end | |
function UpdateShader() --update the lighting details before drawing | |
block.shader.specularPower=2^Focus -- ***** NEW | |
block.shader.mModel=modelMatrix() --this must be updated each time you draw | |
block.shader.eyePosition=camPos -- ***** NEW | |
block.shader.mModel=modelMatrix() | |
end | |
function draw() | |
background(220) | |
perspective() | |
currentModelMatrix[15]=z | |
camera(camPos.x,camPos.y,camPos.z,0,0,0) | |
HandleTouches() | |
UpdateShader() | |
block:draw() | |
z=z+zd | |
if z<-3 or z>0 then zd=-zd end | |
end | |
--shader follows | |
SpecularShader={ | |
vertexShader=[[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
uniform vec4 directColor; | |
uniform vec3 directDirection; | |
uniform vec4 ambientColor; | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
attribute vec3 normal; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vPosition; | |
varying lowp vec4 vNormal; | |
varying vec4 vLight; | |
void main() | |
{ | |
vColor = color; | |
vTexCoord = texCoord; | |
vPosition = mModel * position; | |
gl_Position = modelViewProjection * position; | |
vNormal = mModel * vec4( normal, 0.0 ); | |
vLight = ambientColor+directColor * max( 0.0, dot( normalize(vNormal.xyz), directDirection )); | |
} | |
]], | |
fragmentShader=[[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform vec4 directColor; | |
uniform vec3 directDirection; | |
uniform vec3 eyePosition; | |
uniform float specularPower; | |
uniform float shine; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vPosition; | |
varying lowp vec4 vNormal; | |
varying vec4 vLight; | |
vec4 norm = normalize(vNormal); | |
vec4 eye = vec4(eyePosition, 1.0); | |
vec4 direct = vec4(directDirection, 0.0); | |
void main() | |
{ | |
vec4 cameraDirection = normalize( eye - vPosition ); | |
vec4 halfAngle = normalize( cameraDirection + direct ); | |
float spec = pow( max( 0.0, dot( norm, halfAngle)),specularPower); | |
vec4 totalColor=texture2D(texture, vTexCoord)*(vLight+min(directColor + 0.5, 1.0) * spec * shine ); | |
totalColor.a= 1.; | |
gl_FragColor=totalColor; | |
} | |
]] | |
} | |
--EVERYTHING BELOW IS UNCHANGED -- | |
function HandleTouches() | |
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 | |
end | |
function CreateBlock(w,h,d,tex,col,pos,ms) --width,height,depth,texture,colour,position,mesh (if existing already) | |
pos=pos or vec3(0,0,0) | |
local x,X,y,Y,z,Z=pos.x-w/2,pos.x+w/2,pos.y-h/2,pos.y+h/2,pos.z-d/2,pos.z+d/2 | |
local v={vec3(x,y,Z),vec3(X,y,Z),vec3(X,Y,Z),vec3(x,Y,Z),vec3(x,y,z),vec3(X,y,z),vec3(X,Y,z),vec3(x,Y,z)} | |
local vert={v[1],v[2],v[3],v[1],v[3],v[4],v[2],v[6],v[7],v[2],v[7],v[3],v[6],v[5],v[8],v[6],v[8],v[7], | |
v[5],v[1],v[4],v[5],v[4],v[8],v[4],v[3],v[7],v[4],v[7],v[8],v[5],v[6],v[2],v[5],v[2],v[1]} | |
local texCoords | |
if tex then | |
local t={vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1)} | |
texCoords={t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3], | |
t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3]} | |
end | |
local norm={} --calculate normals | |
for i=1,#vert,3 do | |
local n=GetNormal(vert[i],vert[i+1],vert[i+2]) | |
norm[i],norm[i+1],norm[i+2]=n,n,n | |
end | |
if not ms then ms=mesh() end | |
if ms.size==0 then | |
ms.vertices=vert | |
ms.normals=norm | |
ms.texture,ms.texCoords=tex,texCoords | |
else | |
for i=1,#vert do | |
table.insert(ms.vertices,vert[i]) | |
table.insert(ms.normals,norm[i]) | |
if tex then table.insert(ms.texCoords,texCoords[i]) end | |
end | |
end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
function GetNormal(v1,v2,v3) | |
return ((v1-v3):cross(v2-v3)):normalize() | |
end | |
function PrintExplanation() | |
output.clear() | |
print("Specular light adds a bright spot to the reflection") | |
print("The brightness depends on how much the light reflects off the surface toward the camera") | |
print("Use a finger to rotate the cube") | |
end | |
--# Point | |
--Point | |
--Point light is light from a point in space (rather than from a direction, like diffuse light) | |
function setup() | |
block=CreateBlock(1,0.5,0.75,"Cargo Bot:Starry Background") | |
block.shader=shader(ADSLighting.vertexShader,ADSLighting.fragmentShader) | |
--set position of light source | |
parameter.number("ambientStrength", 0, 1, 0.3) | |
parameter.color("ambientColor", color(255,255,255,255)) | |
parameter.number("diffuseStrength", 0, 1, 0.7) --brightness of light source | |
parameter.color("lightColor", color(255,255,255,255)) | |
block.shader.eyePosition = vec4(0,0,3,1) --- **** NEW | |
currentModelMatrix=modelMatrix() | |
camPos=vec3(0,0,2) | |
z,zd=0,-.01 | |
end | |
function draw() | |
background(0) | |
perspective() | |
camera(camPos.x,camPos.y,camPos.z,0,0,0) | |
currentModelMatrix[15]=z --=currentModelMatrix:translate(0,0,zd) | |
HandleTouches() | |
block.shader.mModel=modelMatrix() | |
block.shader.directColor=diffuseStrength*lightColor*0 | |
block.shader.directDirection = vec4(0,0,1,0):normalize() | |
block.shader.ambientColor = ambientStrength*ambientColor --- ****** NEW | |
block.shader.point1Position=vec4(1,1,1,1):normalize() | |
block.shader.point1Color=color(255) | |
block.shader.eyePosition=camPos | |
block.shader.shine=0 | |
block.shader.point1Range=3 | |
block.shader.point1Strength=1 | |
block:draw() | |
z=z+zd | |
if z<-3 or z>0 then zd=-zd end | |
end | |
--shader follows | |
ADSLighting={ | |
vertexShader=[[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
uniform vec4 directColor; | |
uniform vec4 directDirection; | |
uniform vec4 ambientColor; | |
uniform vec4 point1Position; | |
uniform vec4 point1Color; | |
uniform float point1Strength; | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
attribute vec3 normal; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vPosition; | |
varying lowp vec4 vNormal; | |
varying vec4 vLight; | |
varying vec4 vPoint1Diffuse; | |
void main() | |
{ | |
vColor = color; | |
vTexCoord = texCoord; | |
vPosition = mModel * position; | |
gl_Position = modelViewProjection * position; | |
vNormal = mModel * vec4( normal, 0.0 ); | |
vec4 norm = normalize(vNormal); | |
vLight = ambientColor+directColor * max( 0.0, dot( norm, directDirection )); | |
vec4 d = normalize( point1Position - vPosition ); | |
vPoint1Diffuse = point1Color * point1Strength * max( 0.0, dot( norm, d )); | |
} | |
]], | |
fragmentShader=[[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform vec4 directColor; | |
uniform vec4 directDirection; | |
uniform vec4 eyePosition; | |
uniform float shine; | |
uniform vec4 point1Position; | |
uniform float point1Range; | |
uniform vec4 point1Color; | |
uniform float point1Strength; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vPosition; | |
varying lowp vec4 vNormal; | |
varying vec4 vLight; | |
varying vec4 vPoint1Diffuse; | |
vec4 normalizedNormal = normalize(vNormal); | |
vec4 GetSpecularColor(vec4 lightPosition, vec4 lightColor, bool IsDirectional) | |
{ | |
vec4 lightDirection; | |
if (IsDirectional) lightDirection = lightPosition; | |
else lightDirection = vec4( normalize( lightPosition - vPosition )); | |
vec4 cameraDirection = normalize( eyePosition - vPosition ); | |
vec4 halfAngle = normalize( cameraDirection + lightDirection ); | |
vec4 specularColor = min(lightColor + 0.5, 1.0); | |
float spec = pow( max( 0.0, dot( normalizedNormal, halfAngle)), 32.0 ); | |
return specularColor * spec * shine; | |
} | |
void main() | |
{ | |
lowp vec4 specular=GetSpecularColor(directDirection, directColor, true); | |
float point1Attenuation = max( 0.0, 1.0 - length( point1Position.xyz - vPosition.xyz ) / point1Range ); | |
lowp vec4 point = point1Strength * point1Attenuation * GetSpecularColor(point1Position, point1Color, false); | |
vec4 col = texture2D(texture, vTexCoord) * (vLight + point1Attenuation * vPoint1Diffuse + specular + point); | |
col.a=1.; | |
gl_FragColor=col; | |
} | |
]] | |
} | |
--EVERYTHING BELOW IS UNCHANGED -- | |
function HandleTouches() | |
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 | |
end | |
function CreateBlock(w,h,d,tex,col,pos,ms) --width,height,depth,texture,colour,position,mesh (if existing already) | |
pos=pos or vec3(0,0,0) | |
local x,X,y,Y,z,Z=pos.x-w/2,pos.x+w/2,pos.y-h/2,pos.y+h/2,pos.z-d/2,pos.z+d/2 | |
local v={vec3(x,y,Z),vec3(X,y,Z),vec3(X,Y,Z),vec3(x,Y,Z),vec3(x,y,z),vec3(X,y,z),vec3(X,Y,z),vec3(x,Y,z)} | |
local vert={v[1],v[2],v[3],v[1],v[3],v[4],v[2],v[6],v[7],v[2],v[7],v[3],v[6],v[5],v[8],v[6],v[8],v[7], | |
v[5],v[1],v[4],v[5],v[4],v[8],v[4],v[3],v[7],v[4],v[7],v[8],v[5],v[6],v[2],v[5],v[2],v[1]} | |
local texCoords | |
if tex then | |
local t={vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1)} | |
texCoords={t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3], | |
t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3]} | |
end | |
local n={vec3(0,0,1),vec3(1,0,0),vec3(0,0,-1),vec3(-1,0,0),vec3(0,1,0),vec3(0,-1,0)} | |
local norm={} | |
for i=1,6 do for j=1,6 do norm[#norm+1]=n[i] end end | |
if not ms then ms=mesh() end | |
if ms.size==0 then | |
ms.vertices=vert | |
ms.normals=norm | |
ms.texture,ms.texCoords=tex,texCoords | |
else | |
for i=1,#vert do | |
table.insert(ms.vertices,vert[i]) | |
table.insert(ms.normals,norm[i]) | |
if tex then table.insert(ms.texCoords,texCoords[i]) end | |
end | |
end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
ADSLighting33={ | |
vertexShader=[[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
uniform vec4 directColor; | |
uniform vec4 directDirection; | |
uniform vec4 point1Position; | |
uniform vec4 point1Color; | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
attribute vec3 normal; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vPosition; | |
varying lowp vec4 vNormal; | |
varying vec4 vDirectDiffuse; | |
varying vec4 vPoint1Diffuse; | |
void main() | |
{ | |
vColor = color; | |
gl_Position = modelViewProjection * position; | |
vTexCoord = texCoord; | |
vNormal = mModel * vec4( normal, 0.0 ); | |
vec4 norm = normalize(vNormal); | |
vPosition = mModel * position; | |
vDirectDiffuse = directColor * max( 0.0, dot( norm, directDirection )); | |
vec4 d = normalize( point1Position - vPosition ); | |
vPoint1Diffuse = point1Color * max( 0.0, dot( norm, d )); | |
} | |
]], | |
fragmentShader=[[ | |
precision highp float; | |
uniform vec4 ambientColor; | |
uniform lowp sampler2D texture; | |
uniform float reflec; | |
uniform vec4 directColor; | |
uniform float directStrength; | |
uniform vec4 directDirection; | |
uniform vec4 eyePosition; | |
uniform vec4 specularColor; | |
uniform float specularPower; | |
uniform float shine; | |
uniform vec4 point1Position; | |
uniform float point1Range; | |
uniform vec4 point1Color; | |
uniform float point1Strength; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vPosition; | |
varying lowp vec4 vNormal; | |
varying vec4 vDirectDiffuse; | |
varying vec4 vPoint1Diffuse; | |
vec4 normalizedNormal = normalize(vNormal); | |
vec4 GetSpecularColor(vec4 lightPosition, vec4 lightColor, bool IsDirectional) | |
{ | |
vec4 lightDirection; | |
if (IsDirectional) lightDirection = lightPosition; | |
else lightDirection = vec4( normalize( lightPosition - vPosition )); | |
vec4 cameraDirection = normalize( eyePosition - vPosition ); | |
vec4 halfAngle = normalize( cameraDirection + lightDirection ); | |
vec4 specularColor = min(lightColor + 0.5, 1.0); | |
float spec = pow( max( 0.0, dot( normalizedNormal, halfAngle)), specularPower ); | |
return specularColor * spec * shine; | |
} | |
void main() | |
{ | |
lowp vec4 ambient=vec4(0.,0.,0.,0.); | |
lowp vec4 diffuse=vec4(0.,0.,0.,0.); | |
lowp vec4 specular=vec4(0.,0.,0.,0.); | |
lowp vec4 pixel = texture2D( texture, vTexCoord); | |
ambient = pixel * ambientColor; | |
diffuse = diffuse + pixel * vDirectDiffuse; | |
specular=specular + pixel * directStrength * GetSpecularColor(directDirection, specularColor, true); | |
float r = point1Range; | |
float point1Attenuation = max( 0.0, 1.0 - length( point1Position.xyz - vPosition.xyz ) / r ); | |
float fracSpot=1.0; | |
diffuse = diffuse + pixel * fracSpot * point1Attenuation * vPoint1Diffuse; | |
specular=specular + pixel * fracSpot * point1Attenuation * point1Strength * | |
GetSpecularColor(point1Position, specularColor, false); | |
vec4 totalColor = clamp( reflec * (ambient + diffuse + specular),0.,1.); | |
totalColor.a=1.; | |
gl_FragColor=totalColor; | |
} | |
]] | |
} | |
--# Spot | |
--# Main | |
-- MultiStep | |
function setup() | |
steps = listProjectTabs() | |
if steps[1]=="Notes" then table.remove(steps,1) end --remove first tab if named Notes | |
table.remove(steps) --remove the last tab | |
startStep() | |
global = "select a step" | |
end | |
function showList() | |
output.clear() | |
for i=1,#steps do print(i,steps[i]) end | |
end | |
function startStep() | |
if cleanup then cleanup() end | |
lastStep=Step or readProjectData("lastStep") or 1 | |
lastStep=math.min(lastStep,#steps) | |
saveProjectData("lastStep",lastStep) | |
parameter.clear() | |
parameter.integer("Step", 1, #steps, lastStep,showList) | |
parameter.action("Run", startStep) | |
loadstring(readProjectTab(steps[Step]))() | |
if PrintExplanation then PrintExplanation() end | |
setup() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment