Page 2 of 2

Re: Missile Command Splosion Effect

Posted: Tue Dec 29, 2015 7:04 pm
by Davidobot
An interesting solution to this problem, without using any shaders would be to use the wonderful stencils.
Note: You cannot pass variables to stencils and need to make all the values global for that file at least. (the following is untested psuedo code)

Code: Select all

local r, x, y = 100, 200, 200
local function circleStencil()
   love.graphics.circle("fill", x, y, r, 50)
end

function love.draw()
     r, x, y = -- Whatever the first explosion is
     love.graphics.stencil(circleStencil, "increment", 1, false) -- This increments and clears the previous frame's the shader buffer (think of it as a depth buffer) in the circle's region by 1
     r, x, y = -- Whatever the second explosion is
     love.graphics.stencil(circleStencil, "increment", 1, true) -- The true ensures that the shader buffer is retained 

    -- Only allow rendering on pixels which have a stencil value less than or equal to 1 (not in intersection).
    love.graphics.setStencilTest("lequal", 1)
    -- Draw all explosions with the yellow color

     -- Only allow rendering on pixels which have a stencil value greater than 1 (in intersection).
    love.graphics.setStencilTest("greater", 1)
    -- Draw all explosions with the green color
end
EDIT: Found and fixed a small logical error with the shader buffer clearing and added more explanations.

Re: Missile Command Splosion Effect

Posted: Tue Dec 29, 2015 7:35 pm
by slime
Davidobot wrote:Note: You cannot pass variables to stencils and need to make all the values global for that file at least.
You can pass a local or anonymous function which will capture local variables from the scope that the function was defined in.

For example:

Code: Select all

function love.draw()
    local x1, y1 = 100, 100
    local r1 = 100

    local x2, y2 = 200, 100
    local r2 = 200

    local function drawCircles()
        love.graphics.circle("fill", x1, y1, r1)
        love.graphics.circle("fill", x2, y2, r2)
    end

    -- Anywhere touched by any circle will have its stencil value increased by 1 (so it'll be at least 2, where they overlap).
    love.graphics.stencil(drawCircles, "increment")

    -- love.graphics.setStencilTest etc.
end
It's also a bit more efficient to batch things up into fewer love.graphics.stencil calls if possible (i.e. doing multiple draws in a single stencil).

Re: Missile Command Splosion Effect

Posted: Wed Dec 30, 2015 5:35 am
by Davidobot
slime wrote: You can pass a local or anonymous function which will capture local variables from the scope that the function was defined in.
Oh, that's interesting, but meant it more like can't do this:

Code: Select all

love.graphics.stencil(stencilFun(x, y, r), "increment")
slime wrote: It's also a bit more efficient to batch things up into fewer love.graphics.stencil calls if possible (i.e. doing multiple draws in a single stencil).
Ooh, alright! Will that have the exact same effect as my code? (Result in numbers of 2 and higher in intersecting areas)? EDIT: Yes it does.

I modified OP's code to implement this method, works flawlessly:
Image
Image