我正在为我们的引擎编写Direct3D渲染器。
问题在于:
在OpenGL中,我可以轻松地调用glClearColor()
来清除
在Direct3D中,我需要使用g_pd3dDevice
来调用ClearRenderTargetView()
来清除。
我们引擎的设计是这样的:
class Renderer
{
// ...
}
class Direct3dWin32 : public Renderer
{
private ID3D10Device* g_pd3dDevice;
}
class OpenGLWin32 : public Renderer
{
// Nothing, I can call a function easily without relying on something
}
当我的ShaderManager
类想要编译着色器时,问题就出现了。我需要使用g_pd3dDevice
类上的Direct3dWin32
。
我的问题是,解决这个问题的最佳方法是什么?我正在考虑全局变量,单例类,或者只是在函数中传递类。
答案 0 :(得分:3)
首先,我不禁注意到g_pd3dDevice,这不是全球性的。它是指向设备COM接口ID3D10Device *的类成员指针,它不是全局的,也不应该是全局的。
为了尽可能简单地回答你的问题(因为它似乎是一个初学引擎/框架设计问题),提供一个访问器方法,它返回一个指向工作设备的指针,从中可以进一步传递它,它需要它受雇。
符合你楼上的小“规范”的一个简单例子:
class Direct3DWin32 : public Renderer
{
ID3D10Device* pD3DDevice;
public:
ID3D10Device* getD3DDevice();
}
现在,只要你需要它,当你从Direct3DWin32实例获取它时,你可以通过函数传递它。发动机设计还有很多比这更多的内容,我个人不会推荐这个作为一条路径,但这是另一个时间的故事,也许是一系列的书籍。
你可以定义这样的基本内容,但是如果你真的想要将多个渲染路径设计放到适当的级别,你将不得不引入多态,添加一个很好的抽象级别。然后你可以简单地定义一个统一的渲染界面,它将做正确的事情,无论是当前使用的是DirectX还是OpenGL渲染路径,实例化派生类并将其地址提供给指向其包含指定接口的抽象基类的指针符合。然后,您可以无视渲染API的基础选择。
希望这可以解决您当前的问题。同样,再次避开全局变量。并且编码很快。
答案 1 :(得分:1)
您可以使用双重调度的变体(例如访客模式):
class ShaderManager
{
public:
void compileShader(Renderer* r, Shader* s) { r->compileShader(this, s); }
void compileD3DShader(ID3D10Device* device, Shader*s);
void compileGLShader(Shader* s);
};
class Renderer
{
public:
virtual void compileShader(ShaderManager* m, Shader* s) = 0;
};
class Direct3dWin32 : public Renderer
{
private:
ID3D10Device* m_device;
public:
virtual void compileShader(ShaderManager* m, Shader* s)
{
m->compileD3DShader(m_device, s);
}
}
class OpenGLWin32 : public Renderer
{
public:
virtual void compileShader(ShaderManager* m, Shader* s)
{
m->compileGLShader(s);
}
}
(我不是“吸气鬼”的忠实粉丝。)
答案 2 :(得分:0)
您应该为要传递到另一个类的变量提供访问器方法。
例如,在Direct3dWin32中,您可以:
ID3d10Device* get_gpd3Device()
{
return g_pd3Device;
}
然后您可以将其传递给OpenGLWin32:
void useDevice (ID3d10Device* aDevice)
{
// do work
}
使用这两个类的应用程序将负责缩小差距:
OpenGLWin32 openGL;
openGL.useDevice(direct3d.get_gpd3device());