Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

zLevel limit is 10?

in Questions Posts: 1,061

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?

Comments

  • JohnJohn Admin Mod
    Posts: 643

    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.

  • Posts: 1,061

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

  • Posts: 1,061

    @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!

  • dave1707dave1707 Mod
    Posts: 9,295

    @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
    
  • Posts: 1,061

    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.

  • dave1707dave1707 Mod
    Posts: 9,295

    @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
    
  • Posts: 1,061

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

  • edited January 24 Posts: 2,277
    @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.
  • Posts: 1,061

    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."

  • Posts: 2,277

    @RonJeffries - ah, now I understand. Thanks.

  • Posts: 147

    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.

  • SimeonSimeon Admin Mod
    Posts: 5,645

    @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

  • Posts: 147

    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.

Sign In or Register to comment.