Hex Tile based games in JME

chirstius said:

I was under the same impression theprism.

Renanse-

I have to think dual X1900XT video cards have a pretty decent fill rate.  Plenty enough to render a roughly 40x50 grid of hexes - textured or not.  Does the fact that I have them in the Transparent Queue mean anything?  Could that be slowing things down?


Yes, if you have left on the default twoPassTransparent flag in RenderQueue, then transparent items will be rendered twice (once for front facing tris and once for back facing) to provide accurate transparency.  Obviously you may not require that, especially in the case of transparent quads or hexagons where a line can not be drawn through the mesh and intersect at 2 or more points (except on the plane, which doesn't really matter.)
Landei said:

What I still don't understand: How can reducing the number of triangles by 1/3 make rendering (slightly) slower? I tested different configs, and *always* the 4 triangle hexagon was about 0.5 FPS slower...


No idea, perhaps your card is optimized for sending AT LEAST X amount of data at a time or higher, etc.  .5 FPS is not really big enough to be able to point to a single significant reason I'm afraid.

Landei said:

If I understand you right, then constructing the board as one giant mesh with the hexagons as triangle batches should be much faster? If yes, shouldn't we have some kind of Board class for hexagons and rectangles in JME, which has some support regarding access of single hexagons/rectangles (or did I overlooked it)?


That's a genre specific class that just hasn't been put together yet.  If you come up with something that is generic enough for others to use in their games, please share it!  But yes, having the board as a single mesh (or a few bigger meshes) will be tons faster than sending individual squares to the card.

Landei said:
BTW: I would suggest to put that things in the Wiki, as every neebie will first try things like the ones we did. No long explanations, just some tipps and remarks how to avoid the "usual" performance bottlenecks and traps.


I agree.  Please feel free!  :)
renanse said:

theprism said:

