Objects behind Refractor is not updated properly when moving camera, any idea for solution?

Hi, I have a water-pool with a water surface, I’m using the Refractor from ‘examples/jsm…’ as water surface. It works fine if I don’t move the camera, small movements of the camera is also okay.

But when I’m moving the camera around the pool the walls and floor gets really distorted and is not updated properly, here is an image where I have rotated to the other side:

Here is a small GIF to illustrate:

Water distortion

I have already tried to set needsUpdate = true on the material on the objects behind the surface without success.

Here is the code used to create the surface, I’m using Three.js version: 0.118.3:

                    positions = new Float32Array([
                        0, depth, 0,
                        w, depth, 0,
                        w, depth, -l,
                        0, depth, -l
                    ]);
                    normals = new Float32Array([
                        0, 1, 0,
                        0, 1, 0,
                        0, 1, 0,
                        0, 1, 0
                    ]);
                    uvs = new Float32Array([
                        0, 0,
                        1, 0,
                        1, 1,
                        0, 1
                    ]);
                    indices = [
                        0, 1, 2,
                        2, 3, 0
                    ];

            let geometry = new THREE.BufferGeometry();
            geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
            geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
            geometry.setIndex(indices);

            const options = {
                color: new THREE.Color(colors.water),
                textureWidth: waterRes,
                textureHeight: waterRes,
                shader: this.getSurfaceShader() // Copies the shader from Refractor class to customize the 'waveStrength' and 'waveSpeed' variables, see further down            
            };

            this.surface = new Refractor(geometry, options);

This code is then run every frame to update the Refractor:

            if (this.settings.showWaves) {
                if (this.surface.material.uniforms['tDudv'].value === null) {
                    this.dudv.wrapS = this.dudv.wrapT = THREE.RepeatWrapping;
                    this.surface.material.uniforms['tDudv'].value = this.dudv;
                }
                this.surface.material.uniforms['time'].value = time;
            } else { // Keep the surface but remove the wave effect
                if (this.surface.material.uniforms['tDudv'].value !== null) {
                    this.surface.material.uniforms['tDudv'].value = null;
                }
            }

Here is the shader code returned from this.getSurfaceShader() (I just copied the shader code from the Refractor class so I could adjust the waveSpeed and waveStrength variables):

            uniforms: {
                'color': {
                    value: null
                },
                'time': {
                    value: 0
                },
                'tDiffuse': {
                    value: null
                },
                'tDudv': {
                    value: null
                },
                'textureMatrix': {
                    value: null
                }
            },

            vertexShader: [
                'uniform mat4 textureMatrix;',

                'varying vec2 vUv;',
                'varying vec4 vUvRefraction;',

                'void main() {',
                '	vUv = uv;',
                '	vUvRefraction = textureMatrix * vec4( position, 1.0 );',
                '	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
                '}'
            ].join('\n'),

            fragmentShader: [
                'uniform vec3 color;',
                'uniform float time;',
                'uniform sampler2D tDiffuse;',
                'uniform sampler2D tDudv;',

                'varying vec2 vUv;',
                'varying vec4 vUvRefraction;',

                'float blendOverlay( float base, float blend ) {',
                '	return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );',
                '}',

                'vec3 blendOverlay( vec3 base, vec3 blend ) {',
                '	return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ),blendOverlay( base.b, blend.b ) );',
                '}',

                'void main() {',
                ' float waveStrength = ' + this.settings.waveStrength + ';',
                ' float waveSpeed = ' + this.settings.waveSpeed + ';',

                // simple distortion (ripple) via dudv map (see
                // https://www.youtube.com/watch?v=6B7IF6GOu7s)

                '	vec2 distortedUv = texture2D( tDudv, vec2( vUv.x + time * waveSpeed, vUv.y ) ).rg * waveStrength;',
                '	distortedUv = vUv.xy + vec2( distortedUv.x, distortedUv.y + time * waveSpeed );',
                '	vec2 distortion = ( texture2D( tDudv, distortedUv ).rg * 2.0 - 1.0 ) * waveStrength;',

                // new uv coords
                ' vec4 uv = vec4( vUvRefraction );',
                ' uv.xy += distortion;',
                '	vec4 base = texture2DProj( tDiffuse, uv );',
                '	gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );',
                '}'
            ].join('\n')

The pool is made up of outer wall and the colored sections inside, there is a tiny gap between the wall and the sections:

The material on the outer wall is a MeshPhysicalMaterial and the materail on the colored sections are MeshBasicMaterial (same for the text). The materials are slightly transparent.

BufferGeometry is used for both pool and sections.