Modern OpenGL with Lazarus

Following on from my fast bitmaps experiments I have been looking for the simplest way to use modern OpenGL within a Lazarus application.  By modern I mean using the vertex and fragment shader programmable capabilities introduced with OpenGL 2.0 and also avoiding the use of the now depreciated fixed function pipeline calls that were in the core of the original specification.

Indeed, so much has changed since OpenGL version 1.0, that the current OpenGL ‘core’ specification and the closely related OpenGL ES are to all intents and purposes a completely new API.  OpenGL has also undergone a very fluid development with optional extensions becoming available both in successive releases and from different hardware vendors.  This has made writing portable OpenGL code, that is also stable over time, quite a black art.  Especially in Free Pascal where the official OpenGL header files have lagged behind the latest capabilities.  There have been third party headers released and several conversions from Delphi projects for Windows, but this has often just added noise to an already bewildering situation.

There are some notable libraries that do offer good support.  GLScene has been around since the early days of OpenGL and was originally a Delphi library but now contains reasonable Free Pascal support. The Castle Game Engine is also a very capable library designed from the ground up for Free Pascal.  It is particularly strong as an engine for FPS style game development.  There is also the Asmoday library which is a lower level interface than the first two, but this doesn’t seem to be under active development at present.

Free Pascal does come with a GL unit that offers cross platform support for OpenGL up to version 1.1.  This in turn is used by the Lazarus TOpenGLControl to provide add-in component support for LCL applications.  It does not directly support the new APIs required to use programmable hardware, but there is an additional GLExt unit which can dynamically load support for higher versions.  Furthermore, this unit may be used in conjunction with the Lazarus control once it is initialised.  The magic is performed by a series of ‘Load_GL’ functions which may be called in the TOpenGLControl context once it has been made current as follows:

Procedure TMainForm.FormCreate(Sender: TObject);
Begin
  OpenGLControl.MakeCurrent;
  If Load_GL_VERSION_2_0 Then
    Begin
      ShaderProgram := glCreateProgram();
      ...
    End
  Else
    ShowMessage('Unable to initialize modern OpenGL.');
End;

In this case a version 2.0 OpenGL context is created that may be used by the Lazarus control.  The function returns true if the initialization is successful and the dependant code block can contain further version 2.0 set-up code such as the sample glCreateProgram call shown here.

rendermonkeyOne thing I particularly dislike about examples of OpenGL in any language, is the embedding of shader source code as text within the host program.  I find this makes the shader very hard to read and difficult to debug or reuse.  I much prefer to keep these sources in discrete files which can then be embedded using resource scripts.  In fact, it is very useful to be able to copy and paste the code between Lazarus and shader utilities such as RenderMonkey shown in the screen shot above.

One further word of caution, you do need Lazarus 1.6 and Free Pascal 3.0 or later to get this to work.  Also RC resource scripts cannot have spaces in their paths and Windres does not currently work on OS X at all.  There are other Mac issues caused by the way Apple have implemented OpenGL support.  OpenGL 2.0 or later cannot be used in ‘Carbon’ applications (the default for Lazarus).  It is supported with ‘Cocoa’ widgets, but LCL support for this is still in development.

If you would like to see the full source code for a proof of concept application.  I have set up a test project for this on Bitbucket.  I will develop this further as I continue to experiment with modern OpenGL and this will no doubt be the subject of future posts.

Mandelbrot Revisited

I have decided to update the Mandelbrot viewer I originally wrote as a quick Lazarus test application. The original used standard TBitmap handling which was painfully slow, especially on low powered hardware such as Raspberry Pis.

mandelbrotrewrite

I have re-written it using the compact image class detailed in the Fast Bitmaps articles, including an option to use the experimental OpenGL interface. This has had a dramatic effect upon the rendering times,  they are now universally sub-second on my laptop.  I have not yet re-test on the Pi, but they should be much improved there too, although I might need to implement an OpenGLES interface to really stretch that hardware.

In addition to testing the new graphics library, I have structured the program so that it can be used as a test-bed for comparing different rendering methods.  The current options enable the comparison between using Pascal single and double precision floating point alongside SSE assembler.  At present it would seem the FreePascal compiler is capable of writing more efficient assembler than I can!

This is still in its infancy as I intend to add in multi-threaded rendering tests and not to mention, modernising the OpenGL code to remove its dependencies upon the depreciated API glDrawPixels.  Anyway, progress with these experiments will be posted here in due course.

Free Pascal Fast Bitmaps (Part 3)

I have now made public my repository for the test application mentioned in part 2.  This contains the core CompactImage class and two rendering units.  The first is for LCL applications.  This contains platform specific code to render the buffers to a LCL canvas.  This will achieve better frame rates on Windows, Linux and Mac OSX than using the TCanvas Draw method.  The improvement is best on Windows where I am getting a minimum of around 60fps on all of the machines I have tried.  My Kubuntu Laptop achieves around 30fps and the worst performing is my MacBook Pro which struggles to reach 20fps, although this is still twice as fast as the vanilla LCL.

CompactImageTest

The second rendering unit is an experimental OpenGL implementation.  It’s performance is much better than the LCL renderer.  It will vary depending upon the hardware and drivers in use, but again, on my laptop this is achieving over 80fps.  I have noticed it occasionally hangs the program on termination, so I won’t be using this in production yet.  Also the image transfer is achieved through glDrawPixels which I gather is now depreciated in the OpenGL API, so I will be researching a modern alternative implementation to replace this.

Lastly, the font rendering for the frame count is provided by a third unit that is a wrapper for the FreeType version 1 Pascal source code, which can render text directly into the image buffer by scan-lines.  All of these units are in an experimental state, and they will need considerable testing and extending before being usable in finished applications.  However, as a proof of concept they are very encouraging.  The code repository can be found here:

https://bitbucket.org/PaulFMichell/compactimages

Grid InQuest II Visual C Example

Thanks to a contribution from Shane MacLaughlin of Atlas Computers Ltd. There is now a Windows Visual C++ example available for calling the Grid InQuest II dynamic link library.  This is uploaded to the repository source tree in the Examples/C folder along with a GCC example that I have added for calling Linux shareable objects:

Grid InQuest II Bitbucket Source

If any body else adds additional language wrappers, let me know and I will add them into the repository as well.

Grid InQuest II Launched Today!

Today sees the official launch of Ordnance Survey’s new geoid model OSGM15.  This is to replace their previous model OSGM02 that has been the cornerstone of the British National Grid coordinate system since 2002.  The new model is both a refinement of the accuracy and an increase in the model’s extent to cover offshore bathymetry.

As a consequence it will now be used to refine the definition of the British National Grid, the Irish Grid and the Irish Transverse Mercator map projections.  To accompany this Ordnance Survey, along with Ordnance Survey Ireland and the Land and Property Services of Northern Ireland, commissioned me to re-write their popular Grid InQuest software to serve as a reference implementation for this new system.

GIQ2

The new software is written in Free Pascal and there are binaries available for Linux, Windows and Mac OSX.  Moreover, the software is released under an open source licence so the entire project repository is available on Bitbucket here:

https://bitbucket.org/PaulFMichell/gridinquestii

If any one is interested in more details about what the software can do a digital manual is also available for download here:

https://bitbucket.org/PaulFMichell/…/GridInQuestII.pdf

Further technical data concerning the definition of OSGM15 can be found here:

OSGM15 and OSTN15 – Updated transformations for UK and Ireland

Free Pascal Fast Bitmaps (Part 2)

Whilst reading the Free Pascal mailing lists I read an interesting exchange where there was a discussion of the methods used by FPImage to store bitmap data (Questions regarding FPImage’s TFPMemoryImage.FData variable).  In this my eye was drawn to a class TFPCompactImgRGBA8Bit which was listed as using 32bits per pixel.  As covered in part one of this post, this is the magic pixel sized used by all of the fast software image handling libraries.  I was unaware that it was possible to vary the raw pixel storage in the FCL-Image library, but it turns out that the TFPCustomImage class is designed to allow the definition of descendants that can specify alternative memory allocation strategies.

The class mentioned TFPCompactImgRGBA8Bit does just this and assumes RGBA byte order within the 32bit pixel value.  Unfortunately some platforms, most notably Windows, store the colour components in a different order, BGRA to be precise, so I ideally would like a class that can adapt this order depending upon the target platform.  From this requirement was born my TCompactImage, as an adaptation of the TFPCompactImgRGBA8Bit class:

Unit CompImages;

{ FCL Compact Image Unit (c) 2016, Paul F. Michell. }

{$IFDEF FPC}
  {$ASMMODE INTEL}
  {$MODE OBJFPC}
  {$LONGSTRINGS ON}
{$ENDIF}

Interface

