program BumpMapping;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  GL in 'OpenGL\GL.pas',
  GLu in 'OpenGL\GLu.pas',
  GLut in 'OpenGL\GLut.pas',
  GLext in 'OpenGL\GLext.pas',
  WGLext in 'OpenGL\WGLext.pas',
  GLtools in 'OpenGL\GLtools.pas',
  Math3D in 'Math3D\Math3D.pas',
  VertexArray in 'VertexArray\VertexArray.pas',
  CompiledVertexArray in 'VertexArray\CompiledVertexArray\CompiledVertexArray.pas',
  Images in 'Images\Images.pas',
  TGA in 'Images\TGA\TGA.pas',
  DXT in 'Images\DXT\DXT.pas',
  Textures in 'Textures\Textures.pas',
  Mipmaps in 'Textures\Mipmaps\Mipmaps.pas',
  TextureLODBias in 'Textures\TextureLODBias\TextureLODBias.pas',
  TextureCompression in 'Textures\TextureCompression\TextureCompression.pas',
  S3TC in 'Textures\TextureCompression\S3TC\S3TC.pas',
  AnisotropicFilter in 'Textures\AnisotropicFilter\AnisotropicFilter.pas',
  Texture3D in 'Textures\Texture3D\Texture3D.pas',
  TextureCubeMap in 'Textures\TextureCubeMap\TextureCubeMap.pas',
  TextureRectangle in 'Textures\TextureRectangle\TextureRectangle.pas',
  DepthTexture in 'Textures\DepthTexture\DepthTexture.pas',
  Occlusion in 'Culling\Occlusion\Occlusion.pas',
  ShaderObjects in 'Shaders\GLSL\ShaderObjects\ShaderObjects.pas',
  VertexShaderObject in 'Shaders\GLSL\ShaderObjects\VertexShaderObject\VertexShaderObject.pas',
  FragmentShaderObject in 'Shaders\GLSL\ShaderObjects\FragmentShaderObject\FragmentShaderObject.pas',
  ARBprograms in 'Shaders\ASMShaders\ARBprograms\ARBprograms.pas',
  ARBvertexProgram in 'Shaders\ASMShaders\ARBprograms\ARBvertexProgram\ARBvertexProgram.pas',
  ARBfragmentProgram in 'Shaders\ASMShaders\ARBprograms\ARBfragmentProgram\ARBfragmentProgram.pas',
  TextureCombiners in 'Shaders\TextureCombiners\TextureCombiners.pas',
  Scripts in 'Scripts\Scripts.pas',
  ATIfragmentShader in 'Shaders\ASMShaders\ATIfragmentShader\ATIfragmentShader.pas',
  RegisterCombiners in 'Shaders\RegisterCombiners\RegisterCombiners.pas',
  NV_parse in 'Shaders\NV_parse\NV_parse.pas',
  EnvMapBumpMap in 'Shaders\EnvMapBumpMap\EnvMapBumpMap.pas',
  OffsetTexture in 'Textures\OffsetTexture\OffsetTexture.pas',
  ScissorBox in 'Culling\ScissorBox\ScissorBox.pas',
  Models in 'Models\Models.pas',
  MDF in 'Models\MDF\MDF.pas',
  VertexArrayObject in 'VertexArray\VertexArrayObject\VertexArrayObject.pas',
  TruForm in 'VertexArray\TruForm\TruForm.pas',
  FragmentCombiners in 'Shaders\FragmentCombiners\FragmentCombiners.pas',
  Fonts in 'Fonts\Fonts.pas',
  VertexBufferObject in 'VertexArray\VertexBufferObject\VertexBufferObject.pas',
  Shaders in 'Shaders\Shaders.pas',
  FrameBuffers in 'FrameBuffers\FrameBuffers.pas',
  Camera in 'Camera\Camera.pas',
  FirstPersonCamera in 'Camera\FirstPersonCamera\FirstPersonCamera.pas',
  NewtonImport in 'Newton\NewtonImport.pas',
  BumpMappingPanel in 'BumpMappingPanel.pas' {BumpPanel};

