4 Stimmen

C++ Mit mehreren Grafikoptionen

Derzeit verwendet meine App nur Direct3D9 für die Grafik, aber in Zukunft plane ich, dies auf D3D10 und möglicherweise OpenGL zu erweitern. Die Frage ist, wie kann ich das auf ordentliche Weise tun?

Derzeit gibt es verschiedene Render-Methoden in meinem Code

void Render(boost::function &Call)
{
    D3dDevice->BeginScene();
    Call();
    D3dDevice->EndScene();
    D3dDevice->Present(0,0,0,0);
}

Die übergebene Funktion hängt dann vom genauen Zustand ab, z. B. MainMenu->Render, Loading->Render usw. Diese rufen dann oft die Methoden anderer Objekte auf.

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

Und eine Beispielsklasse abgeleitet von entity::Base

class Sprite: public Base
{
    IDirect3DTexture9 *Tex;
    Point2 Pos;
    Size2 Size;
public:
    Sprite(IDirect3DTexture9  *Tex, const Point2 &Pos, const Size2 &Size);
    virtual void Render();
};

Dann kümmert sich jede Methode darum, wie am besten basierend auf den detaillierteren Einstellungen (zum Beispiel, ob Pixelshader unterstützt wird oder nicht) gerendert werden soll.

Das Problem ist, ich bin mir wirklich nicht sicher, wie ich das erweitern kann, um einen der möglicherweise unterschiedlichen (D3D v OpenGL) Rendermodi zu nutzen...

6voto

Tobi Punkte 71004

Definieren Sie eine Schnittstelle, die für die grafischen Ausgabeanforderungen Ihrer Anwendung ausreichend ist. Implementieren Sie dann diese Schnittstelle für jeden Renderer, den Sie unterstützen möchten.

class IRenderer {
  public:
    virtual ~IRenderer() {}
    virtual void RenderModel(CModel* model) = 0;
    virtual void DrawScreenQuad(int x1, int y1, int x2, int y2) = 0;
    // ...etc...
};

class COpenGLRenderer : public IRenderer {
  public:
    virtual void RenderModel(CModel* model) {
      // Modell mit OpenGL rendern
    }
    virtual void DrawScreenQuad(int x1, int y1, int x2, int y2) {
      // Bildschirmausgerichtetes Quadrat mit OpenGL zeichnen
    }
};

class CDirect3DRenderer : public IRenderer {
  // ähnlich, aber mit Direct3D rendern
};

Es kann jedoch sehr herausfordernd sein, diese Schnittstellen angemessen zu entwerfen und zu pflegen.

Falls Sie auch mit rendernden treiberabhängigen Objekten wie Texturen arbeiten, können Sie ein Fabrikmuster verwenden, um die separaten Renderer jeweils ihre eigene Implementierung von z.B. ITexture mit einer Factory-Methode in IRenderer erstellen zu lassen:

class IRenderer {
  //...
    virtual ITexture* CreateTexture(const char* filename) = 0;
  //...
};

class COpenGLRenderer : public IRenderer {
  //...
    virtual ITexture* CreateTexture(const char* filename) {
      // COpenGLTexture ist die OpenGL-spezifische ITexture-Implementierung
      return new COpenGLTexture(filename);
    }
  //...
};

Ist es trotzdem eine Idee, sich bereits existierende (3D-)Engines anzusehen? Meiner Erfahrung nach lenkt das Entwerfen solcher Schnittstellen wirklich von dem ab, was Sie eigentlich machen möchten:)

0 Stimmen

Da ich bereits alles, was ich brauche, für den d3d9 habe, möchte ich einfach die Möglichkeit haben, auf andere APIs zu erweitern. Da ich bereits Klassen habe, die die meisten d3d-Funktionen umhüllen (z.B. Texture, Sprite, Mesh), könnte ich diese einfach überladen und die tatsächlichen Objekte mit API-unabhängigen Funktionen belassen.

1voto

Baxissimo Punkte 2610

Ich würde sagen, wenn du wirklich eine vollständige Antwort haben möchtest, schau dir den Quellcode von Ogre3D an. Sie haben sowohl D3D als auch OpenGL Backends. Schau hier: http://www.ogre3d.org Grundsätzlich zwingt dich ihre API irgendwie dazu, auf D3D-ähnliche Weise zu arbeiten, indem du Puffer erstellst und sie mit Daten füllst und dann Aufrufe auf diese Puffer machst. Das ist sowieso so, wie es die Hardware mag, also ist es kein schlechter Weg.

Und sobald du siehst, wie sie die Dinge machen, könntest du genauso gut einfach weitermachen und es nutzen und dir die Mühe sparen, all das, was es bereits bietet, neu zu implementieren. :-)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X