top of page

Grass Shaders

Shell texturing, tessellation, and interactivity.

I made shell texturing and tessellation based shaders in HLSL and Unity Shadergraph.

Grass11.gif
Grass5.gif
Grass15.gif
Grass13.gif

Tessellation and Geometry

A basic approach for rendering grass naturally is through tessellation and geometry shaders. The geometry shader can produce new geometry per-vertex, so we can use that to produce triangles which will make up the shape of our individual blades of grass. Geometry shaders are limited in the amount of vertices they can output though based on API specifications, so for shapes with very few vertices to begin with, we'll use tessellation to sub-divide it, allowing more vertices to be passed into the geometry shader and thus, more blades of grass.

While a typical shader program goes from Vertex straight to Fragment, Tessellation and Geometry shaders actually fit right in between.

  • The tessellation shader subdivides a shape into more shapes (or different shapes i.e. tris->quads), and is comprised of a Tessellation Control Shader (Hull Shader) and a Tessellation Evaluation Shader (Domain Shader).

  • The geometry shader runs per-vertex, and can output new vertices and displace them.

pipe.png

Grass Vertices

In the geometry shader, we simply need to define the shape of our grass with extra vertices. To make our grass stick up out of a surface, we multiply some height by the surfaces normal, and displace that in any tangential direction. Then add another vertex opposite to that tangent to create our first triangle. Repeat as desired. Lastly place a vertex at the top of all that and centered (so simply Normal * Height) to complete a blade.

diagram.png
Grass18.gif
Grass19.gif
Grass4.gif
Grass3.gif

Shell Texturing
An alternative technique for generating a grass-like effect is shell texturing, or "shells & fins". The premise of this technique is to render the mesh repeatedly, slightly farther along the surface's normal each time and with the same transparency pattern each  time. For each mesh (shell) this creates a flat cross-section of would-be grass-blades . By stacking a large number of these cross-sections, the illusion of grass is created. See below. Because this technique is based on a shell mesh instead of vertices for each individual blade of grass, it can potentially improve performance by rendering far fewer triangles (albeit with transparency).

Since this technique is texture-driven, the style can change drastically.

Compute Shaders

There are a number of ways to create the shells in Unity, each with their own pros and cons. Entirely separate objects, objects with multiple materials (Unity renders each one), geometry shaders, and compute shaders, to name a few.

I experimented with many of these techniques, but ultimately decided to utilize compute shaders, since I wanted to offload work to the GPU, and geometry shaders are falling out of the popular sphere in API specifications. Also, compute shaders work on mobile, where geometry shaders may not.

Grass8.gif
Grass13.gif
Grass14.gif
Grass20.gif
Grass7.gif
Grass12.gif
grassb.png
grassc.png

Performance

Performance is a tricky thing - most optimizations (that aren't automatic at this point) come with draw backs.

Shell texturing, for example, has the clear drawback of blurring and distortions when observed from the side - since the "slices" are just quads.

I'll look at testing these shaders with various adjustments and optimizations in the near future.

Grass10.gif

Special thanks to the following resources:

Minionsart

Roystan

Harry Alisavakis

bottom of page