Creating a vertex displacement material with Shader Graph
Animate the vertices of a mesh over time with 3D Perlin noise by creating a Shader Graph material.
Overview
Moving the vertices of a mesh with a shader is a valuable technique to have in your shader toolbox. Using this technique, you can procedurally distort the shape of a mesh and animate it over time, all without having to author explicit frame-by-frame animations. Moving the vertices displaces them from their original positions, so this effect is known as vertex displacement, as shown in the example below:
To create a shader graph material that displaces the vertices of a mesh over time, apply a positional offset to each vertex with a Geometry Modifier node and a Noise 3D node. You can control the amplitude, scale, and rate of displacement with shader uniforms. See Loading entities with ShaderGraph materials to download a sample project containing this shader along with many others.
Prepare a displacement node graph
House the vertex displacement logic in a reusable NodeGraph by following these steps:
Create a custom Shader Graph material (Insert > Material > Shader Graph).
Open the Shader Graph Editor by clicking the Shader Graph button.
Add a
NodeGraphnode by clicking the New Node button or pressing the tab key and searching for “Node Graph”.Name the
NodeGraphnode “Displacement”.Add a new input to the Displacement node graph by selecting it and clicking the New Input button in the Inspector.
Name the new input “Position” and give it a type of
Vector3 (Float).Add a new output to the Displacement node graph by selecting it and clicking the New Output button in the Inspector.
Name the new output “ModelPositionOffset” and give it a type of
Vector3 (Float).
The following images show the Displacement node graph and its Inspector:
Set up the geometry modifier
Add a Geometry Modifier node to offset the vertex positions by the output of the Displacement node graph:
Add a Position node.
Connect the output of the
Positionnode to thePositioninput of the Displacement node graph.Add a
Geometry Modifiernode.Connect the
Model Position Offsetoutput of the Displacement node graph to theModel Position Offsetinput of aGeometry Modifiernode.Connect the
Outoutput of theGeometry Modifiernode to theCustom Geometry Modifierinput of theOutputsnode.
The main shader body is as follows:
[Image]
In this example, the Space of the Position node is set to object so that the displacement effect remains consistent regardless of the model’s position, orientation, or scale in world space, but you can use world instead if you want your displacement effect to depend on these factors.
Displace the vertices
One way to displace the vertices in a mesh is by utilizing output of a Noise 3D node:
Open the Displacement node graph by double-clicking it or selecting it in the Navigator.
Add a
Noise 3Dnode.Connect the output of the
Positionnode to thePositioninput of theNoise 3Dnode.Connect the
Outoutput of theNoise 3Dnode to theModel Position Offsetparameter of Outputs.
The following image shows the interior of the Displacement node graph:
[Image]
You can see the result of the shader in the Shader Graph Preview window, as shown below:
[Image]
In the example shown here, the Noise 3D node generates vertex offsets with Perlin noise, which distorts the shape of the mesh in a smooth yet random manner. To distort the shape of the surface differently, you can experiment with other noise functions, such as Fractal Noise 3D or Worley Noise 3D, or you can displace the vertices with your own custom logic.
Control the amplitude of displacement
Control the degree to which the shader offsets the vertices by adjusting the Amplitude parameter of the Noise 3D node:
Add a new input to the Displacement node graph of type
Floatand name it “Amplitude”.Add a Convert node and set its type to
Convert (float vector3f).Connect the output of the
Amplitudenode to the input of theConvertnode.Connect the output of the
Convertnode to theAmplitudeinput of theNoise 3Dnode.
The following image shows the interior of the Displacement node graph:
[Image]
You can increase the value of the Amplitude node to increase the amount the shader displaces the vertices by, as shown in the three examples below:
Control the scale of displacement
Control the scale at which the shader offsets the vertices by multiplying the position by a constant factor before sampling the Noise 3D node:
Add a new input to the Displacement node graph of type
Floatand name it “Scale”.Multiply the output of the
Positionnode by the output of theScalenode with a Multiply node.Connect the output of the
Multiplynode to thePositioninput of theNoise 3Dnode.
The following image shows the interior of the Displacement node graph:
[Image]
You can increase the value of the Scale node to increase the scale at which the shader displaces the vertices, as shown in the three examples below:
Displace the vertices over time
Animate the vertices by moving the position over time, following these steps:
Add a Time node.
Add the output of the
Multiplynode, multiplying thePositionby theScaleto theTimewith an Add node.Connect the output of the
Addnode to thePositioninput of theNoise 3Dnode.
The following image shows the interior of the Displacement node graph:
[Image]
The vertices of the mesh move over time, as shown below:
Control the rate of displacement
Control the rate at which the shader displaces the vertices over time by multiplying the time by a constant factor:
Add a new input of type
Floatand name it “Rate”.Multiply the output of the
Timenode by the output of theRatenode with aMultiplynode.Connect the output of the
Multiplynode to the bottom input of theAddnode.
The following image shows the interior of the Displacement node graph:
[Image]
You can adjust the Rate value to control the speed of the vertex displacement animation, as shown in the three examples below:
Create uniform inputs
Back in the main graph of your shader, create uniform inputs for each of the input properties of the Displacement node — Amplitude, Scale, and Rate — so that you can adjust these properties at the material level:
Creating uniform inputs also allows you to adjust the shader properties in code with the setParameter(name:value:) method, for example.
Correct the normal directions
When displacing the vertices of a mesh, you may notice that the way the mesh reacts to lighting no longer appears correct. This is typically the result of displacing the vertex positions without also modifying the vertex normals to match. For an obvious example, apply the material to the plane mesh in the preview window and observe how flat it looks despite its vertices moving:
See Correcting normals after vertex displacement with Shader Graph for information on how you can approximate and correct the normal directions, as shown in the following video: