Page 1 of 2
sort order with shader
Posted: Tue Oct 18, 2022 6:26 pm
by borr
Code: Select all
extern float depth;
varying vec4 vpos;
#ifdef VERTEX
vec4 position(mat4 transform_projection, vec4 vertex_position)
{
vpos = transform_projection * vertex_position;
vpos.z = depth;
return vpos;
}
#endif
#ifdef PIXEL
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
// texture_coords += vec2(vpos.x, vpos.y);
vec4 texcolor = Texel(tex, texture_coords);
return texcolor * color;
}
#endif
i'm trying draw sort with shader
but i have problem with alpha color. with this shader there is no reaction to changing the alpha for the color
Re: sort order with shader
Posted: Tue Oct 18, 2022 7:45 pm
by ReFreezed
When you draw half-transparent objects you must draw them from back to front for alpha blending to work properly, as the depth buffer only contains the distance to the closest object, no matter how "transparent" that object is (i.e. you cannot draw "behind" objects as the GPU has no concept of what's been drawn before).
Re: sort order with shader
Posted: Tue Oct 18, 2022 8:14 pm
by borr
thanks for your reply.
both rectangles with alpha less than one.
if i change the alpha of the color of the second rectangle to one - it doesn't help
Code: Select all
function love.draw()
love.graphics.clear()
love.graphics.setCanvas({ renderTarget1, depthstencil = depthBuffer })
love.graphics.clear(0.4, 0.4, 1.0, 0.0)
love.graphics.setShader(shader)
shader:send("depth", 1.0)
love.graphics.setDepthMode("less", true)
shader:send("depth", 0.5)
love.graphics.setColor(1.0, 0.0, 0.0, 0.5)
love.graphics.rectangle("fill", 200, 200, 100, 100)
shader:send("depth", 0.8)
love.graphics.setColor(0.0, 1.0, 0.0, 0.5)
love.graphics.rectangle("fill", 250, 250, 100, 100)
love.graphics.reset()
love.graphics.draw(renderTarget1)
love.graphics.draw(depthBuffer, 0, 0, 0, 0.1, 0.1)
end
Re: sort order with shader
Posted: Tue Oct 18, 2022 9:01 pm
by ReFreezed
Draw the rectangles in the opposite order...
Re: sort order with shader
Posted: Wed Oct 19, 2022 5:01 pm
by borr
it works thanks. except for the layer with the greatest depth
Code: Select all
love.graphics.clear(0.4, 0.4, 1.0, 0.0)
love.graphics.setShader(shader)
shader:send("depth", 1.0)
love.graphics.setDepthMode("less", true)
shader:send("depth", -0.5)
love.graphics.setColor(1.0, 0.0, 0.0, 0.5)
love.graphics.rectangle("fill", 200, 200, 100, 100)
shader:send("depth", -0.8)
love.graphics.setColor(0.0, 1.0, 0.0, 0.5)
love.graphics.rectangle("fill", 250, 250, 100, 100)
--love.graphics.reset()
love.graphics.draw(renderTarget1)
Re: sort order with shader
Posted: Wed Oct 19, 2022 5:22 pm
by borr
Is there a way to change the draw order using a shader. with full functionality (stencil, color etc)?
Re: sort order with shader
Posted: Wed Oct 19, 2022 5:57 pm
by ReFreezed
borr wrote: ↑Wed Oct 19, 2022 5:01 pm
it works thanks. except for the layer with the greatest depth
I'm not sure what you mean. That image looks correct. A green see-through rectangle, on top of a red see-through rectangle, on top of the blue background.
Note that shader:send("depth",1.0) doesn't do anything since you don't draw anything before you send a new value for 'depth'.
borr wrote: ↑Wed Oct 19, 2022 5:22 pm
Is there a way to change the draw order using a shader. with full functionality (stencil, color etc)?
The only thing you can change in the shader that affects the depth is the z position of the vertices, like you're currently doing.
I don't think you can use both a depth buffer and a stencil at the same time (oops, I forgot about the depth24stencil8/depth32fstencil8 canvas formats), but you can implement you own stencil-like functionality using an extern Image and the 'discard' keyword.
Code: Select all
extern Image mask;
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
if (Texel(mask, screen_coords/love_ScreenSize.xy).a == 0) discard; // something like this
vec4 texcolor = Texel(tex, texture_coords);
return texcolor * color;
}
Re: sort order with shader
Posted: Wed Oct 19, 2022 6:21 pm
by borr
>I'm not sure what you mean. That image looks correct
red rectangle drawn with wrong alpha(other than 0.5) - love.graphics.setColor(1.0, 0.0, 0.0, 0.5)
looks like the right solution for draw-drawing is
https://love2d.org/wiki/Tutorial:Drawing_Order
I don't like it because you need to sort the array
Re: sort order with shader
Posted: Wed Oct 19, 2022 6:41 pm
by slime
Every game that uses alpha blending with semitransparency (regardless of what engine is being used) needs to sort objects back-to-front to make sure they're blended correctly.
Re: sort order with shader
Posted: Wed Oct 19, 2022 7:04 pm
by ReFreezed
borr wrote: ↑Wed Oct 19, 2022 6:21 pm
>I'm not sure what you mean. That image looks correct
red rectangle drawn with wrong alpha(other than 0.5) - love.graphics.setColor(1.0, 0.0, 0.0, 0.5)
I'm still not sure what you mean, but maybe it has something to do with the way the canvas is drawn to the screen. You ought to use premultiplied alpha. (See the note at the top of
https://love2d.org/wiki/Canvas.)
Code: Select all
love.graphics.setBlendMode("alpha", "premultiplied")
love.graphics.draw(renderTarget1)
love.graphics.setBlendMode("alpha")
It's only really going to be an issue if you have way too many objects in the array you're sorting. Also, you only have to sort objects with half-transparency. Opaque objects can be drawn in any order.