Water effect (reflection + refraction)

Hello again,

I manage to create some nice “reflection and refraction” textures of my scene in order to achieve a “realistic” water effect.

I applied the following steps:

  1. creating FBOs for both reflection and refraction
  2. clipping planes (clipping for reflection the image which is above the water & clipping for refraction the image which is under the water). basically I checked that textures are fine (indeed, are rendered fine in my FBOs)
  3. using projection texture mapping I tried to apply my textures on my “plane” which is the “water”.

However, my textures are not aligned properly (somehow those are not synced with the actual scene). If you can help me getting this done I would be really thankful.

This is what I get: https://www.youtube.com/watch?v=dZqh7CBfE-c (Left Top square is the reflection and Right Top square is refraction) - i’m using only reflection for now.

As you can see, I used only the reflection image, but the refraction image works same (it is not inverted because it is not reflection, but doesn’t fit my ground).

Here is my shader:

Vertex Shader

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 normal;

out vec2 texCoord0;
out vec4 clipSpace;
out vec3 normal0;
out vec3 worldPos0;

uniform mat4 view;
uniform mat4 proj;
uniform mat4 trans;

void main()
{
	gl_Position = proj * view * trans * vec4(position.x, position.y, position.z, 1.0);

	clipSpace = proj * view * trans * vec4(position.x, position.y, position.z, 1.0);
	worldPos0 = (trans * vec4(position, 1.0)).xyz;
	texCoord0 = texCoord;
	normal0 = normal;
}

Fragment Shader

#version 330 core

in vec3 normal0;
in vec2 texCoord0;
in vec4 clipSpace;
in vec3 worldPos0;

out vec4 outColor;


uniform sampler2D reflectionTexture;
uniform sampler2D refractionTexture;

void main()
{
	vec3 ndc = (clipSpace.xyz / clipSpace.w)/ 2.0 + 0.5;

	vec2 reflectTexCoords = vec2(ndc.x, -ndc.y);
	vec2 refractTexCoords = vec2(ndc.x, ndc.y);

	vec4 reflectColor = texture2D(reflectionTexture, reflectTexCoords);
	vec4 refractionColor = texture2D(refractionTexture, refractTexCoords);

    outColor = reflectColor;
}

Source

glEnable(GL_CLIP_DISTANCE0);

        // Render Scene
        /// REFLECTION rendering

        waterFBO->bindReflectionFrameBuffer();
        glUniform4f(planeCoordinates, 0.0f, 1.0f, 0.0f, -150.0f);

        float distance = 2 * 150.0f;

        view->setPosition(glm::vec3(view->getPosition().x, view->getPosition().y - distance, view->getPosition().z));
        view->invertPitch();
        RenderPass(shaderProgram, shadowShaderProgram, mesh1, mesh2, mesh3, uniView, uniProj, uniTrans, view->getProjMatrix(), view->getViewMatrix(), lightSpaceMatrix, sl, skybox, cubeMapSampler, cameraPos, uniTime, time, uniWaterEffect);
        waterFBO->unbindCurrentFrameBuffer();
        view->setPosition(glm::vec3(view->getPosition().x, view->getPosition().y + distance, view->getPosition().z));
        view->invertPitch();
        /// REFRACTION rendering
        waterFBO->bindRefractionFrameBuffer();
        glUniform4f(planeCoordinates, 0.0f, -1.0f, 0.0f, 150.0f);
        RenderPass(shaderProgram, shadowShaderProgram, mesh1, mesh2, mesh3, uniView, uniProj, uniTrans, ProjectionMatrix, ViewMatrix, lightSpaceMatrix, sl, skybox, cubeMapSampler, cameraPos, uniTime, time, uniWaterEffect);
        waterFBO->unbindCurrentFrameBuffer();

        glDisable(GL_CLIP_DISTANCE0);

        /// Normal Rendering

        glUniform4f(planeCoordinates, 0.0f, -1.0f, 0.0f, 100000.0f);
        /*ShadowMapPass(shaderProgram, shadowShaderProgram, mesh1, mesh2, mesh3, uniShadowView, uniShadowProj, uniShadowTrans, sl, uniTime, time, uniWaterEffect);*/
        RenderPass(shaderProgram, shadowShaderProgram, mesh1, mesh2, mesh3, uniView, uniProj, uniTrans, ProjectionMatrix, ViewMatrix, lightSpaceMatrix, sl, skybox, cubeMapSampler, cameraPos, uniTime, time, uniWaterEffect);

        glUseProgram(waterProgram);

        glUniform1i(waterReflSampler, 2);
        glUniform1i(waterRefrSampler, 3);

        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, waterFBO->getReflectionTexture());

        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D, waterFBO->getRefractionTexture());
        RenderWater(waterTrans, waterProj, waterView, ProjectionMatrix, ViewMatrix, uniTime, uniWaterEffect, time);

        glUseProgram(shaderProgram);

Thanks for your time!