Uses
  Classes, fpImage;

{$I Defines.inc}

Type
  TCompactColor = Packed Record
    {$IFDEF BGRAIMAGE}
    Blue, Green, Red, Alpha: Byte;
    {$ELSE}
    Red, Green, Blue, Alpha: Byte;
    {$ENDIF}
  End;
  TCompactColorPointer = ^TCompactColor;

  TCompactImage = class(TFPCustomImage)
  Protected
    FData: TCompactColorPointer;
    Function GetInternalColor(x, y: Integer): TFPColor; 
                                              Override;
    Function GetInternalPixel({%H-}x, {%H-}y: Integer): 
                                     Integer; Override;
    Procedure SetInternalColor (x, y: Integer; 
                      Const Value: TFPColor); Override;
    Procedure SetInternalPixel({%H-}x, {%H-}y: Integer; 
                        {%H-}Value: Integer); Override;
  Public
    Destructor Destroy; Override;
    Procedure Clear(Color: TCompactColor);
    Procedure SetSize(AWidth, AHeight: Integer); 
                                              Override;
    Property Data: TCompactColorPointer Read FData 
                                           Write FData;
  End;

Implementation

Destructor TCompactImage.Destroy;
Begin
  ReAllocMem(FData, 0);
  Inherited Destroy;
End;

Procedure TCompactImage.SetSize(AWidth, 
                                     AHeight: Integer);
Begin
  If (AWidth<>Width) Or (AHeight<>Height) Then
    Begin
      ReAllocMem(FData, 
                 SizeOf(TCompactColor)*AWidth*AHeight);
      Inherited SetSize(AWidth, AHeight);
    End;
End;

Function TCompactImage.GetInternalColor(x, 
                                 y: Integer): TFPColor;
Var
  Color: TCompactColor;
Begin
  Color := FData[x+y*Width];
  With Color Do
    Begin
      Result.Red := (Red ShL 8)+Red;
      Result.Green := (Green ShL 8)+Green;
      Result.Blue := (Blue ShL 8)+Blue;
      Result.Alpha := (Alpha ShL 8)+Alpha;
    End;
End;

Function TCompactImage.GetInternalPixel(x, 
                                  y: Integer): Integer;
Begin
  { Not used by Compact Images. }
  Result := 0;
End;

Procedure TCompactImage.SetInternalColor(x, y: Integer; 
                                Const Value: TFPColor);
Var
  Color: TCompactColor;
Begin
  Color.Red := Value.Red ShR 8;
  Color.Green := Value.Green ShR 8;
  Color.Blue := Value.Blue ShR 8;
  Color.Alpha := Value.Alpha ShR 8;
  FData[x+y*Width] := Color;
End;

Procedure TCompactImage.SetInternalPixel(x, y: Integer; 
                                       Value: Integer);
Begin
  { Not used by Compact Images. }
End;

Procedure TCompactImage.Clear(Color: TCompactColor);
Begin
  FillDWord(FData^, Width*Height, DWord(Color));
End;

End.

The key difference is the BGRAIMAGE define which enables the colour byte order to change with the target platform.  This is controlled by the ‘Defines.inc’ file:

{ Define platform specific byte order. }
{$IFDEF WINDOWS}
  {$DEFINE BGRAIMAGE}
{$ELSE} {$IFDEF LCLQT}
  {$DEFINE BGRAIMAGE}
{$ELSE}
  {$DEFINE RGBAIMAGE}
{$ENDIF}{$ENDIF}

This proves to be the base technique that fulfils my requirements of: platform portability; fast 32bit pixel access; no external dependencies; potential for headless use; integration with the FCL-Image library; and via TRawImage, the potential to integrate with LCL too.  In a future post I will upload my test program that will demonstrate a bridge to LCL and can achieve in the region of 30 frames per second of full screen updates.

 

 

Free Pascal Fast Bitmaps (Part 1)

Recently I have been looking again at the issue of generating large images for a Free Pascal program at interactive display rates. There are two scenarios where I find this useful, creating a back-buffer for graphically intensive programs such as GIS mapping or procedural graphics applications.  The second is for command-line, or server tools that can synthesise images in real-time for feeding into a web server response.

The bottlenecks encountered when developing high performance bitmap graphics are usually due to either the cost of access to individual pixels, or the transfer cost of a graphics buffer to screen or file.  For display access, the programmer is at the mercy of both the system’s desktop shell and the hardware driver.

