Mesh Deformation Seas Project - Dynamic Waves, Foam FX, Sounds, and more


  • Dynamic Waves → Collide and reflect off the boundary as well as off eachother
  • Dynamic Foam → Can swish around with the waves
  • Waves push you around when strong enough
  • Wave Sounds which alter depending on strength of nearby waves
  • Underwater view

Inspired by this also great project

Any suggestions, ideas and feedback?


Try here at:

Old version without skinning:


I think this might be one of the greatest things I’ve ever saw on Roblox. Great work!


You can create a texture scrolling effect on the surface of the water plane by moving the entire mesh. If you want to scroll the texture at a speed of 2 studs per second in the X direction, you would move the entire mesh at a velocity of 2,0,0. However, if you were to move the mesh at a velocity, then eventually the plane would travel away from the rest of the level. To keep the plane in the same place roughly, you would reset the plane’s position after a certain distance has been traveled, so that way the plane can stay in the same area indefinitely. The distance at which you reset the position is some multiple of the amount of studs it takes for the texture to repeat; i.e if the texture repeats every 5 studs you could reset the position after the mesh moved 5 or 10 studs. This way, the texture remains seamless during the jump.

Now, the texture would be scrolled correctly, but the waves would look strange, especially when the plane gets teleported back to its starting position. To fix that, we have to distinguish between the points on the plane that get moved up and down, and the points on the simulation grid. The simulation grid would be completely stationary, but the points on the plane are always moving at a velocity of 2,0,0. So, this means our bones on the skinned mesh and the points calculated in the simulation no longer match up. To fix this, for every bone, you would have to calculate a new wave height by interpolating the nearby simulation grid values. If a bone is in between two simulation points, the wave height at the bone would be 0.5 * pointA + 0.5 * pointB.

If your wave algorithm is expressed as a function of any pair of X and Z coordinates which returns a wave height at said point, then the interpolation stuff I mentioned is totally unnecessary. You would just take the updated global position of each bone and plug it into your wave simulation function.


If your wave algorithm is expressed as a function of any pair of X and Z coordinates which returns a wave height at said point, then the interpolation stuff I mentioned is totally unnecessary. You would just take the updated global position of each bone and plug it into your wave simulation function.

I tried this and it had a nice effect but it was difficult dealing with the whole “reset position after moving too far”. One work-around was to put vertices on the other side that would stay static and stretch to cover the “gap” but this looked visually bad. Overall I figured it wasn’t worth having. It would be nice if PBR had more properties such as an Offset Studs property and a StudsPerTile property similar to what normal textures have.

As a side note,
Does anyone know why Roblox renders less particles from ParticleEmitters at max graphics?

For example, at graphics 5, I can see the foam all over my sea whereas at max graphics, I see way fewer (only nearby particles) which is counter-intuitive. Is there a reason why or way to avoid this? (I’ve tried disabling rain but this behavior still occurs.)

1 Like

You can bruteforce a particle emitter by using :Emit(), which will completely bypass the graphics level-tied particle throttling. There’s one specific emitter in my game that I need to have a consistent output from for gameplay reasons, so I have a little script that runs emit every frame. Works beautifully.


Thanks so much. That’s exactly what I needed

1 Like

this is so goodddddddddddddddddddd

1 Like

This is a shot in the dark, but I’d guess the particles you see at max graphics are denser than those at 5, so increasing the graphics is rendering a lot within a small space. Just based on how it’s suppose to limit particles.

Looks great though

1 Like

Hey, I was wondering how you set up the bones to make this possible? Is it a single mesh or multiple meshes?

I know you’re using Gerstner/trochoidal waves, I just wanted to know how you did the wave mesh itself.

1 Like

This is actually not using Gerstner waves. Tyridge’s one is using those. Mine uses a physics solver for something else. It’s slightly less aesthetic but more unpredictable and can do physics stuff with it. Also ye, single mesh

This is open source right? I can’t rlly check Rn cuz all I got is my phone due to United States Marine Corps training… plus do you have any recommendations on how to make it so that you can make this infinite? I’m thinking chunking right now or maybe using gerstner waves through a possible blender animation on a mesh for my naval game and then adding scripts for my ships but that’s a different aspect…

This is not open-source, he’s asking for constructive feedback, ideas or suggestions.

Oh thanks for that appreciate the input mate.

Just curious but how is it possible to alter the skinned mesh so that it has collisions?

Would be cool if it was open source but ofc the creator smh

I would enjoy an open-source demo as much as you, but please remember that it’s his project and his to do with as he pleases.

1 Like

This has got to be the best Sea simulation I’ve seen, with the foam and all.

I’m currently trying to replicate this on my own, but I can’t solve a few problems, and I would be ever so grateful if you could guide me in the right direction.

First of all, I cant figure out how to get the bones next to a select bone, so if one bone goes down, how do you get the bones next to it to interact.

Next, I can’t figure out how you got the waves to interact with the player… From my testing, I’ve concluded that using normals on a deformed mesh doesn’t work.
I guess you could either create triangles between every bone, but I just feel like there might be a more efficient way.

Once again, thanks for sharing your creation.

Open source this! ;c :slight_smile:

1 Like

I really wish we could use this