const
  OREN_NAYAR_SIGMA                  = 0.5;
  MINNAERT_M                        = 1.5;
  PHONG_N                           = 32;
  BLINN_PHONG_N                     = 64;
  SCHLICK_N                         = 32;
  WARD_ISO_SIGMA                    = 0.1;
  WARD_ANISO_SIGMAX                 = 0.5;
  WARD_ANISO_SIGMAY                 = 0.1;

var
  lx, ly: integer;
  rx, ry: single;
  i: integer;

  vs: array[1..4] of TVertexShaderObject;
  fs: array[1..4] of TFragmentShaderObject;
  po: array[1..4] of TProgramObject;
  name: array[1..4] of string = ('nobump', 'normal', 'parallax', 'pom');
  tex: array[0..1] of TTexture2D;
  img: TImage;

  lp: TVector4;

procedure display; cdecl;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;

  glTranslatef(0, 0, -5);
  glRotatef(rx, 1, 0, 0);
  glRotatef(ry, 0, 1, 0);

  glEnable(GL_CULL_FACE);

  glActiveTexture(GL_TEXTURE0);
  tex[0].Enable;
  po[BumpTechnique].GetUniformObject('normalmap').Value1i := 0;
  glActiveTexture(GL_TEXTURE1);
  tex[1].Enable;
  po[BumpTechnique].GetUniformObject('diffusemap').Value1i := 1;

  po[BumpTechnique].Enable;

  glBegin(GL_QUADS);

    glNormal3f(0,0,1);
    glColor3f(0.5,0,0.5);
    glSecondaryColor3f(1,0.5,0.5);

    glTexCoord2f(0,0);
    glVertex3f(-1,1,1);
    glTexCoord2f(1,0);
    glVertex3f(-1,-1,1);
    glTexCoord2f(1,1);
    glVertex3f(1,-1,1);
    glTexCoord2f(0,1);
    glVertex3f(1,1,1);

    glNormal3f(0,0,-1);
    glColor3f(0.5,0,0.5);
    glSecondaryColor3f(0,0.5,0.5);

    glTexCoord2f(0,0);
    glVertex3f(1,1,-1);
    glTexCoord2f(1,0);
    glVertex3f(1,-1,-1);
    glTexCoord2f(1,1);
    glVertex3f(-1,-1,-1);
    glTexCoord2f(0,1);
    glVertex3f(-1,1,-1);

    glNormal3f(1,0,0);
    glColor3f(0.5,0,0.5);
    glSecondaryColor3f(0.5,0.5,0);

    glTexCoord2f(0,0);
    glVertex3f(1,1,1);
    glTexCoord2f(1,0);
    glVertex3f(1,-1,1);
    glTexCoord2f(1,1);
    glVertex3f(1,-1,-1);
    glTexCoord2f(0,1);
    glVertex3f(1,1,-1);

    glNormal3f(-1,0,0);
    glColor3f(0.5,0,0.5);
    glSecondaryColor3f(0.5,0.5,1);

    glTexCoord2f(0,0);
    glVertex3f(-1,1,-1);
    glTexCoord2f(1,0);
    glVertex3f(-1,-1,-1);
    glTexCoord2f(1,1);
    glVertex3f(-1,-1,1);
    glTexCoord2f(0,1);
    glVertex3f(-1,1,1);

    glNormal3f(0,1,0);
    glColor3f(0,0.5,0.5);
    glSecondaryColor3f(0.5,0.5,1);

    glTexCoord2f(0,0);
    glVertex3f(1,1,-1);
    glTexCoord2f(1,0);
    glVertex3f(-1,1,-1);
    glTexCoord2f(1,1);
    glVertex3f(-1,1,1);
    glTexCoord2f(0,1);
    glVertex3f(1,1,1);

    glNormal3f(0,-1,0);
    glColor3f(0,0.5,0.5);
    glSecondaryColor3f(0.5,0.5,0);

    glTexCoord2f(0,0);
    glVertex3f(1,-1,1);
    glTexCoord2f(1,0);
    glVertex3f(-1,-1,1);
    glTexCoord2f(1,1);
    glVertex3f(-1,-1,-1);
    glTexCoord2f(0,1);
    glVertex3f(1,-1,-1);

  glEnd;

  glutSwapBuffers;
