Creating an interactive grass in the Unreal Engine

Creating an interactive grass in the Unreal Engine
 
Until recently, grass in games was usually referred to as a texture on the ground, rather than rendering individual stems. But with the increase in the power of iron, it became possible to render the grass. Remarkable examples of this rendering can be seen in games like Horizon Zero Dawn and The Legend of Zelda: Breath of the Wild . In these games, a player can wander through grassy meadows, and, more importantly, grass reacts on the actions of the player.
 
 
Fortunately, it is not very difficult to create such a system. In fact, the article will teach you exactly this! In this tutorial you will learn the following:
 
 
 
Create a vector field by using a scene capture and particle system
 
Bend the grass from the player on the basis of the vector field
 
Unreal Engine for Beginners . In particular, pay attention to the tutorial on systems of particles to know how to use Cascade in this tutorial.
 
Note:
This tutorial refers to a series of three tutorials for working with render targets:
 
 
 
Part 1: Drawing with Render Targets
 
Part 2: deformable snow
 
Part 3: Interactive grass
 
 

Let's get to work


 
Let's start with downloading the materials for this tutorial (you can download them from here ). Unzip them, go to
InteractiveGrassStarter
and open
InteractiveGrass.uproject
. You will see a small field of grass, which will be the theme of this tutorial. I also created a widget to display the render target of the scene capture.
 
 

 
 
Before you proceed, you should study the tutorial. on the creation of tracks on the snow , because I will skip some information. It should be noted that this tutorial also uses capture and projection. To save time, I prepared a capture blueprint, similar to the tinted blueprint on the tracks in the snow.
 
 
First, let's look at another way to create an interactive grass. The most common method is to transfer the player's coordinates to the grass material and to use a spherical mask to bend the grass in a certain radius from the player.
 
 
Although this approach is quite good, it scales poorly when we want to add more grass-influencing actors. For each added actor, one more coordinate parameter and a spherical mask will have to be added to the material. A more scalable method is to use
of the 3 r3r3898 vector field. .
 
 

What is a vector field?


 
A vector field is just a texture, each pixel of which corresponds to the direction. If you used to work with stream maps, then they are similar. But instead of moving UV we will be using contact World Position Offset move vertices. Unlike the solution with a spherical mask, only is sufficient to obtain the bending direction of the materials. once sample a vector field.
 
 
Let's find out how you can save directions in the texture. Look at this grid:
 
 

 
Let's say a red dot is an object that we want to move. If we move it to the lower right corner, which vector will this move? If you answered
(? 1)
, then you are right! As you probably know, you can also represent vectors in the form of colors, and thus save them in the texture. Let's insert this vector into the color picker Unreal and see what color it will return.
 
 

 
As you can see, the direction is
(? 1)
returns a yellow color. This means that if we want to bend the grass along the direction of the positive XY axes, then we will have to use this texture color. Let's now look at the colors of all vectors.
 
 

 
The right bottom square looks pretty good, because it has gradients on both axes. This means that we can store in this quadrant in the form of a color any vector, because each vector has a unique color.
 
 
But with the other three quadrants there is a problem. We have a gradient only on one axis, or there is no gradient at all. This means that several vectors will have the same color. For example, we can not distinguish the vectors
in any way. (-? 1)
and
(? 1)
.
 
 
These three quadrants do not have unique colors for each vector because we can only represent colors using values ​​from 0 to 1. However, these three quadrants use negative values ​​that are outside this range.
 
 
The solution is to redistribute the vectors in such a way that they all fit in the range from 0 to 1. This can be done by multiplying the vector by
???r3r3898. and adding
???r3r3898. . Here is a visualization of what we get:
 
 

 
Now each vector has a unique color. When we need to use it for calculations, we simply redistribute it back into the interval from -1 to 1. Here are a few colors, and the corresponding directions after redistribution:
 
 
 
(? 0):
negative X and Y
 
(0.? 0.5):
there is no movement
 
(? 1):
negative X and positive Y
 
(? 0):
positive X and negative Y
 
 
Now let's find out how to create a vector field in Unreal.
 
 

Creating a vector field


 
Unlike the creation of tracks on the snow, we will not perform the capture of the shape of objects. Instead, we will draw on render target with the help of "brushes". It will be just images of the selected vector field. I will call them
brushes directions
.
 
 
Instead of drawing on render target with the help of the blueprints, we can use
particle
. The particles will display the brush directions and emitted from the player. To create a vector field, it's enough to use scene capture and capture only particles. The advantage of this method is that creating traces is very simple. In addition, it allows you to easily manage properties such as the duration of the preservation of tracks and their size. In addition, the particles create temporarily persistent traces, because they exist after leaving the capture area and returning to it.
 
 
Below are a few examples of brushes directions that we can use, as well as their effect on the grass. Notice that in the example below the particles are invisible.
 
 

 
First, let's create a material that will display the directions brush.
 
 

Creating material for directions


 
There are two ways to create a brush direction:
 
 
 
