Z-Up Normals: Stylized Wind Blown Grass

Written For: 4.17 Estimated Duration: 40 mins Difficulty: Medium

After showcasing my latest piece on Twitter, I’ve had many inquiries on how I created the grass in the scene so here’s a walkthrough. This tutorial does require you to have a base understanding of using 3D modeling packages and Unreal Engine.  Shoutouts to Arran Langmead who first taught me the basics of this technique!

watchTower.gif

Start off by creating your grass texture (I’m using Photoshop CC) as solid black silhouette on a transparent background and save as a .png or .targa. Resolution 1024 x 1024.

grass

Then head across to your 3D modelling package of choice (mine is Maya 2016). Model your plane to tightly fit as tightly around your texture as possible so there is a minimal amount of transparent mesh (this helps with reducing overdrawn when we work inside the engine). It’s worth noting, your texture may end up looking a little funky inside Maya, but things will look normal when we get inside the engine.

grass1

We next need to set our vertex normals to face upwards. Select your plane and go to Mesh Display -> Set Vertex Normal and click on the wee square next to it.

grass14

Set the Y Value to 1 and hit Apply.

grass15To check to make sure this has worked, with the mesh still selected, go to Display -> Polygons -> Vertex Normals. If you can’t see any normals go back to Display -> Polygons -> Normals Size and increase the slider until you can see the normals.

grass3

And voila they should be facing up! Duplicate the plane and offset to a X shape before selecting both objects and exporting them as an .fbx.

grass4

Going back to Photoshop we need to create the noise texture that will serve as the wind mask in our Material.Make sure your foreground and background colours are set to black and white, create a new layer and go to Filter -> Render -> Fibers. I set the Variance to 16 and the Strength to 1.

grass5

Still on the same layer, go to Filter -> Distort -> Wave and use the below settings.

grass6

We’ll have to do a little bit of clean-up on the result as the texture won’t tile on the Y-axis. Go to Filter -> Other -> Offset and use these settings.

grass7

You’ll clearly be able to see the seam which we need to fix. My preferred method is to drag the Spot Healing tool, following the contour of the lines, across the seam until it has been removed.

grass8

Once you’re happy with the result save as a .png or .jpeg and open up the engine.Import in your grass mesh, and two textures. Create a new Material for the grass and open up the Material Editor.

grass11

There’s a couple of edits we need to make to the base Material settings. In the Details Panel, change the Blend Mode to Masked, the shading model to Two Sided Foliage and uncheck use Tangent Space Normal.

grass9

The first part of the shader takes our wavy texture and pans it across the world. We start by taking the Absolute World Position and diving it by a Scalar Parameter (WindLineSize) which allows us to control how large the texture appears in world scale. We mask this value down to RG (essentially UV) and plug that into a Panner node.

We then take a Vector Parameter (GrassSpeed) mask that down to RG (again we only want UV values) and plug in into the Speed input of the Panner. This allows us to control the direction and speed of the wind.

The Panner node then plugs into a Texture Sample (our wavy line texture).We take the output of the Texture Sample and Multiply it by another Vector Parameter (GrassOffset) which will allow us to control the displacement of the grass in the X, Y & Z axis.

This Multiply node then plugs into the AdditionalWPO input on a SimpleGrassWind node. Plug two more Scalar Parameters (WindIntensity and WindWeight) into their respective inputs.

grass10

Now if you’ve ever met me at a Game Jam, you’ll know one of my pet peeves is grass that wriggles through the floor. To stop that, create a LinearGradient in the Vaxis, inverse it and plug it into a Power node – which lets us control how high up the stem the grass moves – with a Scalar Parameter (GradientPower).

The output of the SimpleGrassWind node then plugs into the B input of a Lerp and the VertexNormalWS plugs into A. The output of the Lerp links into the World Position Offset.

Create another Texture Sample node with our grass silhouette and plug the Alpha in to the Opacity Mask node. (To be really efficient we should have really channel packed both greyscale textures we are using into one texture but that’s another lesson) and set the Roughness to 1.

grass12

The final thing to do in our Material is to set the colour. Create two more Vector Parameters to control the colour (aptly named Grass1 and Grass2) and plug them into the A & B inputs of a Lerp. Also plug Grass1 into the Subsurface Colour. The Alpha for the Lerp comes from the wavy wind line Texture Sample. This means the grass will fade between two colours as the wind passes across.

The output of this plugs into the B of a second Lerp node. Grass1 goes into A and the Alpha comes from the Power of the Linear Gradient we have created before. This means only the tips of the grass will have a lighter colour applied to them which will give us the effect you can often see in corn fields as wind rustles through them.

Save and Apply the Material and then create a Material Instance and apply this to your grass mesh. This allows you to easily make adjustments to the grass without constantly recompiling. The following are the values I used for my scene but you will have to adapt these to suit the scale/style of yours.

  • Grass1 (colour 1): R 0.0782, G 0.153, B 0.0116, A 1
  • Grass2 (colour 2): R 0.33958, G 0.51, B 0.0, A 1
  • GrassOffset (vertex displacement): R 20, G 20, B -30, A 1
  • Grass Speed (wind direction & speed): R -0.07, G -0.06, B 0, A 1
  • Gradient Power (displacement mask): 3.0
  • Wind Intensity (intensity multiplyer): 1.0
  • Wind Line Size (texture size multiplyer): 3000.0
  • Wind Weight (weight multiplyer): 0.1

grass13

To finish up we need to create another Material for the surface underneath the grass. I recommend setting the colour to the same as Grass1 and the Roughness to 1 to match the base of the grass.

And then finally we need to apply the grass to our scene. Drag the mesh into the Foliage editor, adjust the scaling and density to your needs. Under ‘Instance Settings’ for the grass, I’d recommend turning off Cast Shadows and then get painting!

2017-11-10 20-30-58_1_1.gif