<p>Currently my app uses just Direct3D9 for graphics, however in the future I' m planning to extend this to D3D10 and possibly OpenGL. The question is how can I do this in a tidy way?</p>

<p>At present there are various Render methods in my code</p>

<pre><code>void Render(boost::function&lt;void()&gt; &amp;Call)
{
    D3dDevice-&gt;BeginScene();
    Call();
    D3dDevice-&gt;EndScene();
    D3dDevice-&gt;Present(0,0,0,0);
}
</code></pre>

<p>The function passed then depends on the exact state, eg MainMenu->Render, Loading->Render, etc. These will then oftern call the methods of other objects.</p>

<pre><code>void RenderGame()
{
    for(entity::iterator it = entity::instances.begin();it != entity::instance.end(); ++it)
        (*it)-&gt;Render();
    UI-&gt;Render();
}
</code></pre>

<p>And a sample class derived from entity::Base</p>

<pre><code>class Sprite: public Base
{
    IDirect3DTexture9 *Tex;
    Point2 Pos;
    Size2 Size;
public:
    Sprite(IDirect3DTexture9  *Tex, const Point2 &amp;Pos, const Size2 &amp;Size);
    virtual void Render();
};
</code></pre>

<p>Each method then takes care of how best to render given the more detailed settings (eg are pixel shaders supported or not).</p>

<p>The problem is I'm really not sure how to extend this to be able to use one of, what may be somewhat different (D3D v OpenGL) render modes...</p>

[{'answer_id': 60790, 'author': 'Tobi', 'author_id': 5422, 'author_profile': 'https://Stackoverflow.com/users/5422', 'pm_score': 4, 'selected': True, 'text': "<p>Define an interface that is sufficient for your application's graphic output demands. Then implement this interface for every renderer you want to support.</p>\n\n<pre><code>class IRenderer {\n  public:\n    virtual ~IRenderer() {}\n    virtual void RenderModel(CModel* model) = 0;\n    virtual void DrawScreenQuad(int x1, int y1, int x2, int y2) = 0;\n    // ...etc...\n};\n\nclass COpenGLRenderer : public IRenderer {\n  public:\n    virtual void RenderModel(CModel* model) {\n      // render model using OpenGL\n    }\n    virtual void DrawScreenQuad(int x1, int y1, int x2, int y2) {\n      // draw screen aligned quad using OpenGL\n    }\n};\n\nclass CDirect3DRenderer : public IRenderer {\n  // similar, but render using Direct3D\n};\n</code></pre>\n\n<p>Properly designing and maintaining these interfaces can be very challenging though.</p>\n\n<p>In case you also operate with render driver dependent objects like textures, you can use a factory pattern to have the separate renderers each create their own implementation of e.g. ITexture using a factory method in IRenderer:</p>\n\n<pre><code>class IRenderer {\n  //...\n    virtual ITexture* CreateTexture(const char* filename) = 0;\n  //...\n};\n\nclass COpenGLRenderer : public IRenderer {\n  //...\n    virtual ITexture* CreateTexture(const char* filename) {\n      // COpenGLTexture is the OpenGL specific ITexture implementation\n      return new COpenGLTexture(filename);\n    }\n  //...\n};\n</code></pre>\n\n<p>Isn't it an idea to look at existing (3d) engines though? In my experience designing this kind of interfaces really distracts from what you actually want to make :)</p>\n"}, {'answer_id': 69100, 'author': 'Baxissimo', 'author_id': 9631, 'author_profile': 'https://Stackoverflow.com/users/9631', 'pm_score': 1, 'selected': False, 'text': '<p>I\'d say if you want a really complete the answer, go look at the source code for <code>Ogre3D</code>.  They have both <code>D3D</code> and <code>OpenGL</code> back ends.  Look at : <a href="http://www.ogre3d.org" rel="nofollow noreferrer">http://www.ogre3d.org</a>\nBasically their API kind of forces you into working in a D3D-ish way, creating buffer objects and stuffing them with data, then issuing draw calls on those buffers.  That\'s the way the hardware likes it anyway, so it\'s not a bad way to go.  </p>\n\n<p>And then once you see how they do things, you might as well just just go ahead and use it and save yourself the trouble of having to re-implement all that it already provides.  :-)</p>\n'}]
['https://Stackoverflow.com/questions/60751', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/6266/']