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.

Leave a Reply