is this the same with shared meshes ( im under the illusion that the gpu is reusing the mesh


That's a false impression unless you are locking the target mesh as well.


Just to be clear (pardon my ignorance) but when you say target mesh, do you mean the hex prototype in my code - the REAL mesh that all the SharedMeshes point to?

Yes, I mean what the shared meshes point to.  If textures failed, you may not have completely set up the target mesh before locking it?  (or it might be a bug)



In any case, in your situation with a 6 (or 4) triangle mesh, you won't likely see much improvement.



You can turn off two pass by calling:


DisplaySystem.getDisplaysystem().getRenderer().getQueue().setTwoPassTransparency(false);

renanse said:

Yes, I mean what the shared meshes point to. If textures failed, you may not have completely set up the target mesh before locking it? (or it might be a bug)

In any case, in your situation with a 6 (or 4) triangle mesh, you won't likely see much improvement.

You can turn off two pass by calling:

DisplaySystem.getDisplaysystem().getRenderer().getQueue().setTwoPassTransparency(false);




Can you turn it off by spatial rather than globally or would this require a renderpass

It's not something you can currently set by spatial, but that's a good idea for an enhancement (as a per batch thing though with a convenience method at the Geometry level for setting all batches.)



You could handle it by splitting the transparents into two groups and using the pass system, but if they can be mixed together in depth, the transparency would not look color accurate.

chirstius said:

So again, my question is - why does removing a rendering pass also remove half the geometry?


My guess would be the stats are collected when meshes are sent to be rendered.  So you still only have the same number of meshes etc physically displayed but since they are all sent twice during the two pass rendering the stats for them are collected twice (if you check the numbers when it's on they are all exactly double that of when it's off).

You are probably correct.  I realized it was a doubling of the geometry, but couldn't understand WHY it was doubling.  Your explanation seems perfectly reasonable.  Now I need to figure out why the framerates are half as fast under jME 0.11 vs. jME 0.10…



I know I should just give this damn thing up but it's becoming a personal crusade at this point <sigh>



Thank you, everyone, for your help and guidance so far.

chirstius said:

[..] but it's becoming a personal crusade at this point <sigh>

And we appreciate that you're not giving up because whatever your findings are, I'm sure they'll help us improve jME.

Yesterday I tried something in a different direction: I wrote something similar to an BatchMesh, but with translating the GeomBatch positions to "board coordinates". As a result I was passing all Hexagons in one single giant mesh, and the speed gain was drums trumpets triangle… nothing, zero, nada, niente.



I'll post the code (have it not here), maybe I made something wrong, or you see some improvement possibility…

Landei said:

Yesterday I tried something in a different direction: I wrote something similar to an BatchMesh, but with translating the GeomBatch positions to "board coordinates". As a result I was passing all Hexagons in one single giant mesh, and the speed gain was *drums* *trumpets* *triangle*..... nothing, zero, nada, niente.

I'll post the code (have it not here), maybe I made something wrong, or you see some improvement possibility...


Yikes!  I had hoped an approach like this would be where I went when I stopped "wasting" time on the current Hexagons as Hexagons path I'm beating my head against.  When you can, please do post the code.  I'll give it a go and see what happens.

IMHO, you won't beat the texture based approach, performance wise… (a generic "tiling" implementation could be made, to be applied on a quad or terrain and handle texturing the quad/terrain, picking and displaying one or more hexagons, etc. More shapes could be made available, BTW)



Why do you need each hexagonal mesh? (I'm just curious)

Let's say you have a transparent 3d object with depth, say a torus.  To properly simulate light coming through it and hitting your eye, you have to render the polygons that point away from your eye (the back faces) first, then the polygons that face your eye.  To dynamically split the mesh into these two groups would be cpu intensive and slow.  Instead, we send the mesh through twice, first with front face culling, then back face culling.  This does the same thing as splitting the object without burdening the cpu, but effectively doubles the information sent to the card.  You can limit the impact this has on your app by using display lists (locking your mesh in jME) or by using vbo (VBOInfo) because the data will already be "on the card" and likely in card local memory as it is the most recently used piece of data.



Eliminating the two pass method means you only send your mesh through once, at the risk of artifacts if your mesh has depth and light might pass though it 2+ times before hitting your eye.



Hope that helps clear things up.

The Librarian said:

Why do you need each hexagonal mesh? (I'm just curious)


Really, I don't think that I do, but as I said previously, it's become a bit of a mission to discover why, even at (what I would consider) fairly small "board" sizes that this implementation seems to perform so poorly.

Now, I do think there's a bit of benefit to having the actual board "model" directly align with the board representation (in a 2D world this made great sense) because it simplifies some calculations and makes selecting/modifying any individual coordinate pretty straightforward.

Excellent and very informative Renanse.  Thank you.

When I said "quad", I meant a flat "terrain" (not in the jME sense) or board, made of one or several quads (organized as QuadTrees for instance). There'd be no mapping between your quad assemblage and your tiles. The texture you apply on this board is the size of your tile (and is repeated, obviously).

So for a 100x100 tiled board, you may only need 4 or 16 quads and one 32x32 texture (I just made up these numbers of course).



BTW chirstius, I understand your "crusade" :wink:

…me too.



I have have similar performance problems in my levels, and any new ideas for optimizing it are welcome. For me the problem is, that I put my levels at runtime together from boxes etc, and I can't make optimizations like people with "static" levels.



Here is my BoardMesh class. As I said, it brings NO performance.

Just define the BoardMesh and add your triangleBatches in a loop with addBatch(batch, x, y). To get a triangleBatch, use new Hexagon().getBatch(0)

The class is very straightforward, most things are "borrowed" from BatchMesh. I haven't looked at texturing, I don't know why it doesn't work. Don't take this class too serious…



[Edit] class removed - GeometryBatch seems to do the same, but better…

Landei said:

Here is my BoardMesh class. As I said, it brings NO performance.
Just define the BoardMesh and add your triangleBatches in a loop with addBatch(batch, x, y). To get a triangleBatch, use new Hexagon().getBatch(0)
The class is very straightforward, most things are "borrowed" from BatchMesh. I haven't looked at texturing, I don't know why it doesn't work. Don't take this class too serious...

[Edit] class removed - GeometryBatch seems to do the same, but better...


I found GeometryBatch on the Wiki and added it in.
renanse said:

Let's say you have a transparent 3d object with depth, say a torus. To properly simulate light coming through it and hitting your eye, you have to render the polygons that point away from your eye (the back faces) first, then the polygons that face your eye. To dynamically split the mesh into these two groups would be cpu intensive and slow. Instead, we send the mesh through twice, first with front face culling, then back face culling. This does the same thing as splitting the object without burdening the cpu, but effectively doubles the information sent to the card. You can limit the impact this has on your app by using display lists (locking your mesh in jME) or by using vbo (VBOInfo) because the data will already be "on the card" and likely in card local memory as it is the most recently used piece of data.

Eliminating the two pass method means you only send your mesh through once, at the risk of artifacts if your mesh has depth and light might pass though it 2+ times before hitting your eye.



Can that go n the wiki as is

That, my friend, is called the art of batching. :wink: NVIDIA has a very interesting paper about that subject.