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