unit Noise;

interface

var
  PSeed : LongInt;

function PerlinNoise(X, Y: LongInt): Single;
function CompileNoise(X, Y: Single): Single;

implementation

function PerlinNoise(X, Y: LongInt): Single;
var
  N : LongInt;
begin
  n := x  + y*54 + PSeed ;
  n := ( n shl 13 ) xor n;
  Result := 1 - ( (n * (n * n * 15731 + 789221) + 1376312589) and $7fffffff) / 1073741824;
end;

function SmoothedNoise2D(x, y:Integer): Single;
var
  val : single;
begin
  val := (PerlinNoise(X-1, Y-1) + PerlinNoise(X+1, Y-1) + PerlinNoise(X-1, Y+1) + PerlinNoise(X+1, X+1) ) / 16;
  val := val + (PerlinNoise(X-1, Y) + PerlinNoise(X+1, Y) + PerlinNoise(X, Y-1) + PerlinNoise(X, Y+1) ) / 8;
  val := val + PerlinNoise(X, Y) / 4;

  result := val;
end;

function CompileNoise(X, Y: Single): Single;
var
  v1, v2, v3, v4 : Single;
  intX, intY: Cardinal;

  function Lerp(a, b,x: Single) : Single; inline;
  var  ft ,f: Single;
  begin
    ft := x * pi;
    f := (1 - cos(ft)) * 0.5;
    result := a*(1-f) + b*f;
  end;

begin
  intX := Trunc(X);
  intY := Trunc(Y);

  v1 := SmoothedNoise2D(intX  , intY);
  v2 := SmoothedNoise2D(intX+1, intY);
  v3 := SmoothedNoise2D(intX  , intY+1);
  v4 := SmoothedNoise2D(intX+1, intY+1);

  Result := Lerp(Lerp(v1, v2, Frac(X)), Lerp(v3, v4, Frac(X)), Frac(Y));
end;

end.
