Vertex Arrays

I struggled through setting up vertex arrays (mostly stupid problems, the only kind I do)… and to my horror they didn’t improve speed, actually decreased it. I suspected going into it that it’d have a minimal impact despite the advantage of removing some JNI overhead… I have a few theories about this… the first and probably correct one is that I’m only doing chunks of 24 vertices at a time (yep, cubes, and lots of them), I had considered setting up a monster array but each cube has potentially different color information (not a big deal, I could just use a color array too), different materials (I think this is a big deal, I didn’t see any way to have multiple materials using vertex arrays) and probably the most important one, textures, there is basically an unknown number of textures and each cube could potentially have a different texture (so playing fancy pants with the texture coords isn’t a real option). Typically the cubes would have just a few different textures, so I could always group them by texture and send them in a bigger batch, but that starts to add up to a lot of work since the cubes are frequently changed (work for me to write code that maintains the array, though I think drawElements would allow me to not draw some cubes without altering the array). The other option is that I’m just doing something horrifically wrong (besides the small number of vertices sent at a time).

Anyone have any opinions about this, or have any idea about how many vertices you need to draw (or maybe more accurately gl function calls) to gain an advantage from using vertex arrays? If there is a way to handle the materials well I can probably make better use of the arrays, especially if there is a way to handle binding different textures too…

You’ll need to do some state sorting. Sort the triangles by their lights, materials, textures, etc. Only apply the state when it changes. All triangles with the same state is drawn in one go. This in itself will probably give you a huge performance boost.

If your cubes don’t move relative to eachother, you can batch those triangles with the same state in big vertex arrays.

I’m finally getting around to changing my code to build a (hopefully) massive bytebuffer or two to cover the cubes, since bytebuffers don’t seem particularly modifiable I’ll probably be rebuilding it a lot, which sucks but on to the question.

All of the texture coordinates and normals are the same for every single one of the cubes (as crazy as that might sound), so I’m wondering if there is a way to tell opengl to just repeatedly use the same portion of the array. Basically having an array for vertices with thousands of vertices… and an array with 24 normals and one with 24 texture coordinates. I’m pretty sure this isn’t possible but I thought I’d ask anyway.

But I’m also thinking that so long as the normal and texture arrays is at least as big as the vertex array, I can leave them alone completely or would there be a problem with that? This’ll probably come down to my own testing but has anyone tried this (initially all the arrays would be the same length, but as I remove things from the vertex array it’d be shorter than the other two).

[quote]I’m finally getting around to changing my code to build a (hopefully) massive bytebuffer or two to cover the cubes, since bytebuffers don’t seem particularly modifiable I’ll probably be rebuilding it a lot, which sucks but on to the question.
[/quote]
Use direct FloatBuffers instead of ByteBuffers since you store your data as floats. Buffers are modifiable. Look at the put functions. Or are you thinking of something in particular.

[quote]All of the texture coordinates and normals are the same for every single one of the cubes (as crazy as that might sound), so I’m wondering if there is a way to tell opengl to just repeatedly use the same portion of the array. Basically having an array for vertices with thousands of vertices… and an array with 24 normals and one with 24 texture coordinates. I’m pretty sure this isn’t possible but I thought I’d ask anyway.
[/quote]
It’s not possible. You could have a look at automatic texture coordinate generation, but I doubt it will help. Since the data is static you could use vbos wich stores the data on the card wich is faster.

[quote]But I’m also thinking that so long as the normal and texture arrays is at least as big as the vertex array, I can leave them alone completely or would there be a problem with that?
[/quote]
That will work.

I am using FloatBuffers, just said ByteBuffers for no real apparent reason.

By modifiable I mean there doesn’t seem to be a way to remove data that’s already placed short of using clear. I suppose that it’s possible I could overwrite some of the data using an absolute put to change the data, but once the buffer is built, the only thing that happens is it gets smaller. My current plan is to rebuild the buffer that changed.

I’m still in the process of changing my code to use a set of large arrays to draw, hopefully it’ll provide a speed boost at least when there is a large number of cubes (and hopefully having to allocate new buffers won’t be too much of a speed hit). I’m probably only minutes away from finding out (unless I did something wrong with my code… I’m actually scared of this, I’m not looking forward to trying to figure out where something went wrong here hehe, so hoping to get lucky and have things work the first time).

Grrrr, after a rough day of getting brutalized by not being familiar with nio I finally got the thing to display without having a VM crash (no bluescreen thankfully, I hate having to reboot every time I run a program). I get an AWESOME 2 or 3 fps instead of 20 fps using no vertex arrays (or the 12 fps I was getting with my first vertex array failure), but the good news is I’ve definitely got something wrong still (displaying a large number of cubes I had a ‘spike’ poking out of the middle of the screen, apparently I’m supposed to tell it how many sets of vertices to draw, instead of the capacity of the FloatBuffer… I’m pretty sure I did this exact same thing with my first attempt at vertex arrays, probably had something to do with the slowdown I suffered (suddenly I’m sending about 3 times the data and most of it is bogus…). I feel almost like I should go back to the original vertex array attempt code and retest it properly just to see how badly I really screwed it up :stuck_out_tongue:

Fixing that made no noticable difference… and after what might have seemed like hours and hours of crying (it was only like 30 minutes of crying really) and wondering how display for the vertex arrays completed so quickly while the entire loop was so slow… turns out I was drawing 115 cubes, 115 times (I put my drawarray command inside of the loop that would draw each cube individually)… anyway, for a happy ending, I am getting a bit better performance, about 7ms instead of 9ms with the 115 cubes and with approximately 500 cubes I’m seeing about 20 ms instead of 40ms.

VertexArray performances are only noticeable in really big scene…
If you’ve got a very powerful cpu, you won’t see the difference between drawing a 1000 triangled classical model and a 1000 triangled model using vertex array.
If you want significant speed improvement, you should look into Compiled vertex array and Vertex bufffer objects :wink:

Compiled vertex arrays wouldn’t be benificial here, as it’s a single pass rendering. I don’t think my card supports VBO (seems like it should but still…).

A compiled vertex array could probably work if I only used a single array and sent it once (and again any time it was updated), and used drawElements to draw only some of the array (I believe I can do that). I don’t think I’m willing to go that far for performance in this particular game but my next game I’ll probably be getting a lot more extreme about speed as I’d like to have a lot more complex objects and effects going on.

I’ll probably get pretty ambitious on the next game too in that I’ll try to make an engine general enough to be re-used for just about any 3d game, mainly because I’d like to only have to add features to an engine instead of making a new engine every time I do a game. I’m sure everyone can look forward to the follies of that plan when I start on it, but hopefully it can also produce some useful code I can share with the community (useful as in not too embarrassing to show someone else how it works). That’s a long ways off for me though.