Mathematical:
directions and form are defined inside the material. Its advantage is that it does not require third-party software and is convenient for simple forms.
 
Mapping of normal maps:
Creation of a map of normals of the necessary directions and forms. To convert a map into a suitable vector field, it is enough to remove the blue channel. The advantage of this method is that it is very easy to create complex forms. Below is an example of a brush that will be difficult to create mathematically.
 
 

 
For this tutorial we will create a brush mathematically. Go to the folder
Materials
and open
M_Direction
. Note that for this material, a shading model of
has been selected. Unlit
. This is important because it allows the capture of a scene to capture particles without affecting the lighting.
 
 
In order not to complicate, we will create a material that will cause the grass to move away from the center of the particle. To do this, create the following scheme:
 
 

 
Now we need to redistribute. To do this, add the selected nodes and merge all as follows:
 
 

 
Now let's give the brush a round shape. To do this, add the selected nodes:
 
 

 
RadialGradientExponential
controls the size and sharpness of the circumference of the circle. Multiplying it by
Particle Color
allows you to control the opacity of particles from the particle system. I will discuss this in more detail in the next section.
 
 
Here's how the brush looks:
 
 

 
Press
Apply
and close the material. Now that we've created the material, it's time to start the trace particle system.
 
 

Creation of a system of trace particles


 
Go to the folder
ParticleSystems
and open
PS_GrassTrail
. To save time, I have already created all the necessary modules.
 
 

 
Here's how each module affects traces on the grass:
 
 
 
Spawn:
the frequency of creation affects the smoothness of the tracks. If the tracks look intermittent, then it's worth to increase the frequency of creation. In this tutorial, we leave the default value (20).
 
Lifetime:
The lifetime of the trace before the grass returns to its original state
 
Initial Size:
the size of the track is
 
Color Over Life:
as we use in the material of Particle Color, here you can control the opacity. You can also change the alpha curve to control the disappearance of the track. For example, you can select linear loss, easing in and /or easing out. In this tutorial, we will leave the default setting, that is, linear loss.
 
Lock Axis:
It is used for the particles to be directed towards the capture of the scene
 
Initial Rotation:
It is used for the particles to be oriented along the right axes (more about this later)
 
 
First we need to set the material. Select the module
Required
and set for
Material
the value
M_Direction
. Also set for
Sort Mode
the value
PSORTMODE Age Newest First
.
 
 

 
This sorting mode allows you to render new particles on top of old ones. If this is not done, then the grass will not be affected by new, but old particles.
 
 
Next is the duration of the trace. Select the module
Lifetime
and set
Constant
the value
5
. Thanks to this, the track will disappear within five seconds.
 
 

 
Now go to the size of the track. Select the module
Initial Size
and set for
Constant
the value
(15? 15? 0)
. Due to this, each particle will cover an area of ​​150 × 150.
 
 

 
Now we need to make sure that we are looking in the direction of capturing the scene. Since the scene is captured from the top view, the particles should look in the direction of the positive Z axis. To do this, select the module
Lock Axis
and set for
Lock Axis Flags
the value
Z
.
 
 

 
Finally, we need to specify the rotation of the particles. To date, the colors of the brush are not aligned with the direction they represent. It happened because by default the particle system is applied with a rotation of 90 degrees. To fix this, select the module
Initial Rotation
and set for
Constant
the value
-???r3r3898. . This will rotate the particles 90 degrees counterclockwise.
 
 

 
And that's all we need for a particle system, so let's close it.
 
 
Next, we need to attach the particle system to what should create traces. In our case, we need to attach it to theThe player's face.
 
 

Attaching the particle system


 
Go to
CharactersMannequin
and open
BP_Mannequin
. Next, create the
component. Partice System
and call it
GrassParticles
.
 
 

 
Next, we need to specify a system of particles. Go to the Details panel and set it to
ParticlesTemplate
the value
PS_GrassTrail
.
 
 

 
It would be strange if the player could see the track in the game, so you should hide it. To do this, include
RenderingOwner No See
.
 
 

 
Since the system of particles is attached to the player (the owner), the player will not see it, but it will be visible to everything else.
 
 
Press
Compile
, and then press
Play
. Note that the particles do not appear for the player's camera, but are displayed on the render target.
 
 

 
While the capture of the scene is set to capture total . Obviously, this does not suit us, because only the particles affect the grass. In the next section, we learn how to perform the capture of only particles.
 
 

Capture of particles


 
If we grab the particles now, then we will perform unnecessary bending in regions without particles. This is because the target color of the target target is black. Flexion occurs because black denotes movement toward negative XY axes (after redistribution). To ensure that empty areas do not contain movement, we need to make the render target background color
(0.? 0.? 0)
. The easiest way to do this is by creating a huge plane and attaching it to the player.
 
 
First, create a background material. Go back to the Content Browser and open
MaterialsM_Background
. Then connect the constant
(0.? 0.? 0)
with
Emissive Color
.
 
 

 
Note:
as in the case of particle material, any material that we will capture must have a shading model of
unlit
.
 
