2008-09-13 4 views
4

В настоящее время мое приложение использует только Direct3D9 для графики, однако в будущем я планирую расширить его до D3D10 и, возможно, OpenGL. Вопрос в том, как я могу сделать это аккуратно?C++ Наличие нескольких графических опций

В настоящее время существуют различные методы визуализации в моем коде

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

функция передается затем зависит от конкретного состояния, например MainMenu-> Render, Loading-> Render и т.д. Они будут затем oftern называют методы других объектов.

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

А класс образец, полученный от предприятия :: Base

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

Каждый метод затем заботится о том, как лучше, чтобы сделать, учитывая более детальные настройки (например, поддерживаются пиксельные шейдеры или нет).

Проблема заключается в том, что я действительно не знаю, как расширить это, чтобы иметь возможность использовать один из, что может быть несколько иной (D3D v OpenGL) режимах рендеринга ...

ответ

6

Определить интерфейс, который является достаточным для требований графического вывода вашего приложения. Затем реализуйте этот интерфейс для каждого рендеринга, который вы хотите поддержать.

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) { 
     // render model using OpenGL 
    } 
    virtual void DrawScreenQuad(int x1, int y1, int x2, int y2) { 
     // draw screen aligned quad using OpenGL 
    } 
}; 

class CDirect3DRenderer : public IRenderer { 
    // similar, but render using Direct3D 
}; 

Правильное проектирование и обслуживание этих интерфейсов может быть очень сложным.

Если вы также работаете с объектами, зависящими от визуализации, такими как текстуры, вы можете использовать шаблон фабрики, чтобы отдельные средства визуализации создавали собственную реализацию, например. ITexture используя фабричный метод в IRenderer:

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

class COpenGLRenderer : public IRenderer { 
    //... 
    virtual ITexture* CreateTexture(const char* filename) { 
     // COpenGLTexture is the OpenGL specific ITexture implementation 
     return new COpenGLTexture(filename); 
    } 
    //... 
}; 

Разве это не идея, чтобы посмотреть на существующие (3D) двигателей, хотя? По моему опыту разработки такого рода интерфейсов действительно отвлекает от того, что вы на самом деле хотите сделать :)

+0

Поскольку у меня уже есть материал d3d9 для всего, что мне нужно, я просто хочу, чтобы этот вариант распространялся на другие API. Поскольку у меня уже есть классы, обертывающие большинство материалов d3d (например, Texture, Sprite, Mesh), я мог бы просто перегрузить их, оставив объекты actaul с API-интерфейсом. – 2008-09-13 22:50:15

1

Я бы сказал, что если вы действительно хотите ответить на этот вопрос, посмотрите исходный код для Ogre3D. Они имеют как D3D, так и OpenGL задние концы. Посмотрите на: http://www.ogre3d.org В основном их API-интерфейс заставляет вас работать в режиме D3D-ish, создавая объекты буфера и набивая их данными, а затем выдавая призывы рисования к этим буферам. Так нравится оборудованию, так что это не плохой способ.

И как только вы увидите, как они это делают, вы можете просто просто пойти и использовать его и избавить себя от необходимости повторного внедрения всего, что он уже предоставляет. :-)

Смежные вопросы