Sorry for putting it here, but I got a problem with mouse looking in my app.

Here's the shader I use:
Code:
// Vertex Shader – file "minimal.vert"

#version 150

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

in vec3 in_Position;
in vec3 in_Color;
out vec3 ex_Color;

void main(void)
{
	gl_Position = projectionMatrix * modelViewMatrix * vec4(in_Position, 1.0);
	ex_Color = in_Color;
}
And here's the camera class:
Code:
//******************************************************************************
//
//  BrainEngine
//  Copyright © 2008 - 2010 Patryk Nusbaum.
//  All rights reserved.
//
//  Last modified: 30.01.2010
//  Mail: patrick.nusbaum@gmail.com
//  WWW: www.pateman.net76.net
//
//  Based on code by Luuk van Venrooij.
//
//  License
//  -------------------
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//   * Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//   * Neither the name of Patryk Nusbaum nor the names of his contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
//  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
//  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
//  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//******************************************************************************
unit BrainCamera;

interface

uses
 Windows, dglOpenGL, BrainMath;

type
 { .: TBrainCamera :. }
 TBrainCamera = class(TObject)
 private
  { Private declarations }
  FDir: TAffineVector;
  FFOV: Single;
  FFar: Single;
  FRot: TAffineVector;
  FNear: Single;
  FInvert: Boolean;
  FScreenHeight: Integer;
  FSmooth: Single;
  FUp: TAffineVector;
  FPos: TAffineVector;
  FScreenWidth: Integer;
  procedure SetScreenHeight(const Value: Integer);
  procedure SetScreenWidth(const Value: Integer);
 protected
  { Protected declarations }
  ProjectionLocation, ModelViewLocation: Integer;
  ProjectionMatrix, ModelViewMatrix: TMatrix;
  ScreenCenterX, ScreenCenterY: Integer;
 public
  { Public declarations }
  constructor Create(const AScreenWidth, AScreenHeight: Integer;
   const ProjMatUniform, ModelViewUniform: Integer);

  procedure ApplyPerspective();
  procedure ApplyTransform(); virtual;

  procedure Move(const ASpeed: Single); virtual; abstract;
  procedure Strafe(const ASpeed: Single); virtual; abstract;
  procedure MouseLook(); virtual; abstract;

  property ScreenWidth: Integer read FScreenWidth write SetScreenWidth;
  property ScreenHeight: Integer read FScreenHeight write SetScreenHeight;

  property Position: TAffineVector read FPos write FPos;
  property Direction: TAffineVector read FDir write FDir;
  property Rotation: TAffineVector read FRot write FRot;
  property Up: TAffineVector read FUp write FUp;

  property FieldOfView: Single read FFOV write FFOV;
  property NearPlane: Single read FNear write FNear;
  property FarPlane: Single read FFar write FFar;

  property MouseSmooth: Single read FSmooth write FSmooth;
  property InvertMouse: Boolean read FInvert write FInvert;
 end;

 { .: TBrainFreeCamera :. }
 TBrainFreeCamera = class sealed(TBrainCamera)
 private
  { Private declarations }
  FMaxAngle: Single;
  FMinAngle: Single;
 protected
  { Protected declarations }
  function MakeRotationMatrix(const V: TAffineVector): TMatrix;
 public
  { Public declarations }
  constructor Create(const AScreenWidth, AScreenHeight: Integer;
   const ProjMatUniform, ModelViewUniform: Integer);

  procedure ApplyTransform(); override;

  procedure Move(const ASpeed: Single); override;
  procedure Strafe(const ASpeed: Single); override;
  procedure MouseLook(); override;

  property MaxAngle: Single read FMaxAngle write FMaxAngle;
  property MinAngle: Single read FMinAngle write FMinAngle;
 end;

implementation


{ TBrainCamera }

procedure TBrainCamera.ApplyPerspective;
begin
 if (FScreenHeight <= 0) then
  FScreenHeight := 1;
 glViewport(0, 0, FScreenWidth, FScreenHeight);

 ProjectionMatrix := CalcPerspectiveMatrix(FFOV, FScreenWidth / FScreenHeight,
  FNear, FFar);
 glUniformMatrix4fv(ProjectionLocation, 1, False, @ProjectionMatrix);
end;

procedure TBrainCamera.ApplyTransform;
begin
 // --
end;

constructor TBrainCamera.Create(const AScreenWidth, AScreenHeight,
 ProjMatUniform, ModelViewUniform: Integer);
