CLM logo Development Blog by CLM

Abstraction is your friend

We are quite busy with adding support for additional platforms in our 2D engine/framework, Wombat. One of the biggest issues is support of rendering. Recently, the only supported renderer was OpenGL ES 1.1 (with possibility to run on full fledged OpenGL on desktop machines). Now, I’m proud to say that it also supports the same rendering capabilities with Direct3D 11 (don’t get too excited though, this is no windows game/port announcement).

What is so hard about supporting different graphic APIs? Differences in concepts and data types, at least this is my personal opinion. For example, in OpenGL texture in client code is just one GLuint, but in Direct3D it’s ID3D11Texture2D*, ID3D11ShaderResourceView* and shared ID3D11SamplerState*. How to address this? Our approach is to use handles to hide concepts and underlying data types. Handle might be simply an integer, which is mapped to proper data in the subsystem that manages it — clients have no idea what it really means.

For example, part of texture handling in OpenGL renderer might look something like this:

TextureHandle Renderer::LoadTexture(const TextureData& td)
{
    GLuint textureHandle;

    //... texture loading ...

    return textureHandleManager.Register(textureHandle);
}

void Renderer::FreeResource(TextureHandle handle)
{
    GLuint texture = textureHandleManager.Map(handle);
    glDeleteTextures(1, &texture);
    textureHandleManager.Unregister(handle);
}

void Renderer::SetTexture(TextureHandle handle)
{
    GLuint texture = textureHandleManager.Map(handle);
    glBindTexture(GL_TEXTURE_2D, texture);
}

This way client code uses only TextureHandle and there are no dependencies to OpenGL API. Need Direct3D support? Just implement the same interface and you’re done (yup, I know that this is an oversimplification).

The lesson is to avoid being API dependent, which will allow changing the underlying implementation and libraries, and that is a great deal.

No comments yet

Leave a reply