[fpc-pascal] Loading PNG files as OpenGL textures

Anthony Walter sysrpl at gmail.com
Mon Oct 12 09:05:33 CEST 2015


I would abstract all platform specific code. I define a encapsulating set
of interfaces for any platform specific stuff. Interface types also provide
a nice layer of abstraction.

In such a way I have at least IDocument, IBitmap, IAudio, and IVideo; where
the last three type define methods for loading and decompressing images,
audio, and video frames in that order. Then for each platform I map the
interfaces to whatever native OS functions work best (or perhaps easiest).
On OSX I use the QuickTime objects to decode video and on Linux it would be
ffmpeg. On Windows I use MSXML parser, on Linux it would be libxml2 (I use
my own libxml wrapper which has better xpath encapsulation), and so on.

Interfaces go into standard units such as YourCompany.Graphics, and
implementations go into YourCompany.Platform.Darwin.Graphics or
YourCompany.Platform.Linux.Graphics. Then in code I only reference
YourCompany.Graphics, which has code like this:

unit YourCompany.Graphics;

type IBitmap = interface ... end;

function CreateBitmap(const FileName: string): IBitmap; overload;
function CreateBitmap(Stream: TStream): IBitmap; overload;

So then to your example. In my engine I have a TTextures asset manager
class (exposed as a singleton):

TTextures = class(TAssetManager)
  procedure Add(const FileName: string; const Name: string); overload;
  procedure Add(Stream: TStream; const Name: string); overload;
  procedure Bind(const Name: string);
  property Texture[Name: string]: TTexture read GetTexture; default;
  ...

function Textures: TTextures;

The actual TTextures.Add methods uses an IBitmap interface which can to
load, save, give dimensions, and provide access to pixel data.

procedure TTextures.Add(Stream: TStream; const Name: string);
var
  B: IBitmap;
  T: Texture;
begin
  if Texture[Name] <> nil then Exit;
  B := CreateBitmap(Stream);
  T := TTexture.Create;
  T.Name := Name;
  T.Width := B.Width;
  T.Height := B.Height;
  glGenTextures(1, @T.FId);
  // B.Pixels has the pixel data which will be freed with the interface
  ...
end;

You get the idea I hope.

For stuff which might need a different implementation on platforms: define
interfaces.
For stuff which is unaffected by platforms, encapsulate that using types
like records, classes, enums, and sets.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20151012/7b5ba171/attachment.html>


More information about the fpc-pascal mailing list