How to make grass

Hello, i was wondering how to make grass, using a plane that face the camera is really ugly, using a cylinder show the grass texture also on top, so no, a cone works but it doesn’t have a great look. So how do i do it?

1 Like

Hi @ayrin,

To make realistic grass in realtime rendering isn’t easy, mostly due to the number of patches/strokes of grass you need to render.

Usually the billboard approach is what most games, even AAA games, use. If you can render a large number of them in big numbers then it can look quite realistic or at least sufficiently for the game realistic.

What I usually do, instead of forcing the grass planes to face the camera, I place them in random rotations, enable two-sided rendering on their material and use batching/instancing to draw a large number of them.

You can also add at the same time a wind animation (easily done so using a vertex shader) to make it look alive.

Here are some freely available grass assets to get you started:

@Leonidas placing them randomly rotated would need a large amount of them to make it look realistic i guess. Will not that affect the fps rate?

Yes it would, so you will have to use a number of techniques like batching/instancing together with frustum culling, as well as you may have to add some custom occlusion logic of your own.

Open world games aren’t easy :slight_smile:

Awww…yes i noticed it isn’t…guess i will park the idea of making grass and focus on making a tile mapping for the terrain that would add some realism itself. Anyway the best way to achieve what you suggested is box shaped models that use 2 materials, when they are close you show the side where the grass is displayed 2 sided, when far you disable the side view and enable the top view where the texture show the top of a grass field. That way you will have the best result.

1 Like

Hi @ayrin,

Check this twitter thread on some ideas on what’s possible for grass in Playcanvas.

1 Like

Any chance this is available anywhere, or, is there a way to learn how to make a shader such as this? These are black magic to me. I’m not even sure what type of shader to learn…!

Yeah, you can use a shader to generate grass though in WebGL we aren’t provided geometry shaders to add polygons on the fly, so it can become a bit tricky.

What you see in the picture above isn’t anything special:

  1. Simple grass billboards (plane with a texture) that are rendered from both sides (using a PlayCanvas material).

  2. The variation on the grass color is basically an exploitation of a bug, the back side of the grass plane uses the normals of the front side for lighting. If you don’t understand this no worries, any regular plane has the same issue (you will observe different lighting depending on what side of the grass receives light).

I’ve fixed that bug and used a different strategy in future versions, rotated all side normals to face directly upwards (did that in Blender and exported a single plane to PlayCanvas) and added a noise texture that is sampled in world space.

  1. You can see that many grass blades rendered because the grass material has hardware instancing enabled. That allows you to render A LOT of polygons in a single draw call, check this example on how that works:

That is enough to get decent rendered grass. But if you are creating an open world here comes the tricky part:

  • How do you handle the increase in the polycount?

Hardware instancing will send all grass blades to the GPU for rendering, both visible and non visible, there is no frustum or distance culling there. You will have to handle that on your side and decide on a culling strategy.

One thing I do to simplify that is to split the grass blades into cells, and check per frame if the cell is visible (frustum culling) and close to the camera (distance). If a cell pass both criteria I add it to the vertex buffer sent to the GPU (check the hardware instancing example on how that works).

  • How do you place that much grass in editor?

Creating entities for each grass instance would eventually kill performance. And at the end it isn’t required the way HW instancing works. So you can do a number of things:

  1. Calculate the positions in your modelling/world creation app.
  2. Calculate the positions in code procedurally (for the height either raycast or pass your terrain heightmap to the vertex shader and calculate the required height offset there).
  3. Create a PlayCanvas editor extension that allows you to paint grass on your scene and save the translation info in a file (e.g. json or binary).

Hope I’ve been of help.