Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Foliage on procedural terrain

How would I make grass, trees and other plants on a procedurally generated terrain in a performant way?

I am generating the terrain using marching cubes, and I don't know what the most performant way to make foliage is. It needs to generate it while the game is running. I have a few ideas myself, but I feel like they would be pretty performance heavy:


  1. Raycasts from above. Pick some points in the air and raycast down to find the position of the ground.
  2. Looping over terrain vertices and placing foliage on some of their positions. I am afraid this will look too grid-like though.
  3. Somehow make a particle system, that only spawn particles on the surface of the terrain. Ideally using VFX graph to make it performant. I just don't know how to make the particles (foliage) only spawn on the terrain and not in the air.


I need a lot of foliage for it to look good, so that's why I want a very performant method. Ideally I also want access to the normal vector of the terrain, so it doesn't place trees on the side of a cliff (I can do that with the raycast method and I think the vertex method). It would also be nice if it could be threaded, but it isn't necessary (you can't use raycasts from other threads for example). I will be really happy if someone can help😀. Thanks in advance!

Best Answer

  • MouledouxMouledoux Member
    Accepted Answer

    Raycast is actually pretty performance lite in unity. That being said, you still wouldn't want to do like a 1000 loop every frame, but you could easily stagger it with something like only (arbitrary example) 20 cast a frame.

    Do you happen to have the Y coordinate by any chance? If you're the one generating the land, perhaps you could add foliage to the landmass generation when you have access to the exact XYZ values.

    I haven't done any ray-marching yet, but I have done procedural hexagon grid generation. I found it easier to do decoration at the time of generation when I have easy access to all the information about it.

Answers

  • ZicrusZicrus Member

    Thank you for your answer! Unfortunately I don't have the y coordinate of the terrain because I use marching cubes, which generates 3D terrains (with overhangs, caves, etc.). So I only know the density of the terrain at a given point. For example a density less than 0.5 is air, and greater than 0.5 is terrain. So I don't have a heightmap to get the y-coordinate of the surface from.

    What did you mean about staggering 20 casts a frame? Did you mean to only do 20 raycast each frame to stretch the load over multiple frames? Because that is actually a really good idea!

  • MouledouxMouledoux Member
    edited June 2020

    Yea, you would just need to save your index and start it next frame at the same place.

    Might look something like this:

    int lastRaycastIndex = 0;
    int totalCastLimit = 400; // whatever your total cast needed is
    private void Update()
    {
        if(lastRaycastIndex < totalCastLimit)
        {
            int maxCast = lastRaycastIndex + 20;
            for(int i = lastRaycastIndex; i < maxCast; i++)
            {
                // do something
            }
    
            lastRaycastIndex = maxCast;
        }
    }
    

    You can change that '+20' to however many cast you're comfortable doing per frame.

Sign In or Register to comment.