begin
 inherited Create();

 if (AScreenWidth <= 0) then
  FScreenWidth := 1
 else
  FScreenWidth := AScreenWidth;
 if (AScreenHeight <= 0) then
  FScreenHeight := 1
 else
  FScreenHeight := AScreenHeight;
 ScreenCenterX := FScreenWidth div 2;
 ScreenCenterY := FScreenHeight div 2;

 ProjectionLocation := ProjMatUniform;
 ModelViewLocation := ModelViewUniform;

 ApplyTransform();

 FPos := NullVector;
 FUp := YVector;
 FDir := MinusZVector;
 FRot := NullVector;

 FInvert := False;
 FSmooth := 0.25;

 FFOV := 40.0;
 FNear := 0.1;
 FFar := 1000.0;
end;

procedure TBrainCamera.SetScreenHeight(const Value: Integer);
begin
 if (Value <= 0) then
  FScreenHeight := 1
 else
  FScreenHeight := Value;

 ScreenCenterY := FScreenHeight div 2;
end;

procedure TBrainCamera.SetScreenWidth(const Value: Integer);
begin
 FScreenWidth := Value;

 ScreenCenterX := FScreenWidth div 2;
end;

{ TBrainFreeCamera }

procedure TBrainFreeCamera.ApplyTransform;
begin
 ModelViewMatrix := LookAt(FPos, AffineVectorMake(FPos.V[0] + FDir.V[0],
  FPos.V[1] + FDir.V[1], FPos.V[2] + FDir.V[2]), FUp);
 glUniformMatrix4fv(ModelViewLocation, 1, False, @ModelViewMatrix);
end;

constructor TBrainFreeCamera.Create(const AScreenWidth, AScreenHeight,
 ProjMatUniform, ModelViewUniform: Integer);
begin
 inherited Create(AScreenWidth, AScreenHeight, ProjMatUniform, ModelViewUniform);

 FMaxAngle := 89.0;
 FMinAngle := -89.0;
end;

function TBrainFreeCamera.MakeRotationMatrix(const V: TAffineVector): TMatrix;
var
 M, mX, mY, mZ: TMatrix;
begin
 mX := CreateRotationMatrixX(DegToRad(V.V[0]));
 mY := CreateRotationMatrixY(DegToRad(V.V[1]));
 mZ := CreateRotationMatrixZ(DegToRad(V.V[2]));
 M := MatrixMultiply(mZ, mY);
 Result := MatrixMultiply(mX, M);
end;

procedure TBrainFreeCamera.MouseLook;
var
 Pos, Delta: TPoint;
 M: TMatrix;
begin
 GetCursorPos(Pos);
 SetCursorPos(ScreenCenterX, ScreenCenterY);

 Delta.X := ScreenCenterX - Pos.X;
 Delta.Y := ScreenCenterY - Pos.Y;

 FRot.V[1] := FRot.V[1] + Delta.X * FSmooth;

 if FInvert then
  FRot.V[0] := FRot.V[0] - Delta.Y * FSmooth
 else
  FRot.V[0] := FRot.V[0] + Delta.Y * FSmooth;

 if (FRot.V[0] < FMinAngle) then
  FRot.V[0] := FMinAngle;
 if (FRot.V[0] > FMaxAngle) then
  FRot.V[0] := FMaxAngle;

 M := MakeRotationMatrix(FRot);
 FDir := VectorTransform(MinusZVector, M);
end;

procedure TBrainFreeCamera.Move(const ASpeed: Single);
var
 M: TMatrix;
begin
 M := MakeRotationMatrix(FRot);
 FDir := VectorTransform(MinusZVector, M);

 FPos.V[0] := FPos.V[0] + (FDir.V[0] * -ASpeed);
 FPos.V[1] := FPos.V[1] + (FDir.V[1] * -ASpeed);
 FPos.V[2] := FPos.V[2] + (FDir.V[2] * -ASpeed);
end;

procedure TBrainFreeCamera.Strafe(const ASpeed: Single);
var
 M: TMatrix;
begin
 M := MakeRotationMatrix(FRot);
 FDir := VectorTransform(MinusZVector, M);

 FPos.V[0] := FPos.V[0] + (FDir.V[2] * -ASpeed);
 FPos.V[2] := FPos.V[2] + (-FDir.V[0] * -ASpeed);
end;

end.
I don't know why, but the code produces weird pespective dissonance when I move my mouse:

I have no idea where the problem is. Is the shader code wrong or am I doing something wrong with the matrix operations? Can you point me out my mistake?