How do I use stencil?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
How do I use stencil?
I'm trying to use stencils to make it so when a certain object spawns in my game, it can only be drawn on tiles from Tiled, and not on the background. I've looked at the wiki but trying to implement it gives me a headache :/
The wiki shows it all in one file, main.lua, but my stuff is spread out, all the tiled stuff is in the map_loader, and the object i wanna draw is in its own file as well, my major issue is figuring out what goes where, so if I could get some help that'd be awesome
The wiki shows it all in one file, main.lua, but my stuff is spread out, all the tiled stuff is in the map_loader, and the object i wanna draw is in its own file as well, my major issue is figuring out what goes where, so if I could get some help that'd be awesome
Re: How do I use stencil?
Only you know the organization of your game, but the functionality is as follows.
You can see the stencil as an invisible mask, similar to an alpha layer, but only yes/no. When the stencil is active, a pixel is either drawn or not drawn, even if the values of the mask can be in 0-255; there's no opacity. You control the mask value threshold for a pixel to be drawn.
You draw to that mask (the stencil) with regular draw functions. What gets drawn in the stencil and what gets drawn in the screen, is decided by whether you're drawing inside the stencil function or outside. For example:
The "replace" mode means that the pixels that are drawn will all be set in the mask to the value we supply (1 in this case). The colour and alpha you choose doesn't matter; everything you draw, be it a circle, a rectangle, lines, or whatever, will have the value 1. Since we're setting 'keepvalues' to false, the mask will be cleared before drawing anything to it (similar to a love.graphics.clear of the mask).
The rectangle will be drawn to the stencil; the circle will be drawn to the screen.
Note that once the stencil is drawn to, you have to specify the threshold value for a pixel to be drawable. That's what setStencilTest does. In this case, we're saying that any value greater than zero is drawable. We have drawn the rectangle with the value 1, so all the pixels in the rectangle will be drawable.
Now, as for how to adapt it to your game, exactly how is up to you, but it boils down to this. You would draw the tiles to the stencil as well as to the screen. Assuming you don't need the stencil for other uses, you can just draw the tiles to the screen and to the stencil at the same point of the code. For example:
That prepares the stencil. Then before drawing the objects to spawn, you do:
and when you finish drawing the objects to spawn, you do:
That should be all.
You can see the stencil as an invisible mask, similar to an alpha layer, but only yes/no. When the stencil is active, a pixel is either drawn or not drawn, even if the values of the mask can be in 0-255; there's no opacity. You control the mask value threshold for a pixel to be drawn.
You draw to that mask (the stencil) with regular draw functions. What gets drawn in the stencil and what gets drawn in the screen, is decided by whether you're drawing inside the stencil function or outside. For example:
Code: Select all
love.graphics.stencil(function ()
love.graphics.rectangle("fill", 10, 10, 20, 20)
end,
"replace", 1, false)
love.graphics.setStencilTest("greater", 0)
love.graphics.circle("fill", 30, 30, 20)
The rectangle will be drawn to the stencil; the circle will be drawn to the screen.
Note that once the stencil is drawn to, you have to specify the threshold value for a pixel to be drawable. That's what setStencilTest does. In this case, we're saying that any value greater than zero is drawable. We have drawn the rectangle with the value 1, so all the pixels in the rectangle will be drawable.
Now, as for how to adapt it to your game, exactly how is up to you, but it boils down to this. You would draw the tiles to the stencil as well as to the screen. Assuming you don't need the stencil for other uses, you can just draw the tiles to the screen and to the stencil at the same point of the code. For example:
Code: Select all
local function myStencilFunction()
drawTiles()
end
...
drawTiles()
love.graphics.stencil(myStencilFunction) -- default values for the rest are OK
Code: Select all
love.graphics.setStencilTest("greater", 0)
Code: Select all
love.graphics.setStencilTest()
Re: How do I use stencil?
pgimeno wrote:Only you know the organization of your game, but the functionality is as follows.
You can see the stencil as an invisible mask, similar to an alpha layer, but only yes/no. When the stencil is active, a pixel is either drawn or not drawn, even if the values of the mask can be in 0-255; there's no opacity. You control the mask value threshold for a pixel to be drawn.
You draw to that mask (the stencil) with regular draw functions. What gets drawn in the stencil and what gets drawn in the screen, is decided by whether you're drawing inside the stencil function or outside. For example:The "replace" mode means that the pixels that are drawn will all be set in the mask to the value we supply (1 in this case). The colour and alpha you choose doesn't matter; everything you draw, be it a circle, a rectangle, lines, or whatever, will have the value 1. Since we're setting 'keepvalues' to false, the mask will be cleared before drawing anything to it (similar to a love.graphics.clear of the mask).Code: Select all
love.graphics.stencil(function () love.graphics.rectangle("fill", 10, 10, 20, 20) end, "replace", 1, false) love.graphics.setStencilTest("greater", 0) love.graphics.circle("fill", 30, 30, 20)
The rectangle will be drawn to the stencil; the circle will be drawn to the screen.
Note that once the stencil is drawn to, you have to specify the threshold value for a pixel to be drawable. That's what setStencilTest does. In this case, we're saying that any value greater than zero is drawable. We have drawn the rectangle with the value 1, so all the pixels in the rectangle will be drawable.
Now, as for how to adapt it to your game, exactly how is up to you, but it boils down to this. You would draw the tiles to the stencil as well as to the screen. Assuming you don't need the stencil for other uses, you can just draw the tiles to the screen and to the stencil at the same point of the code. For example:That prepares the stencil. Then before drawing the objects to spawn, you do:Code: Select all
local function myStencilFunction() drawTiles() end ... drawTiles() love.graphics.stencil(myStencilFunction) -- default values for the rest are OK
and when you finish drawing the objects to spawn, you do:Code: Select all
love.graphics.setStencilTest("greater", 0)
That should be all.Code: Select all
love.graphics.setStencilTest()
So if I understand correctly, in my case I'd be putting the DRAW_MAP_LOADER() stuff in the stencil function?
https://love2d.org/imgmirrur/tXwdGgH.png
Sorry, on my phone right now haha
Re: How do I use stencil?
Can't say for sure without looking at your full code, but it seems so. If you want the map to act as a mask for your spawning objects, you'll have to draw the map to the mask (=the stencil).
Edit: Maybe you can just do: love.graphics.stencil(DRAW_MAP_LOADER)
(Note the parentheses are missing, because you're passing the function, not executing it and passing the result)
Edit: Maybe you can just do: love.graphics.stencil(DRAW_MAP_LOADER)
(Note the parentheses are missing, because you're passing the function, not executing it and passing the result)
Re: How do I use stencil?
I'll try that when I get home, I feel like this is one of those things that once I figure it out it'll be obvious, but until then I'm so lost xDpgimeno wrote:Can't say for sure without looking at your full code, but it seems so. If you want the map to act as a mask for your spawning objects, you'll have to draw the map to the mask (=the stencil).
Edit: Maybe you can just do: love.graphics.stencil(DRAW_MAP_LOADER)
(Note the parentheses are missing, because you're passing the function, not executing it and passing the result)
Re: How do I use stencil?
Just doing love.graphics.stencil(DRAW_MAP_LOADER) doesnt crash the game, so thats good, but nothing also changes lol. so either it isn't working, or theres something else i need to add to make it work. I assume i need to add something to my blood_splatter object to make it only draw in the stencil mask, but i dont know what or how haha (I'm bad)Vimm wrote:I'll try that when I get home, I feel like this is one of those things that once I figure it out it'll be obvious, but until then I'm so lost xDpgimeno wrote:Can't say for sure without looking at your full code, but it seems so. If you want the map to act as a mask for your spawning objects, you'll have to draw the map to the mask (=the stencil).
Edit: Maybe you can just do: love.graphics.stencil(DRAW_MAP_LOADER)
(Note the parentheses are missing, because you're passing the function, not executing it and passing the result)
Re: How do I use stencil?
After preparing the stencil by drawing on it, you have to activate it. Read my explanation again.
Re: How do I use stencil?
pgimeno wrote:After preparing the stencil by drawing on it, you have to activate it. Read my explanation again.
I feel like this should be working, but the DRAW_BLOOD isnt being called at all, or at least not drawn.
Code: Select all
local function my_stencil_function()
DRAW_MAP_LOADER()
end
function love.draw()
camera:set()
love.graphics.stencil(my_stencil_function, "replace", 1)
love.graphics.setStencilTest("greater", 0)
DRAW_BLOOD()
love.graphics.setStencilTest()
DRAW_BLOOD_PARTICLE()
DRAW_PLAYER()
DRAW_BLOOD_PROJECTILE()
DRAW_SPIKE()
camera:unset()
end
Re: How do I use stencil?
Looks like it should be working, yes (apart from the fact that you don't draw the map to the screen, only to the stencil, but that shouldn't prevent the blood from being drawn). Hard to help without a test case, sorry.
Re: How do I use stencil?
yeah well the map is invisible in game anyway so that part should matter haha.pgimeno wrote:Looks like it should be working, yes (apart from the fact that you don't draw the map to the screen, only to the stencil, but that shouldn't prevent the blood from being drawn). Hard to help without a test case, sorry.
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 2 guests