Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created December 9, 2013 11:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dermotbalson/7871147 to your computer and use it in GitHub Desktop.
Save dermotbalson/7871147 to your computer and use it in GitHub Desktop.
3D viewer v1.0
--# Main
--3D Model viewer
function setup()
--saveLocalData("Shuttle.mtl",nil)
loadState=2 -- 0=failed, 1=downloading, 2=ready for next one, 3=all loaded 4=running
parameter.integer("Choose",1,#Models,3)
parameter.action("Load",OBJ.ShowModel)
parameter.integer("Zoom",1,300,50)
parameter.boolean("AutoRotate",true)
parameter.integer("X",-180,180,0)
parameter.integer("Y",-180,180,0)
parameter.integer("Z",-180,180,0)
parameter.action("DeleteStoredData",DeleteData)
parameter.integer("FPS",0,60,60)
--rotate shuttle in all three directions
rot=vec3(0,0,0)
tween( 15, rot, { x = 360 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
tween( 27, rot, { y = 360 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
tween( 35, rot, { z = 360 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
output.clear()
for i=1,#Models do print(i,Models[i].name) end
end
function LoadModel(meshes)
m=meshes
for i=1,#m do --add lighting to each mesh
m[i]:setColors(color(255))
m[i].shader=shader(diffuseShader.vertexShader,diffuseShader.fragmentShader)
local ca,cd,cs
if m[i].settings then
ca = m[i].settings.Ka or color(255)
cd = m[i].settings.Kd or color(255)
cs = m[i].settings.Ks or color(255)
sp = m[i].settings.Ns or 32
if m[i].settings.map then m[i].texture="Documents:z3D"..m[i].settings.map end
else ca,cd=color(255),color(255)
end
local a=0.2
m[i].shader.ambientColor=color(ca.r*a,ca.g*a,ca.b*a,255)
local d=1
m[i].shader.directColor=color(cd.r*d,cd.g*d,cd.b*d)
m[i].shader.directDirection=vec4(-2,1,4,0):normalize()
m[i].shader.specularColor=cs
m[i].shader.specularPower=sp
m[i].shader.shine=1
if m[i].hasNormals~=true then
m[i].normals=CalculateAverageNormals(m[i].vertices,0)
end
m[i].shader.reflect=1
if m[i].texture then m[i].shader.hasTexture=true else m[i].shader.hasTexture=false end
end
output.clear()
for i=1,#Models do print(i,Models[i].name) end
end
function DeleteData()
saveLocalData(Models[Choose].name .. ".mtl",nil)
saveLocalData(Models[Choose].name .. ".obj",nil)
--print("Deleting "..Models[Choose].name .. ".mtl")
--print("Deleting "..Models[Choose].name .. ".obj")
if Models[Choose].images then
for i=2,#Models[Choose].images,2 do
--print("Deleting "..Models[Choose].images[i])
saveImage("Documents:z3Dspstob_1",nil)
end
end
end
function draw()
background(116, 173, 182, 255)
FPS=FPS*0.9+0.1/DeltaTime
if dataStatus~='Ready' then return end
if touchPos then
if touchImg==nil then
touchImg=image(WIDTH,HEIGHT)
setContext(touchImg)
else
local a,b=touchImg:get(touchPos.x,touchPos.y)
--print("Vertex="..a*256+b)
touchPos=nil
touchImg=nil
end
end
perspective()
camera(0,0,Zoom,0,0,-Zoom)
pushMatrix()
if AutoRotate then
rotate(rot.x,1,0,0)
rotate(rot.y,0,1,0)
rotate(rot.z,0,0,1)
else
rotate(X,1,0,0)
rotate(Y,0,1,0)
rotate(Z,0,0,1)
end
if m then
for i=1,#m do
if touchPos then
m[i].shader.useIndex=true
m[i].colors=m[i].C2
else
m[i].shader.useIndex=false
--m[i]:setColors(m[i].C1)
end
m[i].shader.mModel=modelMatrix() --part of lighting
m[i].shader.eyePosition=vec3(0,0,Zoom)
m[i]:draw()
end
end
popMatrix()
if touchPos then setContext() end
end
function GetColor(n)
local b=math.fmod(n,256)
local a=(n-b)/255
return color(a,b,0)
end
function touched(t)
if t.state==BEGAN then
touchPos=vec2(t.x,t.y)
end
end
function CalculateNormals(vertices)
--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
function CalculateAverageNormals(vertices,f)
--average normals at each vertex
--first get a list of unique vertices, concatenate the x,y,z values as a key
local norm,unique= {},{}
for i=1, #vertices do
unique[vertices[i].x ..vertices[i].y..vertices[i].z]=vec3(0,0,0)
end
--calculate normals, add them up for each vertex and keep count
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])
for j=0,2 do
local v=vertices[i+j].x ..vertices[i+j].y..vertices[i+j].z
unique[v]=unique[v]+n
end
end
--calculate average for each unique vertex
for i=1,#unique do
unique[i] = unique[i]:normalize()
end
--now apply averages to list of vertices
for i=1, #vertices,3 do --calculate average
local n = (vertices[i+1] - vertices[i]):cross(vertices[i+2] - vertices[i])
for j=0,2 do
norm[i+j] = unique[vertices[i+j].x ..vertices[i+j].y..vertices[i+j].z]
end
end
return norm
end
--# OBJ
--OBJ library
OBJ={}
function OBJ.SetupModel()
local s=readLocalData(OBJ.model..".mtl")
if s then
OBJ.mtl={}
local mname
for line in s:gmatch("[^\r\n]+") do
line=OBJ.trim(line)
if string.find(line,"newmtl") then
mname=OBJ.GetValue(line)
OBJ.mtl[mname]={}
--print(mname)
else
local code=string.sub(line,1,2)
if code=="Ka" then --ambient
OBJ.mtl[mname].Ka=OBJ.GetColor(line)
--print(mname,"Ka",OBJ.mtl[mname].Ka[1],OBJ.mtl[mname].Ka[2],OBJ.mtl[mname].Ka[3])
elseif code=="Kd" then --diffuse
OBJ.mtl[mname].Kd=OBJ.GetColor(line)
--print(mname,"Kd",OBJ.mtl[mname].Kd[1],OBJ.mtl[mname].Kd[2],OBJ.mtl[mname].Kd[3])
elseif code=="Ks" then --specular
OBJ.mtl[mname].Ks=OBJ.GetColor(line)
--print(mname,"Ks",OBJ.mtl[mname].Ks[1],OBJ.mtl[mname].Ks[2],OBJ.mtl[mname].Ks[3])
elseif code=="Ns" then --specular exponent
OBJ.mtl[mname].Ns=OBJ.GetValue(line)
--print(mname,"Ns",OBJ.mtl[mname].Ns)
elseif code=="ill" then --illumination code
OBJ.mtl[mname].illum=OBJ.GetValue(line)
--print(mname,"illum",OBJ.mtl[mname].illum)
elseif code=="ma" then --texture map name
local u=OBJ.split(OBJ.GetValue(line),"\\")
--print(line,"=",string.sub(u[#u],1,string.find(u[#u],".\")-1))
OBJ.mtl[mname].map=string.sub(u[#u],1,string.find(u[#u],"%.")-1)
--print(mname,OBJ.mtl[mname].map)
end
end
end
else
print("ERROR:"..OBJ.model..".mtl could not be loaded")
return
end
local s=readLocalData(OBJ.model..".obj")
if s then
--read in groups of data into separate meshes
OBJ.m={}
local p, v, tx, t, np, n={},{},{},{},{},{}
local mname
for line in s:gmatch("[^\r\n]+") do
line=OBJ.trim(line)
local code=string.sub(line,1,2)
--look for material settings, a separate mesh is used for each
if string.find(line,"usemtl") then
if mname then
local m=mesh()
m.vertices=v
if #t>0 then m.texCoords=t end
if #n>0 then m.normals=n end
m.settings=OBJ.mtl[mname]
OBJ.m[#OBJ.m+1]=m
--print(#p)
end
mname=OBJ.GetValue(line)
v,t,n={},{},{}
--print(mname)
end
if code=="v " then --point position
p[#p+1]=OBJ.GetVec3(line)
elseif code=="vn" then --point normal
np[#np+1]=OBJ.GetVec3(line)
elseif code=="vt" then --texture co-ord
tx[#tx+1]=OBJ.GetVec2(line)
elseif code=="f " then --vertex
local pts,ptex,pnorm=OBJ.GetList(line)
if #pts==3 then
for i=1,3 do v[#v+1]=p[tonumber(pts[i])] end
if ptex then for i=1,3 do t[#t+1]=tx[tonumber(ptex[i])] end end
if pnorm then for i=1,3 do n[#n+1]=np[tonumber(pnorm[i])] end end
elseif #pts==4 then
for i=1,3 do v[#v+1]=p[tonumber(pts[i])] end
if ptex then for i=1,3 do t[#t+1]=tx[tonumber(ptex[i])] end end
if pnorm then for i=1,3 do n[#n+1]=np[tonumber(pnorm[i])] end end
v[#v+1]=p[tonumber(pts[3])]
if ptex then t[#t+1]=tx[tonumber(ptex[3])] end
if pnorm then n[#n+1]=np[tonumber(pnorm[3])] end
v[#v+1]=p[tonumber(pts[4])]
if ptex then t[#t+1]=tx[tonumber(ptex[4])] end
if pnorm then n[#n+1]=np[tonumber(pnorm[4])] end
v[#v+1]=p[tonumber(pts[1])]
if ptex then t[#t+1]=tx[tonumber(ptex[1])] end
if pnorm then n[#n+1]=np[tonumber(pnorm[1])] end
elseif #pts>4 then
local cx,cy,cz=0,0,0
local ttx,tty=0,0
local nx,ny,nz=0,0,0
for i=1,#pts do
local u=p[tonumber(pts[i])] cx,cy,cz=cx+u.x,cy+u.y,cz+u.z
if ptex then local u=tx[tonumber(ptex[i])] ttx,tty=ttx+u.x,tty+u.y end
--if pnorm then local u=p[tonumber(pnorm[i])] nx,ny,nz=nx+u.x,ny+u.y,nz+u.z end
end
local cp=vec3(cx/#pts,cy/#pts,cz/#pts)
if ptex then ct=vec2(ttx/#pts,tty/#pts) end
--if pnorm then cn=vec3(nx/#pts,ny/#pts,nz/#pts):normalize() end
local j
for i=1,#pts do
if i<#pts then j=i+1 else j=1 end
v[#v+1]=p[tonumber(pts[i])]
if ptex then t[#t+1]=tx[tonumber(ptex[i])] end
--if pnorm then n[#n+1]=np[tonumber(pnorm[i])] end
v[#v+1]=p[tonumber(pts[j])]
if ptex then t[#t+1]=tx[tonumber(ptex[j])] end
--if pnorm then n[#n+1]=np[tonumber(pnorm[j])] end
v[#v+1]=cp
if ptex then t[#t+1]=ct end
--if pnorm then n[#n+1]=np[tonumber(cn)] end
end
end
end
end
local m=mesh()
m.vertices=v
if #t>0 then m.texCoords=t end
if #n>0 then m.normals=n end
m.settings=OBJ.mtl[mname]
OBJ.m[#OBJ.m+1]=m
--for i=1,#OBJ.m do print(i,#OBJ.m[i].texCoords) end
return OBJ.m
else
print("ERROR:"..OBJ.model..".obj could not be loaded")
return
end
end
function OBJ.GetColor(s)
local s1=string.find(s," ")
local s2=string.find(s," ",s1+1)
local s3=string.find(s," ",s2+1)
return color(string.sub(s,s1+1,s2-1)*255,string.sub(s,s2+1,s3-1)*255,string.sub(s,s3+1,string.len(s))*255)
end
function OBJ.GetVec3(s)
local s1=string.find(s," ")
local s2=string.find(s," ",s1+1)
local s3=string.find(s," ",s2+1)
return vec3(math.floor(string.sub(s,s1+1,s2-1)*100)/100,
math.floor(string.sub(s,s2+1,s3-1)*100)/100,
math.floor(string.sub(s,s3+1,string.len(s))*100)/100)
end
function OBJ.GetVec2(s)
local s1=string.find(s," ")
local s2=string.find(s," ",s1+1)
return vec2(math.floor(string.sub(s,s1+1,s2-1)*100)/100,
math.floor(string.sub(s,s2+1,string.len(s))*100)/100)
end
function OBJ.GetValue(s)
return string.sub(s,string.find(s," ")+1,string.len(s))
end
function OBJ.trim(s)
while string.find(s," ") do s = string.gsub(s," "," ") end
return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)'
end
function OBJ.split(s,sep)
sep=sep or "/"
local p={}
local pattern = string.format("([^%s]+)", sep)
string.gsub(s,pattern, function(c) p[#p+1] = c end)
return p
end
function OBJ.GetList(s)
local p,t,n={},{},{}
--for word in s:gmatch("%w+") do table.insert(p, word) end
p=OBJ.split(s," ")
table.remove(p,1)
for i=1,#p do
local a=OBJ.split(p[i])
if #a==1 then
p[i]=a[1]
elseif #a==2 then
p[i]=a[1]
t[i]=a[2]
elseif #a==3 then
p[i]=a[1]
t[i]=a[2]
n[i]=a[3]
end
end
return p,t,n
end
function setup0()
s="f 1000/2000 3000/4000 5000/6000"
p,t=OBJ.GetList(s)
for i=1,#p do print(i,p[i],t[i]) end
end
function draw0() end
--# Assets
--Assets
Models={
{name="AllianceStarFighter",
mtl="https://gist.github.com/dermotbalson/7853224/raw/4531e3e1ef1e564dd38835926006b8a677b24c65/gistfile1.txt",
obj="https://gist.github.com/dermotbalson/7853222/raw/bc75e086a6fa11cc48c62ef4c3a7efc452529861/gistfile1.txt"},
{name="Lunar_lander",
mtl="https://gist.github.com/dermotbalson/7854557/raw/a6a2e2dd687650c5b93c166e0c3ddf0e5df1dd4d/gistfile1.txt",
obj="https://gist.github.com/dermotbalson/7854555/raw/0f1dffb2263814cf47145418c3af41d872628576/gistfile1.txt"},
{name="Me262",
mtl="https://gist.github.com/dermotbalson/7858260/raw/78dd90b5c6760b0a28df49ab9354091df8b34bef/gistfile1.txt",
obj="https://gist.github.com/dermotbalson/7858284/raw/b5b4acea32f09a6a9583088a1b307a9abdd01ae0/gistfile1.txt",
images={"http://i1303.photobucket.com/albums/ag142/ignatz_mouse/3D%20-%20Me262/",
"Material__2noCulling","Material__2noCulling_zps9ac9abf8.jpg",
"fusR2noCulling","fusR2noCulling_zps815a3aa9.jpg",
"fusR1noCulling","3D%20-%20Me262/fusR1noCulling_zps2307cad9.jpg",
"fusL1noCulling","3D%20-%20Me262/fusL1noCulling_zpsb2ec3384.jpg",
"engine_1noCulling","engine1noCulling_zpsc9e864fb.jpg",
"_2_1noCulling","_2_1noCulling_zps3af25934.jpg",
"fuselage1noCulling","fuselage1noCulling_zps5ec01367.jpg",
"elevlowL1_1noCulling","elevlowL1_1noCulling_zps92e9007f.jpg",
"elevlowR1noCulling","elevlowR1noCulling_zpsf5d3b587.jpg",
"engine_1noCulling","engine_1noCulling_zps84731447.jpg",
"_22_-_Default1noCulling","_22_-_Default1noCulling_zpsc34b8ed4.jpg",
"_2noCulling","_2noCulling_zpsdb6ae3da.jpg",
"_20_-_Default1noCulling","_20_-_Default1noCulling_zpsab9ada71.jpg",
"wgtopR1noCulling","wgtopR1noCulling_zps01fcba8b.jpg",
"Material__4noCulling","Material__4noCulling_zps57a72fa9.jpg",
"_1noCulling","_1noCulling_zps8d87449d.jpg",
"shield2noCulling","shield2noCulling_zpsd7ab3209.jpg",
"Material__1noCulling","Material__1noCulling_zpseb4845ed.jpg",
"shield1noCulling","shield1noCulling_zpsaa6f4423.jpg",
"Material__3noCulling","Material__3noCulling_zps4422f8d9.jpg"}},
{name="Me262a",
obj="https://gist.github.com/dermotbalson/7866473/raw/57750a8a7a2763db3cb3871eff329a3380a41719/gistfile1.txt",
mtl="https://gist.github.com/dermotbalson/7866500/raw/204a07273c5e1eba1921b0d8dd050d598ae515fd/gistfile1.txt",
images={"http://i1303.photobucket.com/albums/ag142/ignatz_mouse/3D%20-%20Me262/",
"Me262Texture","Me262Texture_zps9a5c6ab4.jpg"}},
{name="TIE",
mtl="https://gist.github.com/dermotbalson/7867711/raw/5bd1d273eb76f2ab0521019a8bf14f62dd35eabe/gistfile1.txt",
obj="https://gist.github.com/dermotbalson/7867714/raw/568570cb2bcc9ccc325f933f6e72609e92f80e8d/gistfile1.txt",
images={"http://i1303.photobucket.com/albums/ag142/ignatz_mouse/TIE2/",
"White_p0","White_p0_zpse833d35d.jpg",
"Pottery_clay","Pottery_clay_zps0dd8067f.jpg",
"Flat_white","Flat_white_zps90fee47d.jpg",
"Metallic_Varnish","Metallic_Varnish_zps9d47ede3.jpg",
"GRAY","GRAY_zps3b6c9a13.jpg",
"Pottery","Pottery__zpsf04e3b44.jpg",
"Flat_whi","Flat_whi_zps3db708fa.jpg",
"GREY_DARK","GREY_DARK_zps10890cbe.jpg",
"Metallic","Metallic_zps3f042630.jpg",
"GREY_DAR","GREY_DAR_zps93b978ef.jpg",
"Blue_glass","Blue_glass_zps3df479ac.jpg",
"Blue_gla","Blue_gla_zps85ce7ffa.jpg",
"BLAST_RED1","BLAST_RED1_zps955b974e.jpg",
"BLAST_R1","BLAST_R1_zpse6832a58.jpg",
"BLAST_RED0","BLAST_RED0_zpsdcb29c70.jpg",
"A_TIE_WI","A_TIE_WI_zps98da0a2f.jpg",
"White_porcelain3","White_porcelain3_zpsb19c4e77.jpg",
"A_TIE_WINDOW","A_TIE_WINDOW_zpscf0b2fc1.jpg",
"BLAST_R0","BLAST_R0_zpsdc173ba1.jpg",
"White_porcelain2","White_porcelain2_zps8380f151.jpg",
"White_p2","White_p2_zps14f2790e.jpg",
"White_p3","White_p3_zps05b2dde8.jpg",
"White_porcelain1","White_porcelain1_zpsd73396c8.jpg",
"White_porcelain0","White_porcelain0_zps839c6206.jpg",
"White_p1","White_p1_zps59e0fa3c.jpg",
"White_p0","White_p0_zpse833d35d.jpg"}},
{name="Shuttle",
mtl="https://gist.github.com/dermotbalson/7868340/raw/8d9daf6171c47040deaa1aa8c8315bb8bec0d95e/gistfile1.txt",
obj="https://gist.github.com/dermotbalson/7868345/raw/e5c3c9b66dc6ae179ad797b8cc833f93939351da/gistfile1.txt",
images={"http://i1303.photobucket.com/albums/ag142/ignatz_mouse/Shuttle5/",
"spstob_1","spstob_1_zpsb14b8e49.jpg",
"spstob_2","spstob_2_zps60610a11.jpg",
"spstob_4","spstob_4_zps95834fee.jpg",
"spstob_e","spstob_e_zpsfdb1dd94.jpg",
"spstob_3","spstob_3_zps5b08c82c.jpg"}}
}
--# AssetLoader
--Asset loader
function OBJ.ShowModel()
OBJ.m=Choose
OBJ.model=Models[OBJ.m].name
OBJ.assetTable={}
OBJ.LoadModel()
end
function OBJ.LoadModel()
output.clear()
--pass through Codea name of file and internet url
--if not in Codea, will be downloaded and saved
OBJ.LoadAsset(OBJ.model..".mtl",Models[OBJ.m].mtl)
OBJ.LoadAsset(OBJ.model..".obj",Models[OBJ.m].obj)
if Models[OBJ.m].images then
local path=Models[OBJ.m].images[1]
for i=2,#Models[OBJ.m].images,2 do
OBJ.LoadAsset(Models[OBJ.m].images[i],path..Models[OBJ.m].images[i+1])
end
--else print("No images")
end
if #OBJ.assetTable==0 then
dataStatus='Ready' --tells draw it's ok to draw the scene
local m= OBJ.SetupModel()
LoadModel(m)
end
end
--downloads assets one by one
function OBJ.LoadAsset(fileName,url)
if OBJ.IsObjFile(fileName) then
local i=readLocalData(fileName)
if i~=nil then return i end
else
local i=readImage("Documents:z3D"..fileName)
if i then return i end
end
--print(fileName.." not found")
--not found, we need to download, add to queue (ie table)
OBJ.assetTable[#OBJ.assetTable+1]={name=fileName,url=url}
print('Queueing',fileName)
dataStatus='Loading'
--if the first one, go ahead and download
if #OBJ.assetTable==1 then
http.request(OBJ.assetTable[1].url,OBJ.AssetDownloaded)
print('loading',OBJ.assetTable[1].name)
end
end
--saves downloaded images
function OBJ.AssetDownloaded(data)
--print(OBJ.assetTable[1].name,'loaded')
if OBJ.IsObjFile(OBJ.assetTable[1].name) then
saveLocalData(OBJ.assetTable[1].name,data) --save
local i=readLocalData(OBJ.assetTable[1].name)
if i~=data then print("ERROR in saving "..OBJ.assetTable[1].name) else
print("Saved"..OBJ.assetTable[1].name) end
else
saveImage("Documents:z3D"..OBJ.assetTable[1].name,data) --save
print("Saved "..OBJ.assetTable[1].name)
end
table.remove(OBJ.assetTable,1)
--load next one if we have any more to do
if #OBJ.assetTable>0 then
http.request(OBJ.assetTable[1].url,OBJ.AssetDownloaded)
print('loading',OBJ.assetTable[1].name)
else
OBJ.LoadModel()
end
end
function OBJ.IsObjFile(f)
local ff=string.upper(f)
if string.find(ff,".OBJ") or string.find(ff,".MTL") then return true else return false end
end
--# Shader
--# Shader2
diffuseShader={
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 lowp vec4 vPosition;
varying lowp vec4 vNormal;
varying vec4 vDirectDiffuse;
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 ));
}
]],
fragmentShader=[[
precision highp float;
uniform vec4 ambientColor;
uniform lowp sampler2D texture;
uniform float reflect;
uniform bool hasTexture;
uniform vec4 directColor;
uniform float directStrength;
uniform vec4 directDirection;
uniform vec4 eyePosition;
uniform vec4 specularColor;
uniform float specularPower;
uniform float shine;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
varying lowp vec4 vPosition;
varying lowp vec4 vNormal;
varying vec4 vDirectDiffuse;
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;
if (hasTexture) pixel = texture2D( texture, vTexCoord);
else pixel = vColor;
ambient = pixel * ambientColor;
diffuse = diffuse + pixel * vDirectDiffuse;
specular=specular + pixel * directStrength * GetSpecularColor(directDirection, specularColor, true);
vec4 totalColor = clamp( reflect * (ambient + diffuse + specular),0.,1.);
totalColor.a=1.;
gl_FragColor=totalColor;
}
]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment