c ++具有多个图形选项
时间:2020-03-05 18:52:47 来源:igfitidea点击:
目前,我的应用仅使用Direct3D9进行图形处理,但是将来我打算将其扩展到D3D10以及可能的OpenGL。问题是我如何整齐地做到这一点?
目前,我的代码中有各种Render方法
void Render(boost::function<void()> &Call) { D3dDevice->BeginScene(); Call(); D3dDevice->EndScene(); D3dDevice->Present(0,0,0,0); }
然后,传递的函数取决于确切的状态,例如MainMenu-> Render,Loading-> Render等。然后,这些函数将交替调用其他对象的方法。
void RenderGame() { for(entity::iterator it = entity::instances.begin();it != entity::instance.end(); ++it) (*it)->Render(); UI->Render(); }
还有一个从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(); };
然后,每种方法都会考虑到在更详细的设置下如何最好地渲染(例如,是否支持像素着色器)。
问题是我真的不确定如何将其扩展为能够使用一种可能有所不同的(D3D v OpenGL)渲染模式...
解决方案
回答
定义一个足以满足我们应用程序的图形输出要求的接口。然后为我们要支持的每个渲染器实现此接口。
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 };
但是,正确设计和维护这些接口可能非常困难。
如果我们还使用与渲染驱动程序相关的对象(如纹理)进行操作,则可以使用工厂模式让单独的渲染器各自创建自己的实现,例如在IRenderer中使用工厂方法的iTexture:
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)引擎不是一个主意吗?根据我的经验,设计这种界面确实会分散实际意图:)
回答
我想说的是,如果我们想要一个真正完整的答案,请查看" Ogre3D"的源代码。它们都有D3D和OpenGL后端。看看:http://www.ogre3d.org
基本上,它们的API会迫使我们以D3D方式工作,创建缓冲区对象并将其填充数据,然后在这些缓冲区上发出绘图调用。无论如何,这就是硬件喜欢它的方式,所以这也不是坏方法。
然后,一旦了解了他们的工作方式,我们就可以继续使用它,而不必为自己重新实现已经提供的所有功能而省去麻烦。 :-)