Hello,
I am pretty new to GLSL, but I was able to create a full screen water distortion effect by setting the pixel colors to that of pixels whose positions are dictated by offsets which are derived from a tiling noise texture. Here is how it looks:
Here is the shader. Time is wrapped to be in the range [0, 256) in order to have the water "flow" without any stutter as the noise texture repeats.
uniform sampler2D screenTex;
uniform sampler2D noiseTex;
uniform float time;
void main()
{
// Get the color of the noise texture at a position the current fragment position offset by the time
vec4 noiseTexCol = texture2D(noiseTex, vec2(gl_TexCoord[0].x + time, gl_TexCoord[0].y + time));
// Reduce the offset
float reducedOffset = noiseTexCol.x / 70;
// Get the color of the screen at the offset location
vec4 col = texture2D(screenTex, gl_TexCoord[0].xy + vec2(reducedOffset, reducedOffset));
// Set the fragment color
gl_FragColor = col;
}
But now I would like to apply that only to a specific region in order to create a body of water. I would like to simply distort a region and apply a blue overlay. I tried binding the shader while I drew a simple blue box, but when I run it what was once a blue box flickers seemingly random colors from the screen texture. I am not sure that I understand the GLSL texture coordinate system properly. Perhaps the lack of texture coordinates on the primitives is causing the color flicker.
Here is the code I am using to draw the body of water:
// Render the water shape with the shader applied
sf::Image screen;
screen.CopyScreen(appWindow);
waterShader.SetTexture("screenTex", screen);
waterShader.SetParameter("time", time / 256.0f);
glColor4f(0.2f, 0.2f, 1.0f, 0.4f);
glDisable(GL_TEXTURE_2D);
waterShader.Bind();
Renderb2Body(body, 80.0f);
waterShader.Unbind();
glEnable(GL_TEXTURE_2D);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
Renderb2Body just draws a box. It works fine without the shader.
Any help on this matter is appreciated.