We can give movement to any object using shaders, how? Just moving their vertex position or their UV map coordinates. In this example, we're going to bring life to a seaweed asset using the sine function.

  • For this test, we're going to use URP (Universal Render Pipeline), also known as LightWeight Render Pipeline..
  • We're going to use Shader Graph, eventually, I will write how to get this using code.

Shader moving the vertices of the mesh.

We're going to use this site as a guide in order to see our functions:

Let's write the next line to see the sine function working:

Now we can see the sine graphic that will give movement to our seaweed, however, in order to have control over the appearance of our wave, we need to control the behavior of this wave, we're going to add a h value, this will allow us to move the whole graphic.:

If we change the h value, we could see how our graphic will move; Inside the shader, this will be useful to give movement to our seaweed. Now, we need to control the frequency of our function, we're going to add a b variable, this will divide the result of 'x - h' and this is the result::
sin ( x - h / b) 

Now, modifying the b value, we can change the frequency of our sine function, you will see this in the shader as the deformations amount applied in our seaweed. The more linear, our seaweed will be flatter.:

Finally, we're going to define this function as 'y' and we're going to multiply this by an 'a' variable, this one will modify the amplitude of our wave, our function is now finished:

y = a sin (x - h / b) 

With this finished, we already have the recipe that we're going to apply to our shader, now we can control the amplitude (a), speed (h) and frequency (b), all these variables are going to distort the vertices and create movement in the mesh..

Remember: We're going to transfer  information from our sine wave to the vertex position of our foliage geometry, so, the vertices will be updated all the time in relation with the wave information, you can see this clearer in the next sample:

We can see how the vertices are moving taken the sine function silhouette, the texture is just adjusting to the mesh



Now we just have to repeat the process inside Shader Graph

We already have our function:

y = a sin(x - h / b) 

1-The 'Split' node separate every vector in our  UV Node, and these are represented as 'R,G,B,A', remember that these values also mean 'X,Y,Z,W''.

We're going to obtain our 'x' value from the UV coordinate of our mesh, remember:
U = X
V = Y 

Having this, we got the 'x' value of our function, now we need to subtract the 'h' value, so, we have to create a float value (or vector 1) with value 1, and we're going to subtract this from our 'x' value..

2-We already have (x - h), now we need to divide them by 'b', we just have to add a divide  node and a float value (or vector 1) and call it 'b', this will have a value of 1 too.. 

3-Now we have (x - h / b), the next  step is obtaining the sine function from this result, let's add a 'sine' node to the result of our previous operation an we will have:

y = sin (x - h / b) 

4-To finish, we just need to multiply everything by 'a', just add a multiply node and plug a float value (or vector 1) called 'a' with a value of 1. 

Done, our graph now is complete and working with our function:

y = a sin (x - h / b) 


Now, we're going to add a 'Position' node with 'Space Object' configuration, this will give us access to the vertex position of the mesh to modify them. Add a 'Split' node to separate the Y (G) vector from the 'position' node, cause this is the one we're going to modify with our sine function.

Add an 'Add' node, plug to the 'Add' node the Y vector (or G) from your split node, and after that, plug the result of your sine function in the 'Add' node too.

Add a 'Combine' node to combine the result of the vertex position of our object to the sine wave movement. In this case, only the Y vector (or G) will be affected by the sine wave function. So, we're going to combine the default position of our mesh to the altered position in Y of our sine function, and then we plug that result in the 'Position' output of our shader. 

Of course, don't forget to plug a texture to the material to see if it's working nice..

If you create a material from this shader and you apply it to a subdivided plane, you will notice that when you move the H value, the vertices of the mesh start to move..
If you modify the B  value, you will change the frequency, and of course, you will modify the amplitude if you move the A value.  This is our sine function modifying our geometry

However, there's a detail here, our seaweed doesn't move by itself yet, to fix this, we just need to add a 'Time' node multiplying the 'h' value

Now, our geometry is moving by itself and we just have to control the speed in the 'h' value.


Just one last detail, right now the whole mesh is being distorted, we have to keep the "root" static to achieve a better result.. 

To do this, we're going to use a 'Lerp' node, in order to create a gradient effect between the original vertex position of the object and our sine function.

Let's create a new 'position' node in 'Space object' and plug it to the 'A' section of our 'Lerp' node, this will keep the vertices in their original position (I mean... without movement), in the 'B' section of the lerp, we're going to plug the result of our Sine function that we already had.

Finally, we're going to obtain again the Y (G) value from a new 'UV' node and we plug it to the 'T' section of the lerp, this is going to work as a gradient to indicate to our shader which  part will be affected by our sine function and what part not.

The 'Y' value of the 'UV' return this gradient from black to white, in this case:

BLACK = 0 
WHITE = 1 
GREY = Intermediate values

So, the vertices nearly to the white color (value 1) will be more affected by our sine function plugged in the 'B' section of our 'Lerp', and the vertices near to the black color (value 0) will be less affected cause the 'Position' node is plugged to the 'A' section, and this make that the vertices keeps their original position. 


This is our final product, remember that this not only useful for a seaweed asset, you can apply this to grass, trees, water, flags, and lots of objects that can use the sine function to get alive. .


  • This shader is moving the vertices of a 3D object, so, the more subdivisions you have, the smoother it will look.
  • At the same time, be careful with the subdivisions amount, if you have lots of vertices this could impact on your game performance, have in mind the destination platform and some other optimization techniques..
  • You can achieve a similar product moving only the texture and not the vertices, I'm going to talk about this in another article. 


If you are interested to directly download the shaders and a scene sample you can do it here: :

You are free to use them for any project you want when you got it

For any kind of doubt, just let me know in the comments or send me a direct message here. If you want to make a donation for the site you can do it in my Ko-fi account, this will help me a lot to continue creating content for you!