I'm programming a game that has walls and the player and other entities hide before them by using stencil. The thing is that I would like to show the items behind but with some opacity instead of its hide.
After looking at the documentation I was not able to find a sample to achieve something like this, only to hide all the contents.
Can someone point me in some direction to investigate more? or some sample?
I really appreciate any help you can provide.
Draw items "behind" a wall
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Draw items "behind" a wall
Take a look at this thread: viewtopic.php?p=246776
The way I ended up doing it:
Step 1: Draw your objects as a black & white mask to a render texture, in back-to-front order. Overlapping objects are white, silhouette-able objects are black.
You can output to multiple render textures at once from a shader, so I could do this in one pass with normal rendering.
Step 2: Redraw all silhouette-able objects with a custom shader. In this shader, read from the mask texture and only draw the silhouette for pixels that are white in the mask.
The final result:
My overall drawing process code:
The main fragment shader that draws objects normally and their black or white mask at the same time:
You need to use shader:send() to set the "isSilhouetteable" setting to either 0 or 1 for each object. I have my object drawing code set up to only send this when it actually needs to change, so it only breaks the batch when necessary.
And the silhouette shader (for drawing the "behind" bits on top):
Of course this is only one method. There are other ways to do it. If you only have one object that you want to show behind things or a limited number or location of "walls", then it's much easier. I wanted something that could handle any number of movable objects silhouetted behind anything anywhere, haha.
Note: My drawing setup is probably different from yours. I'm not using any stencils. I just sort my objects by their base Y position and draw them back to front so they all overlap correctly.
The way I ended up doing it:
Step 1: Draw your objects as a black & white mask to a render texture, in back-to-front order. Overlapping objects are white, silhouette-able objects are black.
You can output to multiple render textures at once from a shader, so I could do this in one pass with normal rendering.
Step 2: Redraw all silhouette-able objects with a custom shader. In this shader, read from the mask texture and only draw the silhouette for pixels that are white in the mask.
The final result:
My overall drawing process code:
Code: Select all
love.graphics.setCanvas(maskCanvas)
love.graphics.clear(0, 0, 0, 1) -- Silhouette shader requires a black background, not transparent.
love.graphics.setCanvas(canvas, maskCanvas)
love.graphics.setShader(maskShader)
layer:draw() -- Draw all objects.
love.graphics.setCanvas(canvas)
love.graphics.setShader(silhouetteShader)
layer:drawSilhouettes() -- Draw silhouettes on top.
love.graphics.setShader()
Code: Select all
uniform Image MainTex;
extern float isSilhouetteable = 0.0;
void effect() {
// Draw regular image color to main canvas.
vec4 texturecolor = Texel(MainTex, VaryingTexCoord.xy);
love_Canvases[0] = texturecolor * VaryingColor;
// Draw black or white silhouette to mask canvas.
float s = 1 - isSilhouetteable;
vec4 maskColor = vec4(s, s, s, texturecolor.a);
love_Canvases[1] = maskColor;
}
And the silhouette shader (for drawing the "behind" bits on top):
Code: Select all
extern Image mask;
extern vec2 maskSize;
extern vec4 silColor = vec4(0, 1, 0, 0.5);
vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) {
vec4 maskCol = Texel(mask, screen_coords/maskSize);
vec4 texCol = Texel(tex, texture_coords);
return vec4(silColor.rgb, silColor.a * texCol.a * maskCol.r);
}
Note: My drawing setup is probably different from yours. I'm not using any stencils. I just sort my objects by their base Y position and draw them back to front so they all overlap correctly.
-
- Prole
- Posts: 2
- Joined: Wed Oct 25, 2023 2:28 pm
Re: Draw items "behind" a wall
Thanks for the in-depth explanation, beyond my expectations. I will try the idea of modifying the current layer for stencil for this one.
Re: Draw items "behind" a wall
You can still do that with the stencil test, you just change the logic you use.fernandezvara wrote: ↑Wed Oct 25, 2023 2:47 pm I'm programming a game that has walls and the player and other entities hide before them by using stencil. The thing is that I would like to show the items behind but with some opacity instead of its hide.
You clear the stencil buffer, then populate it with the objects that hide things, like placing 1 on their pixels. So the stencil buffer has 0 on open pixels and 1 on occupied pixels.
Then you set the stencil test to "equal" to 1 and draw all obscurable sprites with half transparency. Only parts that overlap occupied pixels will be drawn -- effectively drawing them on top of walls. Some games also draw a "silhouette", like fully opaque but with a flat color like turquoise or something like that.
Then you set the stencil test to "equal" to 0 and draw all obscurable sprites as fully opaque. Only the parts that are in open pixels, outside walls, will be drawn.
Who is online
Users browsing this forum: Ahrefs [Bot], whateverest and 6 guests