end;

procedure reshape(w, h: Integer); cdecl;
begin
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(45, w/h, 0.1, 100);
  glMatrixMode(GL_MODELVIEW);
end;

procedure keyboard(key: byte; x, y: Integer); cdecl;
begin
  if key = 27 then halt;
end;

procedure special(key, x, y: Integer); cdecl;
begin
end;

procedure mouse(button, state, x, y: Integer); cdecl;
begin
  lx := x;
  ly := y;
end;

procedure motion(x, y: Integer); cdecl;
begin
  rx := rx + (y-ly)*0.5;
  ry := ry + (x-lx)*0.5;
  lx := x;
  ly := y;
end;

procedure passivemotion(x, y: Integer); cdecl;
begin
end;

procedure visibility(state: Integer); cdecl;
begin
end;

procedure idle; cdecl;
begin
end;

procedure timer(value: integer); cdecl;
begin
  glutTimerFunc(15, timer, 0);
  glutPostRedisplay;
end;

begin
  try
    rx := 30;
    ry := -30;

    writeln('*********************');
    writeln('  BUMP MAPPING DEMO  ');
    writeln('*********************');

    write('GLUT inicializalasa...................');

    glutInit;
    glutInitDisplayMode(GLUT_RGBA or GLUT_DOUBLE or GLUT_DEPTH);
    glutInitWindowSize(600, 600);
    glutCreateWindow('Bump Mapping Demo');

    Load_GL_VERSION_1_2;
    Load_GL_VERSION_1_3;
    Load_GL_VERSION_1_4;
    Load_GL_VERSION_1_5;
    Load_GL_VERSION_2_0;

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(special);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutPassiveMotionFunc(passivemotion);
    glutVisibilityFunc(visibility);
    glutIdleFunc(idle);
    glutTimerFunc(15, timer, 0);

    glEnable(GL_DEPTH_TEST);

    writeln('kesz');

    write('Konfiguracios panel inicializalasa....');

    BumpPanel := TBumpPanel.Create(nil);
    BumpPanel.Show;

    writeln('kesz');

    write('Texturak betoltese....................');

    img := LoadTGA('_textures\normal.tga');
    tex[0] := TTexture2D.Create;
    GenerateMipmap(tex[0], GL_TRUE);
    tex[0].MagFilter := GL_LINEAR;
    tex[0].MinFilter := GL_LINEAR_MIPMAP_LINEAR;
    tex[0].WrapModeS := GL_REPEAT;
    tex[0].WrapModeT := GL_REPEAT;
    tex[0].Image := img;
    img.Destroy;

    img := LoadTGA('_textures\diffuse.tga');
    tex[1] := TTexture2D.Create;
    GenerateMipmap(tex[1], GL_TRUE);
    tex[1].MagFilter := GL_LINEAR;
    tex[1].MinFilter := GL_LINEAR_MIPMAP_LINEAR;
    tex[1].WrapModeS := GL_REPEAT;
    tex[1].WrapModeT := GL_REPEAT;
    tex[1].Image := img;
    img.Destroy;

    writeln('kesz');

    writeln('Shaderek inicializalasa...............');

    for i := 1 to 4 do
    begin
      write(uppercase(name[i]), ' :: beolvasas :: ');
      vs[i] := TVertexShaderObject.Create;
      fs[i] := TFragmentShaderObject.Create;
      po[i] := TProgramObject.Create;
      vs[i].Load('_shaders\'+name[i]+'.vsh');
      fs[i].Load('_shaders\'+name[i]+'.fsh');
      write('forditas :: ');
      vs[i].Compile;
      fs[i].Compile;
      write('szerkesztes :: ');
      po[i].Attach(vs[i]);
      po[i].Attach(fs[i]);
      po[i].Link;
      writeln('kesz');
    end;

    glutMainLoop;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

