Page 1 of 1

[SOLVED] love.graphics.stencil problem

Posted: Tue Jul 26, 2022 8:02 am
by siberian
Hello everyone.
I used two calls love.graphics.stencil() function in my program.

Code: Select all

local function stencil_test()
    lg.circle('fill', cx, cy, radius)
end

function love.draw()
    local w, h = lg.getDimensions()
    lg.setCanvas({canvas, stencil = true})
    lg.clear(0.2, 0.2, 0.2)
    
    cx, cy, radius = w/2, h/2, 200
    lg.stencil(stencil_test, 'increment')
    
    cx, cy, radius = w/2, h/2, 50
    lg.stencil(stencil_test, 'decrement')
    --lg.stencil(stencil_test, 'decrementwrap')
    
    lg.setColor(1, 1, 1)
    lg.setStencilTest('greater', 0)
    lg.rectangle('fill', 0, 0, lg.getDimensions())
    lg.setStencilTest()
    
    lg.setCanvas()
    
    lg.draw(canvas)
end
I expected a circle with a hole to appear on the screen. But there is nothing.
If replace 'decrement" with "decrementwrap", only a smaller circle is visible.

Does calling love.graphics.stencil reset stencil buffer? It looks like this.

Re: love.graphics.stencil problem

Posted: Tue Jul 26, 2022 11:18 am
by marclurr
Must admit I've not used stencils before, and I'm not really sure why yours doesn't work without messing about some more, but the below does render a circle with a "hole" in the centre using a stencil. Hope it puts you on the right track.

Code: Select all

local mx = love.graphics.getWidth() / 2
local my = love.graphics.getHeight() /2

local function drawStencil()
    love.graphics.circle("fill", mx, my, 50)
end

function love.draw()
    love.graphics.clear()
    
    love.graphics.stencil(drawStencil, "replace", 1)
    
    love.graphics.setStencilTest("less",1)
    love.graphics.circle("fill", mx, my, 100)
    love.graphics.setStencilTest()
end
Edit: It looks like there's an example on the wiki which is nearly identical to my suggestion, scroll to the second example on this page: https://love2d.org/wiki/love.graphics.setStencilTest

Re: love.graphics.stencil problem

Posted: Tue Jul 26, 2022 12:37 pm
by siberian
I have seen this example.
I don't really need a circle with a hole in it. I ran into a problem when I was making shadows in 3d. And for that you need to draw the shadow volume twice in the stencil with different StencilAction.

Re: love.graphics.stencil problem

Posted: Tue Jul 26, 2022 1:10 pm
by marclurr
Ah I see what you mean. It seems you were just missing a boolean parameter to love.graphics.stencil. By default it clears the current stencil buffer. This new example does the same thing but using two draws to the stencil. The only difference is the boolean true on the second call.

Code: Select all

local mx = love.graphics.getWidth() / 2
local my = love.graphics.getHeight() /2
local r = 100

local function drawStencil()
    love.graphics.circle("fill", mx, my, r)
end

function love.draw()
    love.graphics.clear()
   
    r = 100
    love.graphics.stencil(drawStencil, "increment", 1)
    
    r = 50
    love.graphics.stencil(drawStencil, "decrement", 1, true)
    love.graphics.setStencilTest("equal",1)

    love.graphics.rectangle("fill", 0, 0, 800, 600)
    
    
    love.graphics.setStencilTest()
end
Edit: https://love2d.org/wiki/love.graphics.stencil

Re: love.graphics.stencil problem

Posted: Tue Jul 26, 2022 4:25 pm
by siberian
Thank you so much.
I can't believe I didn't notice that option.