Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created September 9, 2014 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dermotbalson/dc9a43dd6f585e7dedec to your computer and use it in GitHub Desktop.
Save dermotbalson/dc9a43dd6f585e7dedec to your computer and use it in GitHub Desktop.
Flickering lights
--flickering lights
function setup()
--set up dark area covered by shader
SS_Dark.setup(WIDTH,600,true)
--add an unblinking light that can be moved
L1Pos=vec2(150,175) --initial pos of light1
L1=SS_Dark.AddLight(L1Pos.x,L1Pos.y,150,0)
--add a flickering light (30% flicker)
L2=SS_Dark.AddLight(600,125,150,0.3)
--another light with a bigger flicker
L3=SS_Dark.AddLight(400,325,100,0.6)
print("Drag the first light round the screen with your finger")
end
function draw()
--give ourselves a background behind the dark
sprite("Cargo Bot:Starry Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
SS_Dark.draw() --this draws the dark and the lights
end
--drag L1 light with finger
function touched(t)
if t.state==MOVING then
L1Pos=L1Pos + vec2(t.x-t.prevX,t.y-t.prevY)
SS_Dark.SetLight(L1,nil,L1Pos.x,L1Pos.y) --set new position
end
end
--Darkness and lighting code
--up to 3 lights can be controlled at once
SS_Dark={}
--w, h is width and height of rectangle containing lights
--everything except the lights will be black
--the darkness will fade towards the top if fade=true
function SS_Dark.setup(w,h,fade)
SS_Dark.width=w
SS_Dark.height=h
SS_Dark.Lights={}
SS_Dark.mesh=mesh()
SS_Dark.mesh:addRect(w/2,h/2,w,h)
SS_Dark.mesh.shader=shader(SS_Dark.shader.v,SS_Dark.shader.f)
if fade then SS_Dark.mesh.shader.topY=h else SS_Dark.mesh.shader.topY=0 end
SS_Dark.mesh.shader.lightRadius1=0
SS_Dark.mesh.shader.lightRadius2=0
SS_Dark.mesh.shader.lightRadius3=0
SS_Dark.mesh.shader.lightPos1=vec4(0,0,0,0)
SS_Dark.mesh.shader.lightPos2=vec4(0,0,0,0)
SS_Dark.mesh.shader.lightPos3=vec4(0,0,0,0)
end
--shader lights can't be held in array, must be separate variables
--this next function allocates a new light to the next available shader variable
--making it easy to add and remove lights dynamically without having to worry about what the
--shader calls them
--x,y is position within the dark rectangle
--r is radius of the light
--f is the extent of the flicker (0-1, omit if no flicker)
--returns the id of the light
function SS_Dark.AddLight(x,y,r,f)
local id
for i=1,3 do
if SS_Dark.Lights[i]==nil then id=i break end
end
if not id then return end
if id==1 then
SS_Dark.mesh.shader.lightRadius1=r or 100
SS_Dark.mesh.shader.lightFlicker1=f or 1
SS_Dark.mesh.shader.lightPos1=vec4(x,y,0,1)
elseif id==2 then
SS_Dark.mesh.shader.lightRadius2=r or 100
SS_Dark.mesh.shader.lightFlicker2=f or 1
SS_Dark.mesh.shader.lightPos2=vec4(x,y,0,1)
elseif id==3 then
SS_Dark.mesh.shader.lightRadius3=r or 100
SS_Dark.mesh.shader.lightFlicker3=f or 1
SS_Dark.mesh.shader.lightPos3=vec4(x,y,0,1)
end
--the n variable is included to make the flicker different for each light
SS_Dark.Lights[id]={x=x,y=y,radius=r or 50,flicker=(f or 0),n=math.random()}
return id
end
--use this to change the current flicker or x,y, or radius
function SS_Dark.SetLight(id,f,x,y,r)
if id==1 then
if f then SS_Dark.mesh.shader.lightFlicker1=f end
if x and y then SS_Dark.mesh.shader.lightPos1=vec4(x,y,0,1) end
if r then SS_Dark.mesh.shader.lightRadius1=r end
elseif id==2 then
if f then SS_Dark.mesh.shader.lightFlicker2=f end
if x and y then SS_Dark.mesh.shader.lightPos2=vec4(x,y,0,1) end
if r then SS_Dark.mesh.shader.lightRadius2=r end
elseif id==3 then
if f then SS_Dark.mesh.shader.lightFlicker3=f end
if x and y then SS_Dark.mesh.shader.lightPos3=vec4(x,y,0,1) end
if r then SS_Dark.mesh.shader.lightRadius3=r end
end
end
function SS_Dark.RemoveLight(id)
SS_Dark.Lights[id]=nil
if id==1 then SS_Dark.mesh.shader.lightRadius1=vec2(0,0)
elseif id==2 then SS_Dark.mesh.shader.lightRadius2=vec2(0,0)
elseif id==3 then SS_Dark.mesh.shader.lightRadius3=vec2(0,0)
end
end
function SS_Dark.draw()
--set flicker for current lights
--use noise function to cause flicker
for id=1,3 do
if SS_Dark.Lights[id] ~=nil then
SS_Dark.SetLight(id,1+SS_Dark.Lights[id].flicker*noise(SS_Dark.Lights[id].n+ElapsedTime*2))
end
end
SS_Dark.mesh:draw()
end
--shader
SS_Dark.shader={
v=[[
uniform mat4 modelViewProjection;
attribute vec4 position;
varying highp vec4 vPosition;
void main()
{
vPosition = position;
gl_Position = modelViewProjection * position;
}
]]
,
f=[[
precision highp float;
uniform vec4 lightPos1; //x,y position
uniform vec4 lightPos2; //x,y position
uniform vec4 lightPos3; //x,y position
uniform float lightRadius1;
uniform float lightRadius2;
uniform float lightRadius3;
uniform float lightFlicker1;
uniform float lightFlicker2;
uniform float lightFlicker3;
uniform float topY;
varying highp vec4 vPosition;
void main()
{
highp float d=0.0;
//fade at top of darkness
if (topY>0.) d=clamp(1.0-distance(vPosition,vec4(vPosition.x,topY,0.0,1.0))/100.0,0.0,1.0);
if (lightRadius1>0.0) {
highp float f = lightRadius1 * lightFlicker1;
d=d+clamp(1.0-distance(vPosition,lightPos1)/f+0.1,0.0,1.0);
}
if (lightRadius2>0.0) {
highp float f = lightRadius2 * lightFlicker2;
d=d+clamp(1.0-distance(vPosition,lightPos2)/f+0.1,0.0,1.0);
}
if (lightRadius3>0.0) {
highp float f = lightRadius3 * lightFlicker3;
d=d+clamp(1.0-distance(vPosition,lightPos3)/f+0.1,0.0,1.0);
}
gl_FragColor = vec4(0.,0.,0.,1.0-d);
}
]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment