Recursive instancing with geometry nodes

Generating geometry recursively with geometry nodes is a great way to implement fractal-like geometry such as plants. However, it seems that only four levels of instancing can be done without realizing the instances.
In case some one else wonders how this can be fixed, I leave this little tip here.

Here is a simple example setup that should have five levels of lines that each spawn three new lines. But only four levels come out (long vertical line spawning 3 horizontal lines spawning 3 vertical lines spawning 3 horizontal lines).

Connecting the Realize Instances node at any point in the recursion gives the missing vertical spawns.

(I would have posted another image here with the Realize Instances node connected, but apparently new users are only allowd for one picture.)

Of course, more proper way to implement this would be to make a node group that is dublicated desired number of times. Then one could realize instances inside the node group and all would be good.

In Blender’s documentation (Geometry nodes get instance position and use it recursively) it says that “However, performance can become much worse when the input contains many instances of complex geometry, which is a fundamental limitation when procedurally processing geometry.” Does anybody happen to know what performance penalty they are talking about? Worse performance in UI or in rendering? And is there any benefit trying to avoid unnecessary instancing if I still need to instance at least once to get enough recursions?

I don’t have a problem with this. I’m just curious of the inner working of Blender in this specific case.

2 Likes

Hello !

I don’t have a lot of experience with nested instances, I tried that once and indeed I got worse viewport performance ( workbench and eevee).
It’s already the case with lots of instances, but nested made that worse.

My use case was to generate grass. For that I had a plane with a bunch of grass blades as a texture.

That plane then gets duplicated a bunch of times to form a clump, and that clump was instanced in a vast field.

removing the recursion made the viewport much faster, and realizing the whole, even if that leads to a lot more geometry in the scene it made the viewport even much faster.

Cycles really handles instances much better, you really have a benefit using them.
With Eevee you save some memory but not FPS, performances deteriorates quickly, to a point that you might find cycles realtime much responsive and even workbench impossible to work with.

little things to know, when drawing stuff like wireframe, or selection it get even worse.
Like cycles might be fine to display the scene smoothly, but activating overlay will slowdown the viewport.

And on a slow viewport (eevee workbench) , activating overlay will make it twice as slow.

I didn’t tested how Cycles reacts with nested instances.

Now instead of being really atomic I try to find a good balance between instances number and instanced object’s polycount. And I avoid nesting , but I should investigate a bit more probably.

1 Like

Hello sozap!

I investigated the performance a bit in my actual scene (not the toy problem shown in the opening post). Im building a tree with recursive branching with 4 levels of branches (including the trunk) and leaf (simple cube) as the fifth recursion. The tree has ~110k faces and I’m rendering with Cycles. Vieport was set to solid.

When realized inside the recursion, the viewport is really smooth and render time 9 s.

Without realization, the viewport is very sluggish and and render time 4.5 s. Though the leaves do not show (the case in opening post). Adding a single realization outside of recursion just after the one that spawns the leaves makes the viewport usable again and renders in 10 s. Also, when the single realization is moved to the last step right before the trunk recursion, viewport is again ok and render time is 9.4 s. So at least it seems that it doesn’t matter at which point one realizes the instances.

As these figures are not comparible because one did not spawn the leaves that contribute the most in face count, I tried with removing one level of recursion.

Now the wieport is usable in all cases. I increased spawned instances so that the face count is still ~110 k for the whole tree.

Same tests in the same order:
- Without realization at all: render time 11.90 s
- Realizing in recursion: render time 8.27 s
- Realizing only the one that spawns leaves: render time 10.54 s
- Realizing only just before trunk: render time 8.68 s

This example may be too small to get any differences visible. But based on this, I’d say that it’s best to realize inside the recursion as it produces the best render performance and does not penalize the viewport.

A kind of a side note: realizing inside the recursion is also the only case when the last recursion Output node shows, what I assume to be, the correct number of faces.

This leaves me still wondering what they talk about in the manual. Maybe it’s old documentation from some earlier versions that does not apply anymore.

Have to try this again when I have a full scene with lots of these trees.

2 Likes