One more InstancedNode vs BatchNode basic question


I’ve been reading around the forum and the website about batchnode and instancednode, specially from these links:

But I don’t find clear enough which of them should I use for my case and also exactly how to do it. The part of the scene I would like to batch/instance has around 50 geometries of 6 different models using 2 different materials.

I tried both and I didn’t get the desired results, in both cases framerate dropped between 20-30% and the counters of the statsview remained more less the same (which from my point of view should have been lowered based on information at So I think either I didn’t undertand anything correctly or I’m not using this feature in the correct way.

In both cases, I’m adding all ~50 nodes/geometries to the same node and call batch() or instance() afterwards. This node is child of the root node of the scene. More less the same way the tests in the jmeTest project are done.

I don’t know if this is the correct way of doing this, specially for instancing after reading the comment of the linked post from momoko_fan:

“Yes the mesh instances have to be the same for instancing to work. Material instances also have to be the same for objects to be instanced together. This doesn’t mean instancing will break or anything, just that you won’t see any performance improvement if all objects are completely different.”

That makes me think if I would need to create one InstancedNode for each different geometry or the instance() method is smart enough to group them.

In adition to that, my project is for android, although most of my testing is done in the PC. I don’t think that instancing is supported on android as having a look at the jme3-core code only GL_ARB instancing extensions are checked in the GLRenderer but GL_EXT extensions are not checked that would be the proper extensions for GLES 2.0 ( and also GLES 3.0 is not used and instancing is a core feature in that version and onwards (

Any advice is welcome :wink: Thanks!!

Are you sure they use only 2 different materials? Like, geom1.getMaterial() == geom2.getMaterial()?

Thanks for you reply @pspeed in fact you were right, although materials seemed to be the same they were different materials, I was fully cloning the geometries so materials were also cloned :face_with_raised_eyebrow: Just changing the cloning to avoid cloning materials also, it started to work.

I’ve been making some tests and I’m not fully satisfied with the results. The counters for frame buffers and textures remains the same for all three modes (normal rendering, batched and instancing) but the remaining changed a little:

___________ | normal | batch | instance
Shader(M) | 28 | 28 | 33
Shader(F) | 27 | 27 | 32
Shader(S) | 37 | 37 | 60
Objects | 497 | 274 | 351
Uniforms |~650 | ~280 | ~280
Triangles |174091 | 193687 | 193687
Vertices |194183 | 216455 | 216455

First of all, from execution to execution using one method or the other, I got differences between 2% and 7% fps increase in the best case, but it’s not a great speed increase as I thought in the first place. Also, I expected batch to be faster than instancing (as pointed in other threads) but in my PC it was the other way round. Is it normal nowadays with new enough hardware?

Why is batching and instancing using more vertices and triangles than regular rendering?

In the case of instancing, materials need to have the UseInstancing=true defined but this makes non InstancedNode’s to avoid rendering the models. Is there any way to avoid it other than looping through all the geometries and set it to false in case hardware doesn’t support instancing? (and not calling instance() )

Also related to instancing, is it normal that shader switch is almost double?

Having a look at the counters, what do you think would be the best way to go?

Thank you :wink:

** Sorry about the table, while editing it seemed nice enough :confused:

There are so many variables in what you are trying to do. If you want to learn what means what and what happens when X, Y, or Z change then you may want to start with some more controlled tests.

For example, JME Boxes and code-crafted materials for one. There could be a lot of different things going on with the models themselves that we can’t see… so it’s hard to comment.

In general, 5000 plain geometries will be 5000 draw calls.
5000 instanced geometries will be 1 draw call to the GPU driver but the equivalent of 5000 draw calls inside the driver.
5000 batched geometries will be 1 draw call to the GPU all the way down… but a LOT more memory taken (5000x). It will be the fastest way, though… by a long shot. It also requires no special support (presuming the RAM can hold it).

But between “random imported” model, JME utilities, etc… there could be a lot that splits from those ideals. Then you have to poke around and figure out why.

1 Like