Grass, butterflies and trees with instancing

Hello everyone!

After watching the last video of Simon Dev on grass, I was inspired to recreate and expand it using BabylonJS. So I had a lot of fun with instances and stuff and it came up nicely I think:

You can try it out at Hello BabylonJS ! (WASD or ZQSD to move around the character)

The framerate holds at 60fps most of the time (not on the screenshot lol) on my Iris Xe integrated GPU. I think the trees my be to blame on that one I am not sure.

All the source code is available on github and I made a PG for a minimal patch of grass here that should be easy to reuse if anyone needs.

I went a bit further by implementing some LoD for the thin instances, and also making the player repell the grass and butterflies.

While making the forest, I also made a higher res version of the texture for the babylon tree. You can find it here

17 Likes

Thanks for your work, this is definitely very helpful !

1 Like

It looks super good!!!

1 Like

Nice. Let me add this to the ‘Field of grass thread’ A post discussing about roads and buildings…oops, no, my bad…it’s about fields of grass…makes more sense, doesn’t it? :joy:

2 Likes

Thank you very much :joy:

I would like to ask you a question:
I found that the control of the thin instance lod in the source code is fully variable, rather than changing individually based on the position of the thin instance, just like the effect of the instance lod. Is this the case?

Cool demo :slight_smile:

Do you use animation ratio for equal timing on different FPSs?
The grass is waving crazily fast on my machine.

Do we support LODs with thin instances? If so, I’ve must missed something very badly :slight_smile: LOD is supported with instances and you have to specify the distance from the camera when setting a LOD. Can you rephrase your question please because I don’t clearly understand what are you trying to get an answer for?

The LoD level is controlled by patch indeed. Thin instances can only have a single geometry model as far as I know so there is no easy way to change individual thin instances model. That’s why I have to change the entire patch.

Thankfully the matrix buffer is reused! A possible improvement would be to avoid sending again the matrices to the GPU but I don’t really know how to do that.

Thanks :wink:

I am using the elapsed seconds from page loading to make the grass wave you see in the shader here:

I use engine.getDeltaTime() / 1000 on every render to accumulate the seconds so I don’t really know what is causing the fast waving :thinking:

Can you try this PG?

1 Like

Yes, amazing demo, but do we support individual thin instances model LODs control? Not updating the entire patch,

don’t think so

Is there a way to implement support individual thin instances model LODs control?

Basically thin instances are a base mesh + a matrix buffer for individual instances.

If you want per instance LoD, you must first have multiple base meshes (one for each LOD level).

Then the tricky part comes in: switching a thin instance from one LOD to another means either:

  • Somehow you can take advantage of thinInstanceCount so that the instance you remove is the last of the buffer so you can increase by one for the new LOD and decrease by one for the old LOD

  • Update the matrix buffer and send it back to the GPU (huge performance hit)

I won’t call this problem impossible, but we should probably analyze your use case before undertaking the impossible ^^

So what is your use case?

seems to be ok, smooth slow motion…

Maybe a more accurate comparison would be with this recording:

Maybe crazy fast animation is just how I programmed it haha

For me it’s running at 120 FPS, so twice the speed.

My use case is vegetation, which includes model trees (with a small amount of vertex data) and alpha trees (just a plane). I want to optimize it by displaying model trees when they are close and switching to alpha trees or model trees with fewer vertices when they are far away. Updating the matrix buffer and sending it to the GPU would be quite performance-intensive. Can we use an approach similar to cascading shadows, setting up different levels of models and dynamically hiding and displaying thin instances in different levels based on distance?

That’s so weird my update loop for the grass material is just:

let elapsedSeconds = 0;
scene.onBeforeRenderObservable.add(() => {
        elapsedSeconds += scene.getEngine().getDeltaTime() / 1000;

        const playerPosition = player ? player.position : new Vector3(0, 500, 0); // high y to avoid interaction with grass
        const cameraPosition = scene.activeCamera ? scene.activeCamera.position : new Vector3(0, 0, 0);
        grassMaterial.setVector3("playerPosition", playerPosition);
        grassMaterial.setVector3("cameraPosition", cameraPosition);
        grassMaterial.setFloat("time", elapsedSeconds);
    });

I will have trouble reproducing the issue since all my screen are 60fps :confused:

Interesting, I see multiple ways:

  • Either go to simple instancing for trees if you don’t need thousands of them (regular instances are quite fast already)

  • Use a custom shader material for your instances: there you will be able to control everything and you can use the vertex shader to remove unwanted instances (set all positions to 0)

1 Like

Unfortunately, there are a lot of trees in my scene. I will refer to the Babylon.js source code and try out the approach with custom shaders.