unit DepthTexture;

interface

uses Windows, SysUtils, GL, GLu, GLext, WGLext, GLtools, Textures, Images;

const
  TEX_DEPTH                 = GL_DEPTH_COMPONENT;
  TEX_DEPTH16               = GL_DEPTH_COMPONENT16;
  TEX_DEPTH24               = GL_DEPTH_COMPONENT24;
  TEX_DEPTH32               = GL_DEPTH_COMPONENT32;

procedure DepthTextureFormat(tex: TTexture; fmt: cardinal);

type
  // WARNING!! This class is very experimental!
  TDepthTexture = class(TTexture2D)
  protected
    procedure SetImage(img: TImage); override;
    function GetImage: TImage; override;
  public
    constructor Create; override;
    procedure Initialize(w, h: integer); virtual;
  end;

implementation

var
  GL_ARB_depth_texture_loaded: boolean = false;

constructor TDepthTexture.Create;
begin
  if not GL_ARB_depth_texture_loaded then
  begin
    if not glext_ExtensionSupported('GL_ARB_depth_texture') then
      raise Exception.Create('GL_ARB_depth_texture required!');
    GL_ARB_depth_texture_loaded := true;
  end;

  inherited Create;

  InternalFormat := GL_DEPTH_COMPONENT;
end;

procedure TDepthTexture.Initialize;
var
  data: pointer;
begin
  Bind;
  GetMem(data, w * h);
  glTexImage2D(GL_TEXTURE_2D, 0, FInternalFormat, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, data);
  FreeMem(data, w * h);
end;

procedure TDepthTexture.SetImage;
begin
  Bind;
  glTexImage2D(FTarget, 0, FInternalFormat, img.Width, img.Height, 0, GL_RED,
    GL_FLOAT, img.Data);
end;

function TDepthTexture.GetImage;
begin
  Bind;
  result := TImage.Create(Width*4, Height, 32);
  glGetTexImage(FTarget, 0, GL_BGRA, GL_UNSIGNED_INT, result.Data);
  result.MakeDepthMap;
end;

procedure DepthTextureFormat;
begin
  if not GL_ARB_depth_texture_loaded then
  begin
    if not glext_ExtensionSupported('GL_ARB_depth_texture') then
      raise Exception.Create('GL_ARB_depth_texture required!');
    GL_ARB_depth_texture_loaded := true;
  end;
  tex.InternalFormat := fmt;
end;

end.
