1

To start with,I am pretty new to 3D programming and libgdx. I looked at a few tutorials and I already render the scene I want. I have some 1x1x1 blocks, created with ModelBuilder.createRect() for every visible face, so if another block covers a face of this block, there is no rect created for this block. Also the top and bottom rect is not needed, as I can never see them (except for the floor). So I thought, that this is pretty efficient. I also have Backface culling enabled and I do Viewfrustum culling. However, if I look in a direction, where many blocks are in my viewfrustum the FPS go down to 15-20. This is still okay for me, as my laptop is over 5 years old and its performance is not the best, but this answer made me think.

"ModelBuilder is used for debug only". Okay, but how should i then create my boxes? Why should i create a Model in a Modeling app (like Blender), for simple squares? By doing this i couldn't even cull the faces, which are occupied by other blocks. So my question is: How can i create and render those boxes the most efficient way?

Community
  • 1
  • 1
Robert P
  • 9,398
  • 10
  • 58
  • 100
  • IIRC, your method is resulting in a single draw call for every rectangle, which becomes very expensive if you have many of them. Check out DecalBatch for what you're doing. It can combine all the rectangles into a single draw call. – Tenfour04 Mar 12 '14 at 11:25
  • But doesn't the `ModelBatch` `flush()` them only when its buffer is full, so it is only sent to GPU once. Also `DecalBatch`, as much as i understood, sdoes not do what i need, it draws a 2D `Texture` in 3D space, doesn't it? – Robert P Mar 12 '14 at 12:57
  • Oh yeah, that's right. Are you using blending? How many rects are you drawing? DecalBatch can draw solid rectangles with no texture...you just need a custom GroupStrategy to set that up. This guy (http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=12493&p=55804&hilit=decalbatch#p55804) found that DecalBatch and ModelBuilder have similar performance for rectangles. – Tenfour04 Mar 12 '14 at 15:21
  • I use blending, actually i have a 100*100 block map with 4 block tall walls. I have only the edge walls + 1 wall through the whole map in z-direction and 1 hole inside (to go through). So there are about 1000 rects (as a maximum, depending on my position and direction cause of frustum culling). All the rects have a 128*128 px texture on them. I wanted to group them, but i was not able to repeat the `Texture`s then (see my other question (http://stackoverflow.com/questions/21908241/repeating-textures-on-a-model/22297242#22297242)) – Robert P Mar 12 '14 at 15:27
  • I don't know what's causing your low frame rate, except maybe too much overdraw (which you could test for by not using blending). So this may not help, but I did something like this using DecalBatch. DecalBatch draws rectangles in 3D space, which is pretty much what you're doing with ModelBatch. But I think you could subclass Decal so you could manually adjust UV's to avoid having to draw each wall up to four times. Instead, use a single decal with a repeatable texture, and set the V at the two top vertices to whatever height you want (1, 2, 3, or 4). – Tenfour04 Mar 12 '14 at 17:24
  • I have tested it yesterday again. About 8000 objects are drawn at the same time. Then my FPS are about 15-20. The objects are owerdrawn, thats sure, as other walls are behing the walls in front of me. But doesn't have disable blending some side effects (transparent parts are not transparent anymore) – Robert P Mar 13 '14 at 07:04
  • 8000 rects isn't a lot for PC to handle, so I'm inclined to say you have too much overdraw. Yes, disabling blending will make everything opaque, but it will help tell you if your problem is overdraw. – Tenfour04 Mar 13 '14 at 14:42
  • @Tenfour04 Okay so i try to disable it and then i will update my question. Anyway my main question was about what else should i use to render/ create them? In the linked question xoppa told me to to create them out of parts. But how and why? – Robert P Mar 13 '14 at 15:19
  • Not sure about that...he's the expert since he wrote the 3D API. The DecalBatch works differently since it predates the 3D API. Maybe it has to do with method call efficiency. Maybe what you're doing is resulting in a huge hierarchy of nodes that each need separate batch calls, whereas you could maybe be creating a single mesh that is transferred with a single call for better efficiency (on the CPU, not GPU). – Tenfour04 Mar 13 '14 at 15:37
  • Could be... I am stil new in libgdx and this is my first try with 3D, so i am pretty satisfied with the results until now, but ofc i want to optimate performance, if possible. So thats why i was asking – Robert P Mar 13 '14 at 15:42
  • @Tenfour04 would `Gdx.gl20.glDisable(GL20.GL_BLEND);` be the right way to disable blending? – Robert P Mar 13 '14 at 16:20
  • I think you should use the BlendingAttribute in the material. ModelBatch tracks GL state, so trying to directly control it like that probably won't work. – Tenfour04 Mar 13 '14 at 18:48

1 Answers1

1

ModelBuilder#createRect will create a new model for each rectangle. When rendering a (part of a) model instance, it implies a draw call. Therefor ModelBuilder#createRect is extremely inefficient. It is better to combine multiple rectangle into a single (part of a) Model. This can be done using:

modelBuilder.begin();
MeshPartBuilder mpb = modelBuilder.part(....);
mpb.rect(...); // first rect.
mpb.rect(...); // second rect.
// etc.
Model model = modelBuilder.end();

Note that this is still not efficient enough for e.g. a voxel engine. If you are aiming to optimize for voxels, you'll probably want to build the mesh (after frustum culling and depth sorting) in a custom RenderableProvider. Here's an example: https://github.com/libgdx/libgdx/tree/master/tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/voxel

Xoppa
  • 7,983
  • 1
  • 23
  • 34
  • I just started using `MeshPartBuilder` yesterday, as i have seen i can give it UVs for the `Texture`s. Thanks a lot for your answer. Just another little question to this: If i create one `Model` out of the whole left border wall. Is this more efficient, then rendering a few smaller parts (lets say 4 parts) with view frustum culling? – Robert P Mar 14 '14 at 07:00
  • 1
    The only way to answer that question is to benchmark, it depends on too many variables (vertex count, shader complexity, gpu, etc). In most cases, such questions indicate premature optimization. In practice, it is best to use common sense and only optimize if you experience problems. E.g. combine static parts which are likely to be together in the frustum, split parts when one part is likely to be culled and the other isn't and split parts which are the same (duplicates) and might be culled independent of each other. – Xoppa Mar 14 '14 at 23:31
  • Thanks a lot Xoppa this really helped a lot. And thanks for working on the awesome and easy to use 3D API + helping newbies like me to use it :P Keep it up! – Robert P Mar 15 '14 at 09:30
  • Old question and old answer, but i am struggling with understanding the voxel test example. Is there any explanation document as to what exactly is going on there? – themorfeus Sep 01 '15 at 15:34