Sprites getting corners

Using e.g. Space Art / Asteroid in this simple program, all works fine:

-- sprite alpha

-- Use this function to perform your initial setup
function setup()
    print("Hello World!")
    pos = vec2(WIDTH/2, HEIGHT/2)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(255,0,0)
    pushMatrix()
    translate(WIDTH/2,HEIGHT/2)
    scale(WIDTH/137, HEIGHT/91)
    zLevel(-1)
    sprite(asset.mw)
    popMatrix()
    pos = pos + vec2(1,1)
    translate(pos.x%WIDTH, pos.y%HEIGHT)
    sprite(asset.builtin.Space_Art.Asteroid_Large)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    
end

It looks as you’d expect, the Asteroid acts like it has a transparent background.

In my real asteroids program, they show up with corners in black or other background color. Of course its draw is more complicated but I’m not using blend mode, or such things. I’ve turned off all kinds of fills, and I can’t get the corners transparent.

What might be going on? It does seem that “background” can change the apparent color of the corners, but they’re totally not there in the simple program.

Ideas ever so welcome, this has me confused. Thanks! Pic of good and bad below:

https://ronjeffries.com/articles/020-asteroids-50ff/asteroids-63/good2.png

and

https://ronjeffries.com/articles/020-asteroids-50ff/asteroids-63/bad.png

@RonJeffries i think when creating your image the alpha channel of your background needs to be transparent i.e. alpha=0 in the fourth of the color parameters (red, green, blue, alpha)

It seems to be dependent on zLevel as well. And in my small example, the background isn’t zero/trans, and it works fine.

I think it’s a zLevel sorting thing, but it does seem to have something to do with the color of the background when the asset is accessed. Very mysterious so far.

@ronjeffries - you can see the effect of background colour easily when using emoticons. When you print them with text() you need to specify a fill() before it to get the rich colour of the image. So I use fill(255,255,255,255) before texting the emoticon.

Try texting one before and after the fill().

I believe this is a similar effect to using partially transparent sprites.

The sprites I have are the ones shipped with the system. They show up with proper transparency sometimes and not others. I’m not using text or emoticons and don’t see quite why i would …

@ronjeffries - emoticons just show the effect very well, just a good demo - not related to your issue. I Think most of the sprites packaged with Codea are like fully coloured tiles, but I have made my own sprites up deliberately with transparent pixels which show the background though.

It works sometimes and not sometimes. It seems to be related to z level and possibly to the background setting. i think its an alpha-sorting bug.

@RonJeffries have you had a look at this thread from way back? https://codea.io/talk/discussion/181/how-does-zlevel-work

The demo program half way appears to show what your seeing.

yes sounds similar. order matters, and negative z levels seem right out. i can’t figure where the assets are picking up color.

@RonJeffries this is an issue with draw order. If you have transparent objects, then they need to be drawn last (sorted by Z depth from furthest to closest — actually if you just sort all objects by Z depth you should be good)

The reason for this is that in OpenGL each thing you render writes to the depth buffer. But it writes all of its geometry and does not mask transparent pixel. So that when you go to render something later which should be “behind” the object that has been rendered, OpenGL tests which fragments to render by comparing the depth of the incoming fragment to the value in the depth buffer at that point. If a piece of transparent geometry is there it will “block” the background from getting rendered

Yes. Well, maybe. To do that, one has to either code very carefully, and probably a bit unnaturally, or one has to put z order into all one’s objects and then sort the list every time it changes, which is often. But already I have an idea …

I would have hoped that zLevel was supposed to deal with that, and it seems like it sort of doesn’t.

I’ll have to think harder than I can right here right now about the OpenGL description to really understand, but of course “transparent last” is understandable if perhaps tricky to do. That said, I see at least one way to do it in Asteroids already.

Do you think zLevel will ever be made to work? Or is it your view that it does?

Something like zLevel works more intuitively when you have a scene description up-front. Like you build your scene graph and then you tell Codea to draw the entire thing — we could then check for transparent objects and create the correct render order

When you draw inside the draw() function we have no way to know when you are finished drawing, or what the next thing to be drawn will be. Codea just draws exactly what you specify. We do try to do some automatic batching if you draw the same sprite repeatedly (to avoid lots of draw calls)

You can use a shader to tell OpenGL to ignore transparent pixels in the depth buffer, this would look something like:

if( color.a<=0.0 ){
     discard;
 }

But then you wouldn’t get antialiasing on your sprite edges

The alternative is to have the draw function evaluate into a scene description that is then optimised and rendered out-of-order from what you specify. I think this would be a really interesting area to explore (and it would allow things like zLevel). It would also have its own unexpected side effects (like I drew B after A, why is A showing on top?)

Another alternative might be to have a closure for automatic depth sorting, something like:

render.depthSort(function() 

    -- All drawing in here is rendered in depth order

end)

Or a stateful API

render.depthSort = true

-- All drawing in here is cached and depth-sorted by triangle

render.depthSort = false

I think this is an interesting problem, especially the API design aspect when you have an immediate-mode renderer like Codea (though Codea Craft is a scene renderer, and is a place we could apply proper automatic transparent rendering)