Dreaded alpha again!

Member
Posts: 117
Joined: 2010.09
Post: #1
Hi all,

I've read many threads on this and am still confused as to what is the optimal method to avoid state changes.

Essentially I have a 2d sprite (quad) based top-down game.
I can sort my draw order based on their y (screen rotated, so y axis is up and down).
No probs!Wink
Then I could order them by texture (to avoid state change) but then I would lose my 'y' ordering.

Now adding in alpha (and by that I mean say semi-transparency effects i.e. the texture behind must have already been drawn because it will show through) things get more complicated.
With alpha channel I must order by y (painters algorithm else draws will be wrong); but then I have the issue of texture changes.....Mad

I can't use the z buffer can I??? i.e. assign a 'depth' to a 2d item and then even if I wish to draw it afterwards have it drawn behind because it's z value is less then the foreground object.

Hmmmmm! Annoyed , anyone care to push me in the right direction?

Must admit I am new to this board and so far the topic's, threads and help have been ace! Cool

Cheers
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #2
Zbuffer will only help you if you are trying to order opaque and alpha sprites - if you have a bunch of alpha blended sprites then you will still need to sort them internally.
Keep in mind that unless you can fit all your sprites onto a single texture, you will have some texture state changes - the idea here is to minimize it but you can't avoid it altogether.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
This is why you need a texture atlas -- so that you don't have to change state during a regular draw, and therefore can sort by distance to camera without other penalty.
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #4
I see.
My plan was to have alpha sprites in their own texture atlas.
This obviously saves on the texture swap but won't I need to draw them in order with the opaque sprites aswell? (thereby causing texture page swaps between opague and alpha + other state swaps)???

Or if I enable the Z buffer I can simply draw my alpha sprites in order as the last thing to draw after everything else; is that the solution?

If so how do you set the z order (for the z buffer) when the drawarray vertex is set for just x & y; or must I add z (i.e. draw it with 3 elements per vertex) and then let the z buffer use my z to determine whether to draw a pixel or not?

I presume I have asked and answered my own question ! LOLLOL

Cheers

P.S
So is the order this:
z buffer off
Draw backdrop no alpha
z buffer on
Draw player sprites (1 bit alpha)
Draw any 'overlays' with alpha (like things that you can walk behind)
Draw proper 'n' bit alpha objects e.g. semi-trans

Is this a correct and optimal route to go?
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #5
(Sep 24, 2010 09:33 AM)markhula Wrote:  Draw player sprites (1 bit alpha)

Alpha testing is slow on iPhone. Use the "n-bit" (as you say) blending for anything that needs translucency/transparency. ... therefore, I sort all mine myself, and since it's all 2D and they're sorted, I don't bother with depth testing (i.e. no z buffer).
Quote this message in a reply
Member
Posts: 23
Joined: 2010.08
Post: #6
You can use z-buffer and add a z component to all your quads to have the hardware sort your opaque and AlphaFunc quads - but as AnotherJake mentions you can usually work around it. The trick is how you batch your geometry together.

I am not sure I have a clear picture of your rendering requirements - but it sounds like you are making a tile based game. If so - and to make my examples easier to follow - lets say we are rendering the graphics for The Legend of Zelda: A Link to the Past.

You have several layers in this game:
  1. The ground
  2. Obstacles and stuff you can walk behind: walls, tree trunks etc. The player and NPCs will also be part of this layer.
  3. Overlay: Tree tops, clouds etc.
  4. GUI elements.

The layers should be drawn in the order noted above to get correct rendering - thus you are forced to do at least one draw call per layer. In order to avoid more than one draw call per layer you try to add all graphic elements from one layer into the same Texture Atlas.

If you look through the various layers you will notice that only the Obstacle layer needs to be sorted. Because this is a tile game we can simply push the quads into your vertex buffer in the order top to bottom of the screen. Usually this can easily be done from your level layout - and no fancy sorting is required.

The objects within the remaining layers can usually be drawn order independent - and you are therefore more free regarding how to submit quads to these vertex buffers.

Hope this makes it a bit clearer how you can optimise draw calls and get correct render order.

The Monkey Hustle - Now available on the App Store!
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #7
(Sep 25, 2010 04:17 AM)mariocaprino Wrote:  ... and no fancy sorting is required.

Well, I wouldn't say sorting is "fancy". Using qsort is dead easy to do and it's super fast. The C stdlib version uses function pointers though, so if you really want to squeeze cycles you can make your own simple sort algorithm specifically for sorting your sprites.
Quote this message in a reply
Member
Posts: 117
Joined: 2010.09
Post: #8
Thanks for that.

Of course if you build an array based on z or indeed y (if rendering back to front) then it is possible to do it with no sorting ever required to get the correct depth.

Cheers
Quote this message in a reply
Post Reply