Najdorf Wrote:glDisable(GL_DEPTH_TEST)
You then need to draw your stuff in order (closest stuff needs to be drawn last)

I know how to (de)activate depth buffer.

I ask if you use it, or if it is useful (cost). And by the way, do you reorder this vector every frame? (using for instance std::sort). Do not forget I have to add and remove objects all the time (bullets for instance) and manage transparencies.

riruilo Wrote:by the way, do you reorder this vector every frame? (using for instance std::sort). Do not forget I have to add and remove objects all the time (bullets for instance) and manage transparencies.

Personally I think the simple "sparse array" solution works just fine, with no per-frame sorting at all:

1) decide how many bullets you will ever have active simultaneously.
2) allocate a static array for them. Each entry is the minimal bullet object info-- not the rendering info.
3) each frame, update bullet according to game logic. Dead bullets are marked dead, but not removed from the array. New bullets are added to the end of the array.
4) when array is full, compact array to remove all dead bullets. This is O(N), and is only done once every couple hundred frames, depending on your spawn/die rate.
5) when you draw, scan through the entire array and construct rendering info into vertex buffers, for each non-dead bullet. This is also O(N). Draw order is always maintained as FIFO this way, so overlapping transparencies work.

I think it works this way: when you sort yourself, you're using CPU power, when you use depth buffer, you drain GPU. So depending on what you need more, you can use either this or other method. I'm using standard sort() function - for me the bottleneck is video, not processing power. I've also optimized my routine to only resort once every 30 frames or by demand, which is what you can't do using depth buffer.

I just draw the objects in general order, like background first, then an array of things above the background, then other stuff, then foreground stuff and so on. Probably only use like maybe half a dozen arrays.

I have no idea if any of this makes sense to anyone, but I'll try to describe what I do:

For adding and deleting from the arrays, I compact on the fly as I process each one, each tick. I do this with four total arrays for each set of objects:

- main array containing a generic struct for each object
- array containing indices of available objects from the main array used as a stack
- array of active object indices 1 (front buffer of objects, so to speak)
- array of active object indices 2 (back buffer of objects, so to speak)

The main array is the only relatively large one, since it has the actual structs. The other three arrays simply deal with indices into the main array, so they're relatively small, with just an int or unsigned int in each slot.

So when I add an object, I'm actually adding its index to the front array by taking the next available index off the stack. Then when I process all the active objects in the front array, I copy the index of each object that will be alive next tick into the back buffer. If it was a deleted object then its index is simply not copied to the back buffer, which is how I automatically compact the array every update. Deleted object indices are pushed onto the stack of available objects. At the end of the update of the array, just swap the buffers. It probably sounds complicated, but it is very efficient and incredibly simple.

For depth sorting: I haven't tried it yet, but I've thought a bit about using a similar system, but as a binary tree to do depth sorting on the fly each tick too. Haven't needed that yet though...

Yeah, I've used the depth buffer for 2D. It works fine, but costs some precious iPhone RAM and I find that it's not needed for my 2D stuff, so I choose to skip it.

Have to use it for 2.5D though (3D mesh models represented in a 2D game). I still sort the objects by general grouping. I do give them an individual z value "slot" so they don't pass through each other, which can look weird. The z values are spread out so that they're roughly equal to the thickest object. Of course, things are somewhat limited in that there is only so much you can fit between the near and far planes before precision starts to be a factor, but on iPhone, there just isn't enough screen space to be drawing too many objects in the first place. With purely flat sprites, obviously you wouldn't need much spread, so I can fit those in pretty tight.

> On the other hand, do you usually use standard template library? (std::vector or std::list) or do you create your own structures/functions?

I just use my own structs and functions. I would imagine STL should work just fine for you though.

Yeah, I've used the depth buffer for 2D. It works fine, but costs some precious iPhone RAM and I find that it's not needed for my 2D stuff, so I choose to skip it.

Have to use it for 2.5D though (3D mesh models represented in a 2D game). I still sort the objects by general grouping. I do give them an individual z value "slot" so they don't pass through each other, which can look weird. The z values are spread out so that they're roughly equal to the thickest object. Of course, things are somewhat limited in that there is only so much you can fit between the near and far planes before precision starts to be a factor, but on iPhone, there just isn't enough screen space to be drawing too many objects in the first place. With purely flat sprites, obviously you wouldn't need much spread, so I can fit those in pretty tight.

> On the other hand, do you usually use standard template library? (std::vector or std::list) or do you create your own structures/functions?

I just use my own structs and functions. I would imagine STL should work just fine for you though.

riruilo Wrote:@maximile,miq01,AnotherJake So, you propose create several vectors, one for every "plane" and render the most depth planes firstly...
I think I will use this aproaching.

Depends on the type of game, but if it's possible, I'd go for it. Also, the statically allocated arrays arekkusu mentions avoid having to reserve/release memory each time a new entity (enemy, bullet, ...) appears or disappears.