BaseGrass - Custom Performant Grass System (Devlog)

Hi! After being annoyed with how un-customizable roblox’s grass system is, I decided to attempt to make my own.

This is supposed to be a devlog, I’ll update overtime with big updates I do to this.

I plan to sometime make this a community resource







Showcase

Video

Screenshot

Doesn’t go through parts

Can generate onto parts




Features

I wanted to make this as customizable as possible while stay remaining performant.
Here’s a lot of stuff you can change:

  • Change mesh
  • Adjust render distance / render details extremely quickly in real time
  • Full control over where/what grass can spawn on
  • Adjust all values related to how close together grass is
  • Grass doesn’t hang off of edges or go through parts
  • Update origin and wind shake as frequently as wanted
  • Full control over how wind is calculated
  • Full control over how color is chosen for each mesh

Also, the grass can be re-loaded for different maps. This would be useful with, for example, a simulator where there are different islands. This allows to only have grass loaded for the island needed. (That may not be worded the best, and this has nothing to do with render distances.) The only downside is there is a slight load time for this.




Performance

I believe I’ve gotten the performance as good as it gets (besides from small micro optimizations). The real performance cost comes from rendering the meshes which due to limitations with roblox, I can’t improve.


Settings applied:

Render distance: 200 studs
Wind shake render distance: 40 studs
Chunk size: 32 studs
Mesh average spacing: 4 studs


~3ms per OriginUpdate:
This is where mostly everything is done. This should only be called around every second but varies depending on how many meshes to move

image


~0.5ms per WindShakeUpdate:
This is called every .07 seconds by default
image


  • There’s a function called :LoadOntoMap which does what it sounds like, it loads grass onto the specified map. A ton of stuff that takes heavy calculations is done here, like deciding where grass can spawn, what colors meshes should be, etc. This does lag a bit but should only be used once upon loading into the game.

  • A couple frames after every OriginUpdate, there are 2 :BulkMoveTo’s is used. These updates are extremely minor so I didn’t include a screenshot.

  • Of course with lighter settings, a lower render distance, and lower shake render distance these are all improved.




Closing and Poll

Let me know what you think! Do you see yourself using this in a game? What are some things you’d like to see added?

When I open source this, I’ll @ everyone who toggles this
  • Me!

0 voters




19 Likes

WOW I love that i allways found the default grass to be a bit weird

2 Likes

Thanks! I agree, I actually feel like a lot of robloxs best features are really plain or unfinished

2 Likes

how does it work?
does it use bones? does each grass have a bone, or do random patches of grass have bones? i want to implement something like this for my game.

1 Like

There are no bones included, theres a bunch of grass meshes (I guess you could also call them grass patches), and ones within a certain distance have windshake applied. I actually used part of boatbombers windshake module to get the windshake looking right, but I don’t use the actual module because it includes a bunch of extra stuff I don’t need.

What each grass mesh looks like:

There’s no real reason I didn’t use bones besides that I have absolutely no idea how to use blender, and also I’m not too sure how the performance of bones is.


There’s a lot that goes on behind the scenes:

Open

the positions where grass can spawn is “baked” (think of it like baked lighting) when loading into the game and stored for later using spatial partitioning. When being baked a bunch of stuff is stored like the type of mesh to be spawned at that position, the color, cframe, etc. This is also where it decides if the grass can even spawn at the position, by checking for holes underneath it, dropoffs of the ground, etc.


Then, in real time, grass is spawned only on the grass spawns within x amount of studs (distance checked with spatial partitioning). There’s a custom LOD where the farther away the grass spawns are, it may skip, for example, every other grass spawn so grass is less dense. The meshes are also pooled and recycled so it’s not always creating new instances.

Visual:


A lot of the calculations or heavy tasks are spread out across frames. For example, when moving all of the grass meshes that need to be moved (they may be being pooled, going to a grass spawn, being recycled to a new grass spawn), I use :BulkMoveTo in seperate groups. Depending on the amount of meshes and the settings the user set, there may be 8 groups all moving ~50 meshes each. Then between each group theres a task.wait. There’s a couple other cases of this throughout the script where it’ll use task.wait if a calculation is taking too long. This is just to save peformance so there’s not sudden frame spikes.

2 Likes

thanks, this is really helpful
you should consider:

  • using parallel luau
  • stopping all loops when the window is not in focus (coroutine.yield())
  • not move grass in the wind when its a distance away from the camera

and also i think u should add nodes where grass renders, e.g. 100 studs in front of the player + around the player, grass can spawn. this makes it so that, for example, if im using a spyglass that sees a long distance away, grass can render at the chunks the spyglass is focused on.

3 Likes

I tried this, but I couldn’t get it to work because there’s too many tables being moved with indexes that SharedTables can’t have. Maybe I’ll give it another try sometime but for now the performance is good enough without

The grass only updates when your characters moves x amount of studs. It can also update with the camera but It’s just whatever you choose the origin to be

I already do this

I’m not really sure what you mean, do you mean like frustum culling? (only have grass where the player’s camera can see).

If so, this can already kinda be done, by just setting the origin to be x studs infront of the camera’s cframe, but this means that a lot more grass will be moved around a lot faster so it ends up not helping performance much

1 Like

by the last thing i mean:
your character is a ‘node’ which renders grass around it. what if i wanted to render the grass around another node, i.e. have another node that renders grass around it?

1 Like

You mean having multiple “nodes” (I call it origin) where grass can spawn? I guess I could add this, but I’m not too sure how this would interact with the LOD and also performance.

Right now the function to update the origin looks like this:

Grass.UpdateOrigin(Origin, RenderDistance, WindShakeRenderDistance, BulkMoveGroupMaxParts, PreciseDistanceCheckRadius, MaximumTaskComputeTime, DebugColors)

I don’t really see how you would need multiple area where grass can spawn anyhow. If you look through a spyglass, you could just start updating the grass origin to be 100 or whatever studs infront of the camera

1 Like

Question!!! (its me again) Can you make it bend when the player steps on it?
image
(found on Google)

3 Likes

Yes and no. I could easily add this, the closer grass is the more detailed and the more precise values there are (like a more precise distance value). The only issue with this is that the grass meshes are large patches of grass like this:

image

So it may look odd tilting a large mesh like that. Although, there is support for any size of mesh so this could look good when you have smaller meshes in use.

I’ll keep this in mind when I next work on this, it’s a cool idea!

3 Likes

Is this still in development? I was wondering if you would implement things like grass clumping or wind that blows the grass in wave like patterns.

Hi! I havent been able to work on this lately because ive been busy irl and ive been working on a game, although I do plan to come back to this sometime and continue to work on it.

Im not too sure what you mean by this

The windshake is unfortunately pretty limited because the grass is large meshes.

Great to hear about your developments. By grass clumping I meant if the grass would have varying densities. Or if they would realistically clump like bushes, where it looks as if multiple grass blades come from a single point. It’s hard to explain, I recommend you search up “grass clumping”.

Yeah, okay. So cool. Grass. But can it make rocks?

Yes this is possible. In the future id like to make it so you can paint grass (and other foliage) like the one BrushTool plugin. Right now the system gets all parts tagged with grass and automatically adds grass spawn points itself.

Drum roll :drum: :drum: :drum: :drum:

Yes it can, but not recommended

YES!

1 Like