Some time in the near future, I will begin developing a game engine. One feature that I want to include is having multiple render systems such as directx 9/10/11 and OpenGL. This way, a game using this engine will be able to support more players since if one render system doesn’t work, it will revert to a different one.
So my question, how would I go about doing this? I researched a bit and saw that Ogre3D uses something like this but I have no idea how they do it. I basically want to be able to plug in different render systems and use the same code to run it.
You could create an interface class that allows you to further extend for the API you are hoping to expand to.
I have done this in the past to create a DirectX9\11 Renderer and I am hoping to expand this to OpenGL soon. There is certainty a lot to the task, but it is easy to explain a basic working of it. Unfortunately the project I am on is closed source, so if you have any questions about this please don’t hesitate to ask.
First you will want to create a separate project to be used as a .lib/.dll, I called this “RenderInterface”. This will contain basic interfaces for VertexBuffer’s, IndexBuffer’s, Shaders, and most importantly, IRenderInterface and IRenderUtility, which in the later implementation could potentially hold items such as such as ID3D11DeviceContext and ID3D11Device.
My two most important items in the “RenderInterface” project, are IRenderInterface and IRenderUtility. The idea here is to have IRenderInterface do the heavily lifting, such as creating render targets, presenting, and initializing the API. Where as IRenderUtility will do more common things, such as creating vertex/index buffers, creating shaders and rendering. I pass IRenderUtility around more frequently on initialization and rendering, and IRenderInterface is rarely passed around. This is to prevent the users from doing accidental operations when they do not need to. This project will also include some common structs\enums that will be used throughout the code base.
I then create another project, such as D3D11RenderInterface. This D3D11RenderInterface will have the implementations of the IRenderInterface, IRenderUtlity, IVertexShader, IVertexBuffer, etc.
An overlysimple example would be
This works by having the VertexBuffer and IVertexBuffer being set by a call to IRenderUtility, before the IRenderUtility::Draw call.
Then, in your application will only need to load the RenderInterface project, and api implementation. There are other ways to do this, such as a #define’ing code throughout your code base, but imo, that is just messy.