zLevel limit is 10?

It appears that zLevel’s maximum is 10. Since it’s a float, I’m not clear why there’d be a limit at all, you must be keeping it in a sorted list or some such thing anyway?

Anyway … whazzup, please?

zLevel just moves sprites on the z-plane when rendering them. iirc the orthograph projection depth range used by sprites is set to -10,10 by default. You could either divide your depth slices to be smaller to fit in that range or use ortho(0, WIDTH, 0, HEIGHT, 0, 1000). You might run into precision issues at a certain point. Because of how the renderer works, it doesn’t do sorting for you. You’d need to do that yourself before rendering.

yes, i was surprised by the 10. not sure what you mean about sorting tho?

@John please explain what you meant by the renderer not doing sorting? Do you mean it doesn’t really draw the higher zLevels last? If it doesn’t, just what does zLevel do?

Thanks!

@RonJeffries Heres something I put together to help me see what zlevel is doing.
It looks like zlevel is additive. Multiple zlevels in the draw function are either added to or subtracted from the previous one in the draw cycle. So even though a zlevel might have a high zlevel value, depending of the zlevels before it, the total zlevel value might not be high enough to get it displayed. I think what @John means by sorting is, putting all the zlevel values in the correct order so all the higher zlevel values are displayed in front of the lower zlevel values. What this demo shows is just because an image has a higher zlevel than another image, it might not show in front of it depending on the other zlevels that were drawn before it. This displays overlapping images. You can see the images zlevel on the slider and it’s total zlevel value displayed on it’s image depending on the previous zlevels values.

viewer.mode = STANDARD

function setup()
    print("slide this down to show z8")
    for z=1,8 do
        parameter.integer("z"..z,-10,10,0)
    end
    tab={}
    for z=1,8 do
        tab[z]=image(200+z*40,400-z*40)
        setContext(tab[z])
        background(math.random(255),math.random(255),math.random(255))
        setContext()        
    end
end

function draw()
    background(0)
    zLevel(0)
    zl={z1,z2,z3,z4,z5,z6,z7,z8}
    fill(255)
    lev=0
    for a,b in pairs(tab) do
        zLevel(zl[a])
        lev=lev+zl[a]
        sprite(b,20+a*20,HEIGHT/2)
        text(a..":"..lev,100+a*40,HEIGHT/2+190-a*20)
    end
end

interesting … i always set zlevel explicitly, push/pop. in your example the larger z always seems to go on top, taking the adding into account. the adding is just weird tho.

i still want to know what it actually does that makes sense.

this thread relates: https://codea.io/talk/discussion/10618/sprites-getting-corners

@RonJeffries If you display a lot of sprites, the later drawn sprite will hide the earlier one if they overlap. The zLevel lets you change which sprites show in front of or behind other sprites. If you have several characters that are moving around the screen and they pass each other at the same y screen value, by using the zlevel, you can alter which characters appear to be in front of the other characters. Or you can change if a person sprite passes in front of or behind another sprite without having to change the drawing order.

Here’s an example.

viewer.mode = FULLSCREEN

function setup()
    x=30
    v=5
end

function draw()
    background(0)
    sprite(asset.builtin.Space_Art.Asteroid_Large,WIDTH/2,HEIGHT/2,300)
    if v<0 then
        zLevel(-1)
    end
    sprite(asset.builtin.Platformer_Art.Guy_Standing,x,HEIGHT/2)
    x=x+v
    if x<20 or x>WIDTH-20 then
        v=-v
    end
end

yes, i agree that’s how it should work. but it often does odd things, mostly involving alpha.

@RonJeffries @dave1707 - seem to remember @John posting something about the blend mode when using the z_level. Could be what you are seeing with ‘odd things’. Try searching the forum for blend mode posts.

the link above explains what i’m seeing. i would paraphrase this way: “OpenGL does not correctly handle z level transparency. The result is that you need to draw transparent things in increasing z order, most times.”

@RonJeffries - ah, now I understand. Thanks.

It seems that in regards to transparent pixels, zLevel is not showing the pixels that should appear below a transparent one.
In the attached examples -

Solid black square
White squares with numbers and randomly cut out alpha pixels
Both examples use zLevel of 3 for the white squares and zLevel 2 for the black one.
The difference is in “working” the black square is drawn first, then all the white squares. In “broken” the black square is drawn last.

So for some reason the transparent areas of the white squares are not showing the black square behind it.

@skar this is unfortunately due to the way rasterization works. Basically each sprite, when rendered, also renders its depth into the depth buffer. If another sprite is drawn “behind” that sprite then it will discard any fragments that are occluded by the depth buffer

The way around this is to do what you did — sort the sprites by z-level (furthest to nearest) and render them in that order

Thanks, that’s what I figured based on the other users’ experiences and my own. Not a deal breaker, I will find a way to use my Queue structure to change around draw order.

@Simeon is it not possible to discard fragments if a shader is enabled? Do I have to add depth buffer to my own shader? Any idea how to do that or B where to start if so?