#version 110
varying vec2 vertex_uv;
uniform sampler2D texture;
uniform sampler2D displace_map;
uniform float maximum;
uniform float time;
void
main (void)
{
  float time_e      = time * 0.001;
  vec2 uv_t         = vec2(vertex_uv.s + time_e, vertex_uv.t + time_e);
  vec4 displace     = texture2D(displace_map, uv_t);
 
  float displace_k  = displace.g * maximum;
  vec2 uv_displaced = vec2(vertex_uv.x + displace_k,
                           vertex_uv.y + displace_k);
  gl_FragColor      = texture2D(texture, uv_displaced);
}
Ripple(
  final String image,
  final String displace)
  throws IOException
{
  this.texture_image = Utilities.loadTexture(image);
  this.texture_displacement_map = Utilities.loadTexture(displace);
  this.framebuffer_texture =
    Utilities.createEmptyTexture(
      Ripple.TEXTURE_WIDTH,
      Ripple.TEXTURE_HEIGHT);
  this.framebuffer = Utilities.createFramebuffer(this.framebuffer_texture);
  this.shader_uv = Utilities.createShader("dist/shader_uv.v", "dist/shader_uv.f");
  this.shader_displace =
    Utilities.createShader("dist/shader_uv.v", "dist/shader_displace.f");
}
private void renderToTexture()
{
  GL11.glMatrixMode(GL11.GL_PROJECTION);
  GL11.glLoadIdentity();
  GL11.glOrtho(0, 1, 0, 1, 1, 100);
  GL11.glMatrixMode(GL11.GL_MODELVIEW);
  GL11.glLoadIdentity();
  GL11.glTranslated(0, 0, -1);
  GL11.glViewport(0, 0, Ripple.TEXTURE_WIDTH, Ripple.TEXTURE_HEIGHT);
  GL11.glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
  GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, this.framebuffer);
  {
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_image);
    GL13.glActiveTexture(GL13.GL_TEXTURE1);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_displacement_map);
    GL20.glUseProgram(this.shader_displace);
    {
      final int ut = GL20.glGetUniformLocation(this.shader_displace, "texture");
      final int udm = GL20.glGetUniformLocation(this.shader_displace, "displace_map");
      final int umax = GL20.glGetUniformLocation(this.shader_displace, "maximum");
      final int utime = GL20.glGetUniformLocation(this.shader_displace, "time");
      GL20.glUniform1i(ut, 0);
      GL20.glUniform1i(udm, 1);
      GL20.glUniform1f(umax, 0.2f);
      GL20.glUniform1f(utime, this.time);
      Utilities.checkGL();
      GL11.glBegin(GL11.GL_QUADS);
      {
        GL11.glTexCoord2f(0, 1);
        GL11.glVertex3d(0, 1, 0);
        GL11.glTexCoord2f(0, 0);
        GL11.glVertex3d(0, 0, 0);
        GL11.glTexCoord2f(1, 0);
        GL11.glVertex3d(1, 0, 0);
        GL11.glTexCoord2f(1, 1);
        GL11.glVertex3d(1, 1, 0);
      }
      GL11.glEnd();
    }
    GL20.glUseProgram(0);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    GL13.glActiveTexture(GL13.GL_TEXTURE1);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
  }
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
  Utilities.checkGL();
}
private void renderScene()
{
  GL11.glMatrixMode(GL11.GL_PROJECTION);
  GL11.glLoadIdentity();
  GL11.glFrustum(-1, 1, -1, 1, 1, 100);
  GL11.glMatrixMode(GL11.GL_MODELVIEW);
  GL11.glLoadIdentity();
  GL11.glTranslated(0, 0, -1.25);
  GL11.glRotated(30, 0, 0, 1);
  GL11.glViewport(0, 0, Ripple.SCREEN_WIDTH, Ripple.SCREEN_HEIGHT);
  GL11.glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
  GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
  GL20.glUseProgram(this.shader_uv);
  {
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.framebuffer_texture);
    Utilities.checkGL();
    final int ut = GL20.glGetUniformLocation(this.shader_uv, "texture");
    GL20.glUniform1i(ut, 0);
    Utilities.checkGL();
    GL11.glBegin(GL11.GL_QUADS);
    {
      GL11.glTexCoord2f(0, 0);
      GL11.glVertex3d(-0.75, 0.75, 0);
      GL11.glTexCoord2f(0, 1);
      GL11.glVertex3d(-0.75, -0.75, 0);
      GL11.glTexCoord2f(1, 1);
      GL11.glVertex3d(0.75, -0.75, 0);
      GL11.glTexCoord2f(1, 0);
      GL11.glVertex3d(0.75, 0.75, 0);
    }
    GL11.glEnd();
  }
  GL20.glUseProgram(0);
  Utilities.checkGL();
}
Caustics(
  final String underlay,
  final String overlay,
  final String displace)
  throws IOException
{
  this.texture_underlay = Utilities.loadTexture(underlay);
  this.texture_overlay = Utilities.loadTexture(overlay);
  this.texture_displacement_map = Utilities.loadTexture(displace);
  this.framebuffer_texture =
    Utilities.createEmptyTexture(
      Caustics.TEXTURE_WIDTH,
      Caustics.TEXTURE_HEIGHT);
  this.framebuffer = Utilities.createFramebuffer(this.framebuffer_texture);
  this.shader_uv =
    Utilities.createShader("dist/shader_uv.v", "dist/shader_multi_uv.f");
  this.shader_displace =
    Utilities.createShader("dist/shader_uv.v", "dist/shader_displace.f");
}
private void renderToTexture()
{
  GL11.glMatrixMode(GL11.GL_PROJECTION);
  GL11.glLoadIdentity();
  GL11.glOrtho(0, 1, 0, 1, 1, 100);
  GL11.glMatrixMode(GL11.GL_MODELVIEW);
  GL11.glLoadIdentity();
  GL11.glTranslated(0, 0, -1);
  GL11.glViewport(0, 0, Caustics.TEXTURE_WIDTH, Caustics.TEXTURE_HEIGHT);
  GL11.glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
  GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, this.framebuffer);
  {
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_overlay);
    GL13.glActiveTexture(GL13.GL_TEXTURE1);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_displacement_map);
    GL20.glUseProgram(this.shader_displace);
    {
      final int ut =
        GL20.glGetUniformLocation(this.shader_displace, "texture");
      final int udm =
        GL20.glGetUniformLocation(this.shader_displace, "displace_map");
      final int umax =
        GL20.glGetUniformLocation(this.shader_displace, "maximum");
      final int utime =
        GL20.glGetUniformLocation(this.shader_displace, "time");
      GL20.glUniform1i(ut, 0);
      GL20.glUniform1i(udm, 1);
      GL20.glUniform1f(umax, 0.1f);
      GL20.glUniform1f(utime, this.time);
      Utilities.checkGL();
      GL11.glBegin(GL11.GL_QUADS);
      {
        GL11.glTexCoord2f(0, 1);
        GL11.glVertex3d(0, 1, 0);
        GL11.glTexCoord2f(0, 0);
        GL11.glVertex3d(0, 0, 0);
        GL11.glTexCoord2f(1, 0);
        GL11.glVertex3d(1, 0, 0);
        GL11.glTexCoord2f(1, 1);
        GL11.glVertex3d(1, 1, 0);
      }
      GL11.glEnd();
    }
    GL20.glUseProgram(0);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    GL13.glActiveTexture(GL13.GL_TEXTURE1);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
  }
  GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
  Utilities.checkGL();
}
private void renderScene()
{
  GL11.glMatrixMode(GL11.GL_PROJECTION);
  GL11.glLoadIdentity();
  GL11.glFrustum(-1, 1, -1, 1, 1, 100);
  GL11.glMatrixMode(GL11.GL_MODELVIEW);
  GL11.glLoadIdentity();
  GL11.glTranslated(0, 0, -1.25);
  GL11.glRotated(30, 0, 0, 1);
  GL11.glViewport(0, 0, Caustics.SCREEN_WIDTH, Caustics.SCREEN_HEIGHT);
  GL11.glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
  GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
  GL20.glUseProgram(this.shader_uv);
  {
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_underlay);
    GL13.glActiveTexture(GL13.GL_TEXTURE1);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.framebuffer_texture);
    Utilities.checkGL();
    final int ut0 = GL20.glGetUniformLocation(this.shader_uv, "texture0");
    GL20.glUniform1i(ut0, 0);
    final int ut1 = GL20.glGetUniformLocation(this.shader_uv, "texture1");
    GL20.glUniform1i(ut1, 1);
    final int um = GL20.glGetUniformLocation(this.shader_uv, "mix");
    GL20.glUniform1f(um, 0.5f);
    final int us0 = GL20.glGetUniformLocation(this.shader_uv, "scale0");
    GL20.glUniform1f(us0, 2.0f);
    final int us1 = GL20.glGetUniformLocation(this.shader_uv, "scale1");
    GL20.glUniform1f(us1, 0.8f);
    Utilities.checkGL();
    GL11.glBegin(GL11.GL_QUADS);
    {
      GL11.glTexCoord2f(0, 0);
      GL11.glVertex3d(-0.75, 0.75, 0);
      GL11.glTexCoord2f(0, 1);
      GL11.glVertex3d(-0.75, -0.75, 0);
      GL11.glTexCoord2f(1, 1);
      GL11.glVertex3d(0.75, -0.75, 0);
      GL11.glTexCoord2f(1, 0);
      GL11.glVertex3d(0.75, 0.75, 0);
    }
    GL11.glEnd();
  }
  GL20.glUseProgram(0);
  Utilities.checkGL();
}