Glowing line shader

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!

By reading the code, it looks interesting, but I can’t try it right now. Thanks!

@Zoyt GLine outlines any polygon with 4 vertices, could have done it based on the point count but I only needed it for a box on my game and GStroke is a line from point a to point b, thanks.

@luatee very nice! Runs 60hz on ipad1 too =D>

@Jmv38 Thanks, 60Fps really? As I said it completely outweighs the other method in terms of speed and at the same time has many more applications. Didn’t think it was that good though :wink:

Finally got a chance to try it. It’s sweet! May I have permission to use it in StackIt? I was literally looking for something like this 2 days ago.
Thanks!

Sure go for it! Glad you like it, it’s more like plasma than a glow though.

@Luatee - It’s actually a better effect than I was looking for. Thanks!

It looks so sexy…

@TheRogueBatcher There are children on here…

@SkyTheCoder kids as young as 5 are being taught about that sort of education if you don’t want to use the word.

@Luatee I don’t understand, what sort of education?

I just think that it’s stupid to say something that looks cool is “sexy.”

Sexual education, and I agree but it’s his choice of words, I can’t argue with that.

I hate to agree, Kids are learning words that are just pointless! Swag being the worst! At least use Swagger, its a real word thats existed for hundreds of years!

School isn’t helping at all, either…

With 150 physics bodies on the screen, it draws at 20fps on my ipad 3

Very nice job @Luatee!

I wonder if I can use this as the basic graphics of a game I’m working on? (ofcourse I’d give credits!)

Nice @stevon8ter.

Wow thanks I didn’t test it thoroughly. You could only for lines though, I’m trying to figure out how to make a fast enough circle glow all the ones I’ve come up with are too slow, using just math no conditionals and it’s still slow.

@Luatee I’m far from a shader expert (well I actually never used it) but I could take a look at the math behind it if you want me to

Also, my game would be all about cubic shapes so yeah :wink:

And note that the physics probably also slows the program down, so my guess is that 150 squares without physics would run around 30fps…

@Luatee - I’m on an iPhone, so my shot at a solution might not be too clear, but here we go: You you basically take the normal shader, then add this at the end to move the x position to cos(pixelX/totalX*6.28+circleDist) and do the same with the y. I actually don’t know that much about how it works, so if I have a bit of extra time, I’ll take a peak.