Press
Apply
and close the material. Go back to
BP_Mannequin
, and then create a new component
Plane
. Call it
Background
.
 
 

 
Then set the following properties:
 
 
 
Location:
(? ? -5000). We place the plane so low that it does not block any particles.
 
Scale:
(10? 10? 1). This is how we scale up to a size sufficient to cover the entire capture area.
 
Material:
M_Background
 
 

 
As in the case of particles, it would be strange if the player saw under him a huge yellow plane. To hide it, turn on
RenderingOwner No See
.
 
 

 
Now that we've set up the background, it's time to grab particles. We can do this by adding a particle system to the list
show-only list
capture the scene. This is the list of components that will capture the scene capture.
 
 

Using the Show-Only List


 
Before we get the opportunity to add to the show-only list, we need a way to get all the actors influencing the grass. One of the ways to get them is using
tags
. Tags are simple strings that can be assigned to actors and components. Then you can use the node
Get All Actors With Tag
to get all the actors with the appropriate tag.
 
 
Since the player's actor must influence the grass, he needs a tag. To add a tag, press the
button. Class Defaults
. Then create in
ActorTags
a new tag and call it
GrassAffector
.
 
 

 
Since only can be transferred to the show-only list. components , we need to add tags to the components that affect the grass. Select the
component. GrassParticles
and add a new tag located in section
Tags
. Call it also
GrassAffector
(
? optionally
? use this tag). Repeat the same for the
component. Background
.
 
 

 
Now we need to add the grass-affecting components to the show-only list of the scene capture. Press
Compile
and close
BP_Mannequin
. Then open
BlueprintsBP_Capture
. Go to
Event BeginPlay
and add the selected nodes. Also make sure that the marked contacts are connected.
 
 

 
This scheme will bypass the cycle of all actors with the tag
GrassAffector
. After that, it will check if the actor has components with such a tag, and add them to the show-only list.
 
 
Next, we need to tell the scene capture, so that it only uses show-only list. Select the
component. SceneCapture
and go to section
Scene Capture
. Specify for
Primitive Render Mode
the value
Use ShowOnly List
.
 
 

 
Press
Compile
and close the blueprint. If you click on
Play
, you'll see that render target now only captures particles and the background plane.
 
 

 
In the next section, we'll get to what we expected. It's time to teach the grass to bend!
 
 

We bend the grass


 
First we need to project render target onto the grass. Go to the folder
Materials
and open
M_Grass
. Then create the nodes shown below. Specify the texture as
RT_Capture
.
 
 

 
Since we redistributed the colors in the interval from 0 to ? we need to redistribute them back to the interval from -1 to 1. before use. To do this, we add the selected nodes:
 
 

 
Now that we have the direction of bending, we need some way to turn the grass in this direction. Fortunately, there is a node called
for this. RotateAboutAxis
. Let's create it.
 
 

 
Let's start with contact
Normalized RotationAxis
. As you can see from the name, this is the axis around which the top will rotate. For calculation, we only need vectorial product direction of bending by
(? ? -1)
. To do this, we need to add the selected nodes:
 
 

 
Also we need to specify
RotationAngle
, that is, the amount of rotation of the vertex relative to the point of rotation. By default, the value should be in the range from 0 to ? where 0 is 0 degrees, and 1 is 360 degrees. To obtain the angle of rotation, we can use the length of the bending direction, multiplied by the maximum rotation.
 
 

 
Multiplication by the maximum rotation in
???r3r3898. will mean that the maximum rotation angle is
72
degrees.
 
 
Calculation of
PivotPoint
- A slightly more complicated task, because one mesh of grass contains several stems. This means that we can not use something like node
Object Position
, because it will return one point for all the grass stalks.
 
 
Ideally, you should use a third-party 3D editor to store points of rotation inside UV channels. But for this tutorial, we just approximate the point of rotation. This can be done by moving from the top
down
for a certain offset.
 
 

 
To do this, add the selected nodes:
 
 

 
In this tutorial, the grass is about 3-33-?897 in height. 80
units, so I ask for
PivotOffset
this value.
 
 
Next, we need to perform two masks. The first mask ensures that the root of the stem does not move. The second mask ensures that the vector field does not act on the grass outside the capture area.
 
 

Masking


 
For this tutorial, I set the colors of the vertices of the grass in such a way that the lower vertices are black and the top vertices are white.
 
 

 
To mask the roots, we simply multiply the result
RotateAboutAxis
to the node
Vertex Color
.
 
 

 
To mask the grass outside the capture area, we multiply the previous result by the selected node:
 
 

 
Press
Apply
and close the material. Press
Play
and run along the grass to leave traces on it!
 
 

 

Where to move next?


 
The finished project can be downloaded from here.
 
 
Although the method shown in the tutorial works great for such simple objects as grass, it is not enough when using objects that require more dynamism. Partial solution of the problem is to use physical versions of foliage. For more information, see this post is about interactive foliage.
 
 
Finally, I want to thank Deathrey from the Unreal Engine community for hinting this method with particles!
+ 0 -

Add comment