To do this, you have interfaces for all your API-specific objects (renderer, mesh, texture, etc.). ProgramProgram all your high-level code (like models, lights, materials) to these interfaces. Now
// The renderer interface.
// Your game code should work with this and not the concrete implementations.
class IRenderer
{
public:
virtual void Render() = 0;
};
Now, write concrete implementations for these interfaces, one implementation per API.
// The Direct3D 11 renderer.
class D3DRenderer : public IRenderer
{
public:
virtual void Render()
{
// Clears the screen.
context->ClearRenderTargetView(renderTargetView, { 0.0f, 0.5f, 1.0f, 1.0f });
// Render the rest of the scene...
}
private:
ID3D11DeviceContext *context;
ID3D11RenderTargetView *renderTargetView;
// Other API-specific data...
};
// The OpenGL renderer.
class OpenGLRenderer : public IRenderer
{
public:
virtual void Render()
{
// Clears the screen
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render the rest of the scene...
}
};
// The abstract factory.
class IEngineFactory
{
virtual IRenderer *CreateRenderer() = 0;
};
// The D3D11 factory.
class D3DEngineFactory
{
virtual IRenderer *CreateRenderer()
{
return new D3DRenderer();
}
};
// The OpenGL factory.
class OpenGLEngineFactory
{
virtual IRenderer *CreateRenderer()
{
return new OpenGLRenderer();
}
};