Water Material fix

Hey everyone,

I hope you’re all doing well! I’m currently working on a game project using Babylon.js, and I’ve run into a bit of a snag with the WaterMaterial. I’ve attached some images to help illustrate the issue, and I’m hoping that someone here can lend me a hand in debugging this problem.

Firstly, let me explain the problem I’m encountering. I’ve been trying to implement the WaterMaterial in my game to create realistic water effects. However, when I apply the material to my water mesh, the result is not what I expected. Instead of seeing a beautiful water surface, I’m getting some weird artifacts and glitches. It’s definitely not the stunning water effect I was hoping for.

I’ve included some screenshots below to show you exactly what I mean:



As you can see, the water surface appears distorted, with strange patterns and artifacts scattered across it. I’ve tried adjusting various parameters such as the bump texture, wave height, and reflection properties, but I haven’t been able to resolve the issue.

Now, I’m reaching out to the Babylon.js community to seek guidance and advice on how to tackle this problem. If anyone has encountered similar issues with the WaterMaterial or has expertise in debugging such rendering problems, I would greatly appreciate your input.

Here are some additional details about my setup:

  • Babylon.js version: 6.4.0
  • WaterMaterial parameters used:

prepareEnvironment() {
// Skybox
let skybox = MeshBuilder.CreateBox(‘skybox’, {
size: 1024,
}, this.scene);
var skyboxMaterial = new StandardMaterial(‘skyBox’, this.scene);

  skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("../Resources/textures/skybox", this.scene);
  skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
  skyboxMaterial.backFaceCulling = false;
  //skyboxMaterial.useSunPosition = true;
  //skyboxMaterial.sunPosition = new Vector3(0, 100, 0);
  skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
  skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
  skybox.material = skyboxMaterial;


    // Use your existing code to generate the hexagonal grid here...
  // Ground
  let radius = 7.5;
const cylinder = MeshBuilder.CreateCylinder("cylinder", {tessellation: 6, height:0.01, diameter: 2 * radius}, this.scene);
//const block_mat = new StandardMaterial("block_mat", this.scene);
//block_mat.diffuseColor = Color3.Blue();
 // const waterMesh = new BABYLON.Mesh("waterMesh", this.scene);
const water = new WaterMaterial("water", this.scene);
water.bumpTexture = new BABYLON.Texture("../Resources/textures/waterbump.png", this.scene); // Set the bump texture
   //Water properties
   water.backFaceCulling = true;
water.windForce = 10;
water.waveHeight = 0.1;
water.windDirection = new BABYLON.Vector2(1, 1);
water.waterColor = new BABYLON.Color3(0.1, 0, 1);
water.colorBlendFactor = 0.3;
water.bumpHeight = 0.03;
water.waveLength = 0.3;

//Add skybox and ground to the reflection and refraction
water.addToRenderList(skybox);
//water.addToRenderList(cylinder);

cylinder.material = water;
cylinder.setEnabled(false);

radius += 0.5; //add a small gap
const bigHexRadius = 12;
const height = Math.sqrt(3) * 0.5 * radius;
let nbInCol = 2 * bigHexRadius + 1;
const deltaCol = 1.5 * radius;
let rowStartAt = -2 * bigHexRadius * height;
let currentRow = rowStartAt;
let colStartAt = 0;
let hexCount = 0;
//center row
for(let i = 0; i < nbInCol; i++) {
    const instance = cylinder.createInstance("ins_cy" + (hexCount++))
    instance.position = new BABYLON.Vector3(colStartAt, 0, currentRow);

  // Create a HexTile for each hexagon and store it in the hexTiles array
  const hexTile = new HexTile(cylinder, instance.position, radius);
  this.hexTiles.push(hexTile);

    currentRow += 2 * height;
}
colStartAt += deltaCol;
rowStartAt += height;
currentRow = rowStartAt;
nbInCol--;
while (nbInCol > bigHexRadius) {
    for(let i = 0; i < nbInCol; i++) {
        const instanceR = cylinder.createInstance("ins_cy" + (hexCount++))
        instanceR.position = new BABYLON.Vector3(colStartAt, 0, currentRow);
        const instanceL = cylinder.createInstance("ins_cy" + (hexCount++))
        instanceL.position = new BABYLON.Vector3(-colStartAt, 0, currentRow);
        currentRow += 2 * height;
    }
    colStartAt += deltaCol;
    rowStartAt += height;
    currentRow = rowStartAt;
    nbInCol--;
}
}

I’ve already gone through the official Babylon.js documentation and searched the forum for similar issues, but I couldn’t find a solution that worked for my specific case.

If you have any suggestions on what might be causing this problem or how I can go about debugging it, please share your insights. Any tips or tricks would be immensely helpful.

Thank you in advance for your time and assistance. I’m eagerly looking forward to your responses and suggestions.

Best regards,
Deny Heam

Hello! It would be helpful to have a Playground with a reproduction of your problem, as it will let examine the issue further :slight_smile: in the meantime, tagging @Evgeni_Popov to take a look.

Hi, I have set up a playground scene, which reproduce the error: https://playground.babylonjs.com/#QANVC6#3650

Without knowing the water material,
It looks like the reflection does not account for the position of each instance :thinking:

I don’t know if this is intended (performance)

Maybe you can try putting your tiles into a Solid Particle System (SPS), that will turn them into single mesh

Cylinder Mesh | Babylon.js Playground (babylonjs.com)
Is this what you want? :flushed:
The artifact problem with the first image seems to be related to the camera view

We ll see if @Evgeni_Popov can confirm but the watermaterial does not seem instances ready Which I can understand as nobody probably ever created instances with it ?

Yes, the water material is not instance friendly because it is using the local vertex coordinates for some of the calculation and not the world coordinates.

This PR will add better support for instances (adding a useWorldCoordinatesForWaveDeformation property):

When this PR is merged, this PG will work:

5 Likes