antonijn's picture

Pencil.Gaming - The OpenTK Alternative

So I, like many others, am in a love-hate relationship with OpenTK. I love its OpenGL support, but am fed up with three things:

  • The windowing implementation
  • The necessity to install the OpenAL redistributable package
  • A more temporal issue: the lack of updates recently

I believe that the second two points are relatively straightforward, but the first bullet deserves an explanation.
it
The OpenTK windowing API has been written entirely independent of any other windowing APIs, like FreeGLUT and GLFW. This means that it is really buggy in some places, especially on non-windows platforms, and the users of the library should not have to fix these things themselves.

That is why I decided to write my own library, which relies on a well-established native windowing library: GLFW, providing way more stability than OpenTK now does (full rationale can be found here).

It's by no means designed to be backwards-compatible with OpenTK (although it won't require a lot of work to change your application). A few notable differences:

  • It's designed to be a library used only for games
  • Half-precision floating point numbers, and their implementations in Vector2h etc., have been removed
  • Double precision matices and vectors have been removed
  • There's no need for ANY redistributable packages
  • It provides some utility classes for GLFW and OpenAL: Glfw.Utils and Al.Utils respectively

Features that are still there:

  • It's 100% cross-platform
  • It provides support for OpenGL and OpenAL
  • It has strongly typed enums
  • It has the MIT license

The most notable difference is the GLFW implementation. Have a look at the tutorials on their site to find out more about it.

The github repository, including the source code, the binaries, a list of compatible platforms and a sample program, can be found here.

This is the sample program provided by the github repo, so you don't have to click the link to see it...

using Pencil.Gaming;
using Pencil.Gaming.Audio;
using Pencil.Gaming.Graphics;
using Pencil.Gaming.MathUtils;
 
class Program {
    private static void Main(string[] args) {
        try {
            Glfw.Init();
 
            try {
                Glfw.OpenWindow(800, 600, 8, 8, 8, 8, 24, 0, WindowMode.Window);
                Glfw.SetWindowTitle("Sample application");
                Glfw.SwapInterval(false);
 
                Glfw.SetWindowSizeCallback((int width, int height) => {
                    GL.Viewport(0, 0, width, height);
 
                    GL.MatrixMode(MatrixMode.Projection);
                    GL.LoadIdentity();
                    GL.Ortho(0.0, 1.0, 1.0, 0.0, 0.0, 1.0);
                    GL.MatrixMode(MatrixMode.Modelview);
                });
 
                Glfw.SetTime(0.0);
                do {
                    float deltaTime = (float) Glfw.GetTime();
                    Glfw.SetTime(0.0);
 
                    GL.ClearColor(Color4.White);
                    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
                    GL.Begin(BeginMode.Triangles);
                      GL.Color4(Color4.Red);
                      GL.Vertex2(0.1f, 0.1f);
                      GL.Color4(Color4.Green);
                      GL.Vertex2(0.1f, 0.9f);
                      GL.Color4(Color4.Blue);
                      GL.Vertex2(0.9f, 0.9f);
                    GL.End();
 
                    Glfw.SwapBuffers();
                    Glfw.PollEvents();
                } while (Glfw.GetWindowParam(WindowParam.Opened) == 1);
            } finally {
                Glfw.CloseWindow();
            }
        } finally {
            Glfw.Terminate();
        }
    }
}

NOTE: This example is for GLFW2, make sure to compile it as such

And here is another example (once again from the github repo), this time OpenAL, showing one of the nifty utilities.

uint buffer = AL.Utils.BufferFromWav("MyWaveFile.wav");
uint source;
AL.GenSources(1, out source);
 
AL.Source(source, ALSourcei.Buffer, (int) buffer);
AL.Source(source, ALSourceb.Looping, true);
 
AL.SourcePlay(source);
 
// ...
// ...
 
// When cleaning up:
AL.DeleteSources(1, ref source);
AL.DeleteBuffers(1, ref buffer);

Feedback and contributions to the git repo would be much appreciated!


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
antonijn's picture

@Mailaender I understand that this is not what you were looking for, but this is the only solution I could think of without having to install anything whatsoever.

The library pretty much checks during runtime whether the process is 64-bit, and selects the proper delegates accordingly.

Mailaender's picture

We try to detect if the sound card driver already provide OpenAL and if not automatize the download of the distributable installer for Windows with NSIS https://github.com/OpenRA/OpenRA/blob/bleed/packaging/windows/OpenRA.nsi... This will fail if the creativelabs servers are down however so you might want to mirror it yourself. On Linux it is much easier, simply require openal-soft as a dependency in the packages and you are done.

antonijn's picture

@Mailaender Thanks for the advice, although I don't think I'll implement it right now (or at least not right away), I think I prefer the method I currently use.

Mailaender's picture

If you distribute your game on http://desura.com/ it will automatically get .NET and OpenAL silently for Windows users.