In Unity 2018.2 we added the “Vertex Position” input to Shader Graph, allowing you to adjust and animate your meshes. In this blog post, I’ll demonstrate how you can create your own vertex animation shaders, and provide some common examples such as a wind and a water shader.
This scene does not use any textures or animation assets; everything you see is colored and animated using Shader Graph.
Shaders are an incredibly powerful aspect of the rendering pipeline, allowing a great degree of control over how our scene assets are displayed. Using a series of inputs and operations, we can create shaders that change the various rendering properties of our assets, such as their surface color and texture, and even the vertex positions of the mesh. You can also combine all of these into complex, rich animations. This blog post will demonstrate how you can get started with vertex animations, introduce the concept of using masks and properties, and finish by explaining how we made the shaders for the Desert Island Scene.
Download the Desert Island Scene sample project to start experimenting and interacting with the shaders yourself! This project contains everything you need to get started with Shader Graph. Ensure you launch the project using Unity version 2018.2 or above.
Every shader in the Desert Island Scene was built with customization in mind, so feel free to start playing around with the shader values in the Inspector! Each object also has a preset file that will return the values to default.
This work is licensed under the Creative Commons Attribution 4.0 International License.
In order to use Shader Graph, your Project must meet the following requirements:
To install Shader Graph, either create or update a Project to version 2018.2 or above, navigate to Window > Package Manager > All, find Shader Graph in the list and click install.
If your materials are not animating in the Scene view, make sure you have Animated Materials checked:
— John O'Reilly ? (@John_O_Really) July 17, 2018
Before we can start using fancy maths to move things, we need to understand what it is that we’re moving.
A Mesh in the scene has four types of spaces:
You can select which Space you wish to affect in the dropdown of the Position node.
By using the Split node we can select which axis we want to affect.
The Split node outputs to four channels, the first three correspond to our Transform axis (R=X, G=Y, B=Z). In the example above, I’ve split out the y-axis of the object and added 1, moving our object up by 1 on its own axis.
Sometimes you may wish to move the object in world space. To do this, select World from the Position node, then convert the output back to object space using the Transform node.
Now that we’ve established how to move a Mesh, it’s often useful to know how we can restrict the effect.
By using nodes such as Lerp, we can blend between two values. The T Input is the control value for the Lerp. When our T input is 0 (visualized as black), the A channel is used. When our input is 1 (visualized as white), the B channel is used. In the example below, the slider is used to blend between the two inputs. Any of the following examples can be used in place of the slider.
With a black and white texture, we can use detailed shapes to push our Mesh. In the above example, you can see how white represents the maximum height of our range, while black represents no effect on the Mesh position. This is because black has the numerical value of 0, and so adding 0 to the Mesh position doesn’t move it.
To use a texture with vertex position, you must use the Sample Texture 2D LOD node instead of the typical Sample Texture 2D node. Textures are particularly useful if you need a mask with a unique shape or a certain degree of falloff.
While similar to a Texture mask, with a UV mask you can choose which part of the mesh you wish you affect based on the UV Unwrap. In the above screenshot, I’m using the u-axis of the UV to create a gradient from left to right. To offset the gradient, use an Add node; to increase the strength, use a Multiply node; and to increase the falloff, use a Power node.
Each vertex stores a unit of Vector3 information that we refer to as Vertex Colour. Using the Poly Brush package, we can directly paint vertex colors inside the editor. Alternatively, you can use 3D modeling software (such as 3ds Max, Maya, Blender, 3D Coat or Modo) to assign vertex colors. It is worth noting that, by default, most 3D modeling software will export models with the maximum value for RGB assigned to each vertex.
In the above screenshot, the Vertex Colour node is split into the red (R) channel, then connected to the T channel of the Lerp node, acting as a mask. The A channel of the Lerp node is used when the input is 0, with the B channel being used when the input is 1. In practice, the above set up will only add 1 to the y-axis if the vertices have the red vertex color assigned.
By using the Normal Vector node, we can mask an input by the orientation of the Mesh faces. Again, the Split node allows us to select which axis we wish to affect (R=X, G=Y, B=Z). In the above screenshot, I mask using the y-axis, so that only the faces that face up are positive. It’s important to use a Clamp node to discard any values that are not between 0 and 1.
This series of nodes masks an input if the object’s position is above world position 0 on the y-axis.
When building Shaders, it can be difficult to get the correct input values for the desired effect. For this reason, and for later customization with Prefabs and presets, it’s important to use properties.
Properties allow us to modify the Shader’s values after the Shader has compiled. To create a property, click the + symbol in the Blackboard (pictured on the right). There are six types of properties:
The flag Shader pans an object space sine wave across the flag, using a UV mask to keep the left side still.
The wind Shader uses world space Gradient Noise panning along a single axis to gently push and pull the leaves and grass.
In this Shader, we’re using a sine wave that’s generated across the object’s axis to make the fish wobble. We then mask off the head of the fish, so that the head stays still.
Finally, we have the ocean Shader! This Shader offsets the top of the Mesh using three sine waves of different scales and angles. These sine waves are also used to generate the colours for the wave troughs and tips.
If you would like to know how to get started with Shader Graph, Andy Touch’s GDC talk is a great place to start. If you’re looking for other Shader Graph examples, Andy also has an Example Library available on GitHub.
For detailed documentation about Shader Graph, including descriptions of every node, go to the Shader Graph developer Wiki on GitHub. Get stuck in and join the conversation in our Graphics Experimental Previews forum! And finally, if you’re making something cool with Shader Graph, I’d love to see it! Feel free to reach out to me on Twitter @John_O_Really.