Creating an Interactive Vertex Effect using Shader Graph

We created an example interactive vertex displacement effect with Shader Graph and the Lightweight Render Pipeline to help you use these features to design effects. This post will walk you through our process. Get the demo project with the Shader Graph shader, example scene, and some example game assets from the 3D Game Kit, and follow along!

The sphere in the video example below has a shader-based displacement effect that activates when we hit the space bar. In your game, you would assign this to some relevant gameplay event. In this article, we will look at how to create this shader using the Shader Graph package, and integrate the spacebar keypress trigger. The goal is to help you understand how to design effects in Shader Graph, and interact with them from your other C# scripts. The demo project contains the shader, the script that controls the shader, a preconfigured Lightweight Scriptable Render Pipeline (LWRP) Asset, and an example scene for you to get started with. If you prefer to view this tutorial as a video instead of text you can find it on the Unity YouTube channel.

﻿

Installing Shader Graph and LWRP Packages

First, let’s look at how to set up Shader Graph and the Lightweight Render Pipeline. Open the Package Manager and select install on the Lightweight RP package. This will automatically install the correct version of Shader Graph.

Once we’ve installed the Lightweight RP, we need to create a new Pipeline asset in the Project. Select Create->Rendering->Lightweight Render Pipeline Asset.

We can then activate this pipeline asset by going to Edit->Project Settings->Graphics, and dragging the LightweightRenderPipelineAsset into the Scriptable Render Pipeline Settings field. If you are following along with the downloaded assets, this step has already been completed for you.

Now that the Lightweight Render Pipeline is installed, we can look at creating a new Shader Graph. Let’s create a new graph in our project by selecting Create->Shader->PBR Graph. The PBR Graph allows us to create a new shader that takes inputs from Unity’s Physically Based Rendering system,so that our shader can use features such as shadows and reflections. Once we have created this shader, we add it to a new Material and attach the Material to a Sphere in our example scene by dragging and dropping the material onto the sphere.

Vertex Displacement with Shader Graph

To achieve the effect, we will displace the vertices in our mesh along its normals by changing the output Position in the PBR Master output node. We will displace by using an Add node on the base Object Position of each vertex. By adding the Normal Vector to the base Object Position, we can see all the vertices become extruded, making the sphere appear bigger. To vary this displacement, we will multiply this normal vector displacement semi-randomly by using a Simple Noise node.

When we click Save Asset, we can see in the Scene View that the sphere is now displaced based on Simple Noise.

Unfortunately, there are seams in the displacement because the Simple Noise is being sampled based on UV space. To fix the seams by using Object Space for the Simple Noise instead of UV Space, we can simply add a Position node set to Object.

To create the pulsation effect, we will scroll this Position output by adding it to a Time node, before sending it to the Simple Noise node. We can also use a Multiply with the Time node to vary the speed of the scroll.

Controlling Shader Graph Properties in C#

To control our displacement, we expose a new Shader Property in our Shader Graph. Shader Properties allow us to provide inputs to our shader via values entered in the Inspector, or via our own C# scripts as in this case. We will create a new Vector1 property named Amount and changed the Reference to _Amount. The reference field is the string name by which we will access and change the displacement via script. If we do not change this, it will use an auto-generated value. If the string does not match exactly, we will not be able to address our property via script so double check that both match, including capitalization.

We use this Amount shader property in a Multiply node with the Simple Noise before it gets multiplied with the normal vector. This allows us to scale the noise before it’s applied to the vertex positions. Now, the Amount variable controls how much we displace each vertex in the mesh.

To control this Amount variable, we have created a C# script called DisplacementControl and attached it to the DisplacementSphere GameObject. This script controls the _Amount variable by interacting with the property we created in our material which is assigned to the MeshRenderer component. We store a reference to the MeshRenderer component in the variable meshRender, and declare a new float variable displacementAmount.

We use a simple lerp in the Update function to interpolate the displacementAmount variable to the value of 0. We then set the shader variable _Amount to the value stored in displacementAmount variable. This will update the Shader Graph’s _Amount variable, smoothing it over time to 0.

We are using Unity’s default “Jump” Input Axis (which is assigned to the space bar by default) to set the value of displacementAmount to 1 when pressed.

Now, when we enter Play Mode in the scene, we can see that by pressing the spacebar, displacementAmount gets set to the value of 1, and then slowly interpolates back to 0.

Creating the Voronoi Glow Effect with Shader Graph

To create the adjustable glow effect, we will output to the Emission in the PBR Master node. We use a Voronoi Noise node and Multiply it to a Color node. This will create a little modulation in the glow effect with some dark spots. Then, we use a Lerp node with another Color node as the base color, and use the Amount variable in the T input. This will allow us to blend between a base Color node and the Voronoi Noise color node using the Amount variable.

Then, we will scroll the glow by using a similar setup as before. We use a Position node set to Object and add it to a Time node, and connect the output into the UV slot of our Voronoi Noise node.

We can also add a second layer of glow for additional variation by using a Simple Noise node scrolled by an additional layer of Time, and multiplying the two Noise outputs together. This gives us a second layer of noise, which adds visual interest.

Because this glow effect is adjusted by the Amount variable in the Lerp node, we can see in Play Mode that when we press the spacebar, the sphere will activate both effects, vertex displacement and glow, and then slowly go back to its normal state.

To add a little extra touch, we have also linked up a simple particle system in the DisplacementControl script.

And here is our finished product:

If you’d like to experiment with these features yourself, we have provided the complete project, with all assets, meshes, shader, and example scene for you to download here. We look forward to seeing what cool stuff you create with it!

To learn more about Unity, check out some of our available courses on our Learn website. To check out some other cool effects, feel free to also browse the Unity Asset Store.

Really appreciate this kind of post – Thanks!
Had a brief look at the demo project and then set up my own solely via your text tutorial without needing to refer back to the demo. So the info vs. length balance is about right.

The diagram appears to show the Amount being multiplied with the product of Simple and Normal rather than directly with Simple and preceding Normal in the chain as noted in the text. However, I don’t see any precedent issues with two consecutive mults, so either way seems equivalent – but I stand to be corrected.

For LWRP there is no “refraction output”. Refraction should be done manually and added to the desired material channels (we wont be adding these restrictive abstractions). HD Lit has refraction outputs as offsets. For us refraction is like distortion but driven by index of refraction and normal so we don’t expect the user to replace that, they can specify the IOR or thickness of the object. For distortion they can do what they want. Short version, this is very pipeline dependent and we think its implemented correctly for each already.

In the event that you snap to surface while in turn mode the item will snap the rotate purpose of the article to the surface. On the off chance that in focus mode the article will snap the closest vertices of the chose item to the surface.