unit dgen_perlin;

interface

uses
  dcolors,
  dvector2f,
  dscreenbuffer,
  dtexture2d_generator,
  dgen_noise;

type
TTexPerlin1f = class(TTexGen1f)
  Noise: TTexGen1f;
  Steps: Integer;
  function Get(const V: TVec2f): Single; override;
end;

function Turbulence1f(Steps: Integer = 64; Noise: TTexGen1f = nil): TTexPerlin1f;

implementation

const
  GUESS_SIZE = 512;

function GetTurbulence(Noise: TTexGen1f; X, Y: Single; Size: Integer): Single; inline;
var
  InitialSize: Single;
begin
  InitialSize := Size;

  Result := 0;
  while Size >= 1 do begin
    Result := Result + Noise.Get(Vec2f(X / Size, Y / Size)) * Size;
	Size := Size div 2;
  end;

  Result := 0.5 * Result / InitialSize;
end;

function TTexPerlin1f.Get(const V: TVec2f): Single;
begin
  Result := GetTurbulence(Noise, V.X, V.Y, Steps);
end;

function Turbulence1f(Steps: Integer = 64; Noise: TTexGen1f = nil): TTexPerlin1f;
begin
  Result := TTexPerlin1f.Create;
  Result.Steps := Steps;
  if Noise = nil then
    Result.Link(Result.Noise, DefaultNoise1f)
  else
    Result.Link(Result.Noise, Noise);
end;

end.
