Creating A Water Mesh From Separate Meshes

Hello,
I just wanted to ask a question here before I try some other optimization ideas.
I am building a voxel engine and in order to have water like shader effects to work properly I built a system that would combine together all the water meshes together for all the chunks.

I was just wondering if anyone knew of a way to do this without having to actually make the mesh one big mesh? I seen someone connect water meshes together with bones but not sure if that is possible in Babylon.

This would just make it easier to work with the engine and enable it for server use.
In the engine the water mesh is put together in a separate thread to not cause lag.

I have ideas to still do it this way and still have it work on a server for multiple clients.
I just wanted to check here before I try my ideas.

Here is an example of a water mesh in the engine:
DVE ocean

Hi lucas-divinestar,

I’m not sure I fully understand the aim, but if you’re specifically trying to speed up the rendering of many copies of a thing then instances and thin instances may be able to help you. The latter in particular will abstract a lot of the “combining”-style logic away. Hope this helps, and best of luck!

Thank you for the reply!

I think maybe what I am talking about with just how 3d rendering works but I am not sure.

I am not exactly looking to speed up the rendering. I am trying to find a different way to put together a mesh that represents a body of water. Thin instances are good if I need a bunch of the exact same thing. But in this case that is not what I am doing.

So, let me explain it like this.
The water mesh has shader effects on it that make it look more or less like an actual fluid. In order for the mesh to appear as one body of water it’s vertices must be part of the same mesh.
In the picture you can see that the mesh itself is kind of bent and wavy.

My question is how can I apply the same water shader effect to meshes that are right next to each other and make it look like one big body of water?

I could combine the separate water meshes on the client side but that would honestly be harder than what I am currently doing.

Ah, now I understand! All you should have to do is use world coordinates in your material instead of UV coordinates, and that should solve it for you.

Seamless Terrain Shader | Babylon.js Playground (babylonjs.com)

Here’s an example of a fun (if slightly complicated) shader I created in NME being applied two meshes side-by side. However, the result looks like one seamless mesh because the shader is basing its calculations off world-space coordinates, not UV coordinates. You can even grab the meshes and drag them around in the XZ plane and watch the material update based on where it is. Hope this helps, and best of luck!

Oh wow! That is pretty sweet.
Thank you!

But I am a little confused.
How do I send the world cords? I think I already am but I am not sure.
If you can point me in the right direction I should be able to do it.

Here is how I create the material :

  const shaderMaterial = new BABYLON.ShaderMaterial("fluid", scene, "fluid", {
   attributes: [
    "position",
    "normal",
    "cuv3",
    "colors",
    "rgbLightColors",
    "sunLightColors",
   ],
   uniforms: [
    "world",
    "view",
    "viewProjection",
    "worldView",
    "worldViewProjection",
    "vFogInfos",
    "vFogColor",
    "sunLightLevel",
    "baseLevel",
    "projection",
    "arrayTex",
    "doSun",
    "doRGB",
    "doColor",
    "time",
    ...animData.uniforms,
   ],
   needAlphaBlending: true,
   needAlphaTesting: false,
  });

And here is the Vertex shader code that distorts the mesh:

vec3 p = position;
float height = fbm(p.xz * 0.08 + time);
p.y += height * 0.1 - .3;
vec4 worldPosition = world * vec4(p, 1.0);
gl_Position = viewProjection * worldPosition; 

I think I may have answered my question.
This is how to get the world pos:

vec4 posWorld = worldMatrix * gl_Vertex;

I got it from here:

Stack overflow Answer

Okay here is what I did to get it working:

vec4 posWorld = world * vec4(position, 1.0);
vec3 p = position;
float height = fbm(posWorld.xz * 0.08 + time);
p.y += height * 0.1 - .3;
vec4 worldPosition = world * vec4(p, 1.0);
gl_Position = viewProjection * worldPosition; 

And I just tested it and it totally works!
Thank you so much!

2 Likes