C ++ Having multiple graphical options

Currently, my application uses only Direct3D9 for graphics, but in the future I plan to expand it to D3D10 and, possibly, OpenGL. The question is, how can I do this neatly?

There are currently various rendering methods in my code

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

Then the function passed depends on the exact state, for example MainMenu-> Render, Loading-> Render, etc. Then they will call methods of other objects.

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

And a class sample derived from 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(); }; 

Each method then takes care of how best to display data with more detailed settings (for example, pixel shaders are supported).

The problem is that I'm really not sure how to extend this to be able to use one of which may be slightly different (D3D v OpenGL modes) ...

+4
source share
2 answers

Define an interface sufficient for the graphics requirements of the application. Then implement this interface for each rendering that you want to support.

 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 }; 

Proper design and maintenance of these interfaces can be very difficult.

If you also work with driver-dependent objects, such as textures, you can use the factory template so that individual renderers create their own implementation, for example. ITexture using factory method in 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); } //... }; 

Isn't it an idea to look at existing (3d) engines? In my experience developing these kinds of interfaces really distracts from what you really want to do :)

+6
source

I would say if you want to really complete the answer, look at the source code for Ogre3D . They have both D3D and OpenGL . Take a look: http://www.ogre3d.org Basically, their API type makes you work in D3D-ish mode, creating buffer objects and stuffing them with data, and then issuing drawing calls to these buffers. This is the way hardware likes it anyway, so this is not a bad way.

And then, as soon as you see how they do it, you can just go and use it and save yourself the need to re-implement everything that it already provides. :-)

+1
source

Source: https://habr.com/ru/post/975977/


All Articles