Water not reflecting correctly

I have a scene with a reflective sphere, and everything reflects correctly.

However, once I replaced the “water” on the floor to an actual Water object, the reflection (of only the Water object) seems rotated.

What am I doing incorrectly?

Code to create Water object:

  const waterGeometry = new THREE.CircleGeometry(50, 50);

  const water = new Water(waterGeometry, {
    textureWidth: 512,
    textureHeight: 512,
    waterNormals: new THREE.TextureLoader().load(
      "https://cdn.glitch.com/7da04fe9-3f35-4ff9-9dd5-1de3d6fcea32%2Fwaternormals.jpg?v=1605815093396",
      function(texture) {
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      }
    ),
    alpha: 0,
    sunDirection: new THREE.Vector3(),
    sunColor: 0xffffff,
    waterColor: 0x001e0f,
    distortionScale: 3.7,
    fog: scene.fog !== undefined
  });
  
  water.rotation.x = -Math.PI / 2;
  
  water.matrixAutoUpdate = false; //same result if true
  water.rotationAutoUpdate = false; //same result if true
  water.updateMatrix();

  scene.add(water);

Code to create sphere:

   function makeSphere(scene, pos) {
      var cubeRenderTarget = new THREE.WebGLCubeRenderTarget(128, {
      format: THREE.RGBFormat,
      generateMipmaps: true,
      minFilter: THREE.LinearMipmapLinearFilter,
    });

    var sphereCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
    scene.add(sphereCamera);

    var sphereMaterial = new THREE.MeshBasicMaterial({
      envMap: cubeRenderTarget.texture,
      combine: THREE.MultiplyOperation,
      reflectivity: 0.95
    });
    var sphere = new THREE.Mesh(
      new THREE.SphereGeometry(0.6, 32, 32),
      sphereMaterial
    );
    
    scene.add(sphere);

    sphere.position.copy(pos);
    sphereCamera.position.copy(sphere.position);
    sphere.userData = sphereCamera;
    
    return sphere;
  }
 makeSphere(scene, new THREE.Vector3(1, 2.5, 0));

Render code:

  var sphereCamera = sphere.userData;
  sphere.visible = false;
  sphereCamera.position.copy( sphere.position );
  sphereCamera.update(renderer, scene);
  sphere.visible = true;

Apologies if I have formatted my question poorly, this is my first time on the forum. Thank you!

Yeah, rotating the water shader can have a few glamorous implications - ex. if you move the camera horizontally, frustum will treat water as if it was still vertical and can start occluding parts of visible water plane. :face_with_hand_over_mouth:

But for this issue - try updating the reflections like in this example (source / live-reflections codepen using same technique.) Create a second cube camera and alternate between them to render a correct reflection - be sure to do it after the water is rendered horizontally.

Thanks for your response! I tried to alternate between the two cube cameras, and the reflections of objects now seem to be distorted as well. The sphere has a reflection of itself, and there is no reflection of the water at all.

I’m wondering if you could take a peek at this jsfiddle to see if I did something wrongly? The sphere/environment is draggable, and you can also generate more objects using the buttons at the bottom to check the reflections.

Thank you again!

(1) CubeCamera does a 360 screenshot of the scene from a certain position. To get reflections for each object, you’d need to render a cube map from each position (and it can get very expensive very fast.)

It’s unlikely you’ll get raytracing-quality reflections this way (for that there’s a Reflector object, but it works only for flat surfaces.)

You can try implementing reflection probe / capture similar to how UE4 generates reflections.

(2) That would still not resolve issue from your original post and water will still render vertically. If I remember correctly, to fix that in the shader you’d have to modify this normal to point upwards instead of sideways. I don’t remember if there’s an easy way to do that, though. :pensive:

1 Like