a tutorial on Medium because where else should I put it these days
Grass is often the bane of 3D scenes: it spans the range from a flat plane with a diffuse texture slapped onto it to particle systems rendering tens of thousands of blades, stems and weeds to create this entire ecosystem and crank rendering times through the roof.
Vray has enjoyed microdisplacement for a long time now so this grass technique isn’t super new, but I thought it was worth the tutorial for Blender since tessellation is a relatively new feature for Cycles (and sure beats the old method of crazy subdividing everything at a geometry level).
Here’s my baseline test render. We’ve got our “building” and a “sidewalk” and a strip of grass that goes around the corner. This particular (heh) render is Andrew Price’s Grass Essentials pack, which I really do endorse and love for hero shots of grass like this:
But in the context of a building like the above, it’s pretty inefficient. That’s a 7:40 render time just for what might be a really minor detail in the end of a scene that’s mostly building with large parking lot.
So the real goal is:
- be vertical to give the edges of things silhouette (where grass meets the wall, where grass is in front of the sidewalk that juts backwards, where the sun shadow line interacts with some blades and not others to give lighter and darker spikes)
- be faster rendering so we can use this for animations so we can iterate and work on video projects in hours instead of days or weeks
- be relatively lightweight on VRAM so we can fit it into the GPU (fortunately the 1070’s 8 GBs has handled even weighty scenes like a champ, but not too long ago I was running 2 GB so hitting that limit was easy and frustrating)
- be relatively easy to set up / import and have running. I like the endless freedom of particles, but the fact is I don’t really care or have time to delicately set up little lawn strips every time I import the group. This also dynamically does LoD which means I don’t have to manually weight paint grass densities to shove them closer to the camera / occluded behind building geometry / etc.
- look like grass, or at least enough to be better than a flat plane with a dumb grass texture on it
First try with displacement was okay but not great.
The encouraging part was that we got render times down. 1:58 which is nearly 1/4 of the time as before. Awesome!
I set up a separate testbed so I could play with dicing rate by itself.
Dicing rate difference between 1.0 and 2.0 is 80% less VRAM usage and 26% faster rendering, but the difference between 2.0 and 3.0 was only 20% less VRAM (than 2.0), and a scant 5% improvement on render times, so clearly there was some diminishing returns to uglier dicing rates getting fast results.
I suspected from this point there’d be a sweet spot somewhere in 1.5 to 2.5 and as it turns out, my final grass for the building render was 1.8
At this point we’re still using the diffuse shader with an image texture and the spikes look solid and spiky.
This is the hair shader which smooths out a lot of the lumpiness in the main body of the grass and yet continues to give us the nice silhouette we’re after.
Render time goes up to 2:12 but still a huge reduction from 7:40 and the 14 seconds really does look much nicer. It’s worth it.
…and finally, we can texture that back with an image or procedurally to give it some more random-feeling variation. I didn’t run the texture straight, you’ll see an RGB mix in the nodes — grass, while random, is shockingly uniform. You don’t need much to give it the effect and so grass textures intended for use as plain diffuse materials are often too random feeling.
Final render time is 2:15 which is awesome compared to 7:40.
A few notes here:
- I actually use the non-color data even though the texture is green. Seems to help the bump / displacement and I can remix the green back into my final material with the same colour mix that I was using to de-randomize the texture anyway, so, a bizarre win-win.
- the hair BSDF is used straight which I was sort of shocked by, but great. I just eyed everything in situ. The color, the roughness(es), the texture showing through: it’s all to taste and per lighting. Ideally we’d use magic PBR so it’s always good, but it’s 90% useful in any situation right now and it’s so easy to adjust I’ll prioritize keeping the nodes simple.
- the multiply is the strength of the grass bump, which is essentially grass height in the same way you’d use particle size. The subtract node just keeps the whole plane from jumping up and floating with higher values (above 2, say, which means we probably don’t need it for 0.8) and the value for subtract seems to work nicely at 1/2 the value for multiply.
No idea why.
- Dicing rate is 1.0 in the subsurf panel and adjusted in the rendering panel to 1.8 and a preview of whatever you want. The default max subdivisions is 12, I found 10 is okay and slightly faster, but you really get nicer grass spike shapes with higher numbers. As shown above, it’s 11.
- in the material panel, make sure you set bump to ‘true’ so it’s actually 3D
I think that’s pretty much it. The other good news is if you append it into different scenes you don’t also need to worry about particle groups and multiple materials and everything. It’s pretty much plug and play.
The downside is that you won’t get any fancy weeds or weight painting for density or anything but for my purposes I just wanted little rectangles of lawn to put in front of buildings. They’re almost always thin and flat and the bare minimum to be considered ‘green space’ in marketing materials. As such, you don’t want to render them with weeds anyway, though it’s more realistic.
If you really wanted, you could use Grass Essentials in conjunction with this method to intersperse real geometry bushes and weeds and stuff with faster, fake grass.