I have come across these hurdles repeatedly in my career.  To many, the obvious solution would be to use the now ubiquitous hardware based GPU options, most likely OpenGL or OpenGLES.  Whilst they are very powerful there are two capabilities I need that are not so easy to achieve with this approach: complex polygon filling and high quality vector font rendering.  In addition, when targeting embedded systems or older hardware, these interfaces may not be available at all.

These days I also require code to be highly portable and ideally with very few external dependencies beyond the units supplied with Free Pascal and Lazarus.  In the past I have found the best results were achieved with the Graphics32 library.  Unfortunately, its development seems to have slowed of late and its support for Lazarus can be patchy. Another very useful library is BGRABitmap which was developed specifically for Lazarus and is the rendering library behind the LazPaint image editor.  This unfortunately does not compile with the current trunk compiler 3.1.1 due to changes in the UTF8 text handling, although I expect this will be fixed in due course.  Also both of these libraries are a poor choice for the sever/command-line role as they depend upon the LCL desktop interface.

There are many other graphics libraries, AggPas, Vampyre, LazRGBGraphics to name a few.  All of them share the same basic premise of handling memory images directly and optimise reading and writing pixels, but they are written from the ground up and so are not well integrated for use with the native image handling of Free Pascal and Lazarus.

So what are the native capabilities of Free Pascal and Lazarus and why have so many additional libraries been written?  The graphics library distributed with Free Pascal is called FCL-Image and it supports all of the common image file formats and provides a a memory based drawing canvas interface.  There is also the TBitmap implementation in the Lazarus Graphics unit.  This is largely compatible with Delphi’s TBitmap and uses the FCL for some of its file and drawing capabilities.  Unfortunately, both libraries are very slow in use compared to the third party libraries mentioned before.  The fundamental reason for this is due to the FCL library abstracting pixel representation as a 64bit quantity.  Whilst this provides superior colour accuracy, for more common place 32bit colour depths, it comes at the cost of requiring per pixel conversion between the two colour forms.  This conversion overhead is especially noticeable for large images being transferred to files or the screen.

I have attempted to use FCL-Image on a couple of occasions but ended up rejecting the solution because I couldn’t get the performance to an acceptable level for my application.  In both cases, I found myself wishing in frustration that I could use the 32bit techniques of the other libraries within the FCL.  As it happens, I have now discovered that you can and that will be the subject of my next post!

 

Windres Installation on Linux

I have recently updated my Linux desktop to Kubuntu 16.04.  In the main this has been a painless and positive experience.  One small problem was caused by the loss of my old hand-built Linux resource compiler.  This is used by Lazarus to generate Windows style resources that I need for embedding data files in cross-platform applications.

As I can’t now remember how I built the utility on 15.04, I started researching the simplest way to get a working resource compiler for 16.04.  Fortunately, it turns out that there is a cross-compiling package available in the Ubuntu Universal repository that contains a binary clone of windres.  This package can be installed by:

sudo apt-get install mingw-w64

In this package the required program is named x86_64-w64-mingw32-windres.  Lazarus looks for an executable simply called windres.  So to enable Lazarus to find this, I created a symlink to the file with the following command:

sudo ln -s /usr/bin/x86_64-w64-mingw32-windres /usr/bin/windres

Now Windows ‘rc’ files can be automatically processed by Lazarus during build commands just as they would be when working on a Windows host.

Natural Earth Data

For a recent project I needed to produce a globe display, similar to Google Earth. However, it needed to be completely embedded and not require an active internet connection.  To keep it compact, I wanted a good quality vector dataset for national boundaries.  It needed to be under a liberal licence so that I could modify it if needed.  It also had to be free from any licence tracking requirements and permit distribution with my application.

Fortunately my research lead me to discover the Natural Earth project.  It contains exactly what I needed and more besides, in both vector and tiled raster formats.  It is released into the public domain and so its reuse is completely unrestricted.

In the 1:10M cultural vector data is an 8.2Mb shape file containing country multi-polygons:  ne_10m_admin_0_countries.shp.  With line simplification this could be reduced to just under 1Mb as Well Known Text and when Z compressed reduced further to 334Kb. This was then directly linked as a resource file into the application.  The built test program itself was 2.5Mb (Linux 64bit GTK2) with no additional external dependencies.

Globe

So if you need good quality global mapping data, supplied under liberal licensing terms, I strongly recommend that you investigate the Natural Earth website.