Rasengan, using shader graph in Unity

Hello everyone, welcome back.

I have just received a good news that Minato Namikaze will going to have a one shot spin off manga. Now I am certainly excited for that, and I thought let's recreate one of his iconic jutsu in Unity and no it's not Flying Raijin its too quick. So today, we will recreate the one that he originally created, the Rasengan, using shader graph.



For this I am using Unity version 2022.2 but it will work on any Unity LTS versions. I have a project in URP and for this we need a post processing volume with modules Bloom and Tone mapping with the mode Aces.

Without further ado, let's get shading.

Effect break down

Now looking at various references, Rasengan can be broken down in 3 parts, the outer edge, the core and swirling lines. 



We will start with edge and core because they are super easy.

Let's create a shader graph. Right click > create > shader graph > URP > Lit shader graph. Call it RasenganShaderGraph.

Create a material, right click > create > Material, call it Rasengan, create a new sphere in scene and apply our new material to our sphere.

Let's open the shader graph. Let's quickly do some setup, In the Graph inspector, Check Allow material Override, so we can modify these settings in the inspector.

Set Surface type to transparent. And I don't want our mesh to receive any shadows so uncheck Receive shadows. That's it for the setup.

Edge and Core

We will start with the edge and for that let's create a Fresnel effect node. It will give us this nice effect and this power is similar to the Power node, performs the power operation and it will darken the values which are less then 1 as we increase the power.

We want to control this power from inspector so let's create a float property, call it EdgePower, give default value of something like 5, drag it in and feed it into the power.

Let's also create a Color property for our edge color, call it EdgeColor, set the mode HDR, give default blueish color, drag that in and we will multiply with our fresnel. There we go.

Now for the core part, let's create another Fresnel effect node, keep it's power at 1. Now for core we want to invert this so we will take it's output and feed it into One minus node.

One minus node as the name suggest will subtract 1 from whatever value we feed in, for this instance it will invert the colors.

We cannot control the strength of our core using this power value, we are very limited here, so we will create a seperate Power node, feed our One minus output and then we can control the core using this second input.

We will control that from the inspector, so let's create another float property, call it CorePower, give a default value of something like 50. drag it in and feed it into Power node.

Now let's create another property, Color to control the color of our core, call it CoreColor, set the mode HDR, give a default color, drag it in and we will multiply it with our core.

Now we have core and edge, let's add them together with Add node. Then we will take its output and feed it into Emission block of our Fragment context.

Let's also create another Color property, call it BaseColor, set the mode HDR, give a default color, drag that in, assign it to our base color. Let's also create a Split node and take its alpha and feed it into Alpha block. So that we can control the opacity as well. Your shader graph will look something like this.







Swirling lines

Let's deal with swirling lines part, for that we will use Voronoi node, we will control the cell density from the inspector so let's create a float property, call it CellDensity, give a default of something like 3, drag it in and assign it into cell density.

Let's create a Power node, feed the Voronoi into it, and let's increase the power to something like 5.45.

To make them look like they are swirling, we have a handy little node called Twirl node. This Strength determines how powerful the twirl effect will be, we will control this from the inspector so let's create another float property, call it TwirlStrength, give default of something like 5, drag it in and assign it to this strength.

Take our Twirl node's output and feed it into Voronoi node's UVs. And we have this amazing effect.



Now we want to rotate that so let's create Rotate node, take its output and feed it into this UVs, now we can rotate this by increasing the rotation value.

To do that, let's create a Time node, We also want to control the speed of our rotation so let's create a float property, call it RotationSpeed, give a default value of 2. Drag it in. We will take the Time output and multiply it with our speed. and feed it into this rotation.



Now this swirling lines represent chakra rotation, if you remember from the episode when Naruto was learning it, to master the Rasengan, user need to rotate the chakra from multiple direction.

So to replicate it in our shader, let's just duplicate the nodes Rotate, Twirl, Voronoi and Power. We will change new Voronoi nodes' angle offset so it won't look identical to the one above.

Then we will twirl it in opposite direction, so take the TwirlStrength and feed it into the Negate node, Negate node will multiply whatever value we pass in with -1. So 5 * -1 = -5. Then take the output and feed it into the strength.

We will also do the same for the rotation.



Let's add these 2 Power nodes together, let's multiply it with our BaseColor. Then add that to our edge and core. Then finally feed that into our Emission.



Issues with UVs

Now if we save and see how it looks into scene view, it will looks weird. This is because it is trying to apply the texture based on the default UVs of our sphere.

Solution

We can fix it by finding a direction from our game object to camera and with that direction, find a perpendicular XY plane and apply the texture. We can do it in 2 ways.

First method

Via script, we will find the direction vector from our object to camera, normalize it and then rotate our sphere in a way so that its Z axis points towards the camera.

Let's create a script, call it RotateZTowardsCamera, attach it on our sphere.

using UnityEngine;

public class RotateZTowardsCamera : MonoBehaviour{
private Transform cameraTransform;

private void Awake() {
cameraTransform = Camera.main.transform;
}

private void Update() {
Vector3 directionVector =
cameraTransform.position - transform.position;
directionVector.Normalize();
transform.forward = directionVector;
}
}

Then In our shader graph we will apply the texture relative to our object's local XY plane.

create Normal vector node, keep its space to Object. So as we rotate the sphere the texture will rotate relative to the sphere. Take its output and feed it into Tiling and Offset node. Put 0.5 in offset XY and feed its output to both Rotate nodes' UVs.



That should do the trick. Now a quick note, if you are on HDRP, this is the only applicable method next one won't work in HDRP.

Second method

The 2nd method is almost same except that we modify our shader so that instead of rotating our object we apply our texture perpendicular to the direction vector.

Let's go in our shader graph, let's find the direction, just as we did in our script, so lets create a Camera node. Now this node is not supported in HDRP hence we cannot use this method in HDRP.

We will take our camera position and subtract it with our object's position so let's create Object node, take the position and feed it into subtract node, now let's normalize it.

So now we have normalized direction which points towards the camera just like this. But we cannot use it alone, we also need X and Y axes relative to our direction.

To find them, we will take our direction vector and we will do a cross with our world's up axis so that we will get the X axis relative to our direction, then we will take our newly found X and do a cross with our direction vector so we will get the Y axis relative to our direction. Then we can apply our texture perpendicular to our direction using XY axes.

In shader graph, let me call normalize direction, Z and take its output and feed it into Cross product node, and world's up will be 0, 1, 0. Now we have our X axis. Then we will take this newly found X axis and feed it into another Cross product. Then we will take the Z axis and feed it there. Now every thing we are Now we have our Y axis.



Okay, we have all 3 axes but we need a way to combine them, so we need to create a matrix. Matrices are a broad topic themselves but just a TLDR matrices are used to perform operation on vectors such as Translation, rotation, scale, shear etc.

Now let's create a Matrix contruction node, then we will take our X, Y and Z in respectively. Now we have a rotation matrix, and since we are not dealing with translation we can use 3x3 Matrix and feed it into Multiply, Then we will use this Normal vector node, set the space to World and feed it into multiply.

Finally we will feed Multiply node's output and feed it into Tiling and Offset node's UVs.



Now I know this is complicated but what we have done here, is in the multiply we have rotated all our vertices of sphere in a way similar as if the local Z axis points towards the camera, and recalculated the normals based on the rotation matrix.

Now we won't need the script so we can remove it from the Sphere and our shader graph will look something like this at the end.



Trouble following along? Check out this video!



Thank you so much for reading!

Comments