As some of you might know I added a little glow effect to the physgun in my game for when objects are being held, well as fewer of you may know it doesn’t perform too well with big objects, so I thought I would take a basic line shader and add the glowing effect I was looking for, this time it actually glows which is what I was aiming for the first time.
Here’s the code:
--# GLine
GLine = class()
function GLine:init(ent,width)
-- you can accept and set parameters here
self.m = mesh()
self.r = {}
local pos1 = nil
local pos2 = nil
for i=1,4 do
if i == 1 then
pos1 = ent.points[i]
pos2 = ent.points[4]
else
pos1 = ent.points[i]
pos2 = ent.points[i-1]
end
local d = (pos1-pos2)
self.r[i] = self.m:addRect(pos1.x-d.x/2,pos1.y-d.y/2,d:len(),width*5,angleOfPoint(d)/mp)
end
self.m.shader = shader(shadr.vS,shadr.fS)
self.m.shader.color = vec4(0,1,2,1)
self.m.shader.len = (ent.points[1]-ent.position):len()/45
self.width = width
end
function GLine:setPositions(ent)
local pos1,pos2
for i=1,4 do
if i == 1 then
pos1 = ent.points[i]:rotate(ent.angle/mp)
pos2 = ent.points[4]:rotate(ent.angle/mp)
else
pos1 = ent.points[i]:rotate(ent.angle/mp)
pos2 = ent.points[i-1]:rotate(ent.angle/mp)
end
local d = (pos1-pos2)
self.m:setRect(self.r[i],ent.x+pos1.x-d.x/2,ent.y+pos1.y-d.y/2,d:len(),self.width*5,angleOfPoint(d)/mp)
end
self.m.shader.len = (ent.points[1]-ent.position):len()/45
end
function GLine:draw()
self.m.shader.time = ElapsedTime*2
self.m:draw()
end
function GLine:touched(touch)
-- Codea does not automatically call this method
end
shadr = {vS = [[
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
//Pass the mesh color to the fragment shader
vColor = color;
vTexCoord = texCoord;
//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
]],
fS = [[
varying highp vec2 vTexCoord;
uniform lowp vec4 color;
uniform highp float time;
uniform highp float len;
void main()
{
highp float mp = sin(time*4.0+(25.0*vTexCoord.x)*0.03*len)*
sin(time*10.0+25.0*vTexCoord.x*0.055*len)*1.9+3.0;
mediump vec2 vTexCoordn = 1.0-2.0*vec2(vTexCoord.x,vTexCoord.y);
lowp float dist = sqrt(vTexCoordn.x*vTexCoordn.x+vTexCoordn.y*vTexCoordn.y);
vTexCoordn.x = 0.0;
//Premult
gl_FragColor = color*(1.4-length(vTexCoordn)*0.7*mp-dist);
}
]]}
-- Codea does not automatically call this method
--# GStroke
GStroke = class()
function GStroke:init(pos1,pos2,width)
-- you can accept and set parameters here
self.pos1 = pos1
self.pos2 = pos2
self.m = mesh()
self.m.shader = shader(shadr.vS,shadr.fS)
self.m.shader.color = vec4(0,1,2,0.8)
local d = (pos1-pos2)
self.m.shader.len = d:len()/5
self.r = self.m:addRect(pos1.x-d.x/2,pos1.y-d.y/2,d:len(),width*5,angleOfPoint(d)/mp)
self.width = width
end
function GStroke:setPositions(pos1,pos2)
self.pos1 = pos1
self.pos2 = pos2
local d = (pos1-pos2)
self.m.shader.len = d:len()/5
self.m:setRect(self.r,pos1.x-d.x/2,pos1.y-d.y/2,d:len(),self.width*5,angleOfPoint(d)/mp)
end
function GStroke:draw()
self.m.shader.time = ElapsedTime*5
self.m:draw()
end
function GStroke:touched(touch)
-- Codea does not automatically call this method
end
--# Main
mp = (180/math.pi)
function angleOfPoint( pt )
local ang = math.atan2(pt.y,pt.x)*(180/math.pi)
if ang < 0 then ang = 360+ang elseif ang > 360 then ang = 0+(ang-360) end
return ang
end
function setup()
pos = vec2(WIDTH/2,HEIGHT/2)
body = physics.body(POLYGON,vec2(-40,-40),vec2(-40,40),vec2(40,40),vec2(40,-40))
body.position = pos
lines = GLine(body,5)
lines.m.shader.color = vec4(2,1,0,1)
floor = physics.body(POLYGON,vec2(-WIDTH/2,-5),vec2(-WIDTH/2,5),vec2(WIDTH/2,5),vec2(WIDTH/2,-5))
floor.position = vec2(WIDTH/2,5)
flines = GLine(floor,4)
flines.m.shader.color = vec4(1,1,1,1)
floor.type = STATIC
holding = nil
tline = nil
end
function draw()
background(50,255)
flines:setPositions(floor)
flines:draw()
lines:setPositions(body)
lines:draw()
if holding then
local dist = vec2(holding.x,holding.y):dist(body.position)
body:applyForce((vec2(holding.x,holding.y)-body.position)*(dist/250)-body.linearVelocity/10)
tline:setPositions(body.position,vec2(holding.x,holding.y))
tline:draw()
end
text(1/DeltaTime,200,100)
end
function touched(t)
if t.state == BEGAN and body:testPoint(vec2(t.x,t.y)) then
holding = t
tline = GStroke(body.position,vec2(t.x,t.y),5)
end
if holding ~= nil then
holding = t
end
if t.state == ENDED then
holding = nil
tline = nil
end
end
This is a little example of what it can be used for, hope you enjoy it, I was looking for one of these for 2D for ages! But I thought I might as well try and write my own, the performance is much better!