2

現在、エンジン用の Direct3D レンダラーを作成しています。

ここに問題があります
。OpenGL では、簡単glClearColor()に clear を呼び出すことができます。
Direct3D では、clearg_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

私の質問は、この問題を解決するための最良のアプローチは何ですか? グローバル変数、シングルトン クラス、または単にクラスを関数に渡すことを考えています。

4

3 に答える 3

3

まず、g_pd3dDevice がグローバルではないことに気付きます。これは、デバイス ID3D10Device* の COM インターフェイスへのクラス メンバー ポインターであり、ここではグローバルではなく、そうすべきでもありません。

そして、あなたの質問にできるだけ簡単に答えるために (初心者のエンジン/フレームワーク設計の問題のように思えるため)、ポインターをさらに渡すことができる作業デバイスへのポインターを返すアクセサー メソッドを提供します。

2 階の小さな「仕様」に準拠するための簡単な例:

class Direct3DWin32 : public Renderer
{
      ID3D10Device* pD3DDevice;
  public:
      ID3D10Device* getD3DDevice();

}

これで、必要なときはいつでも、Direct3DWin32 インスタンスから取得するときに関数を介して渡すことができます。エンジン設計にはこれ以外にも多くのことがあり、個人的にはこれを進むべき道としてはお勧めしませんが、それはまた別の機会に、おそらく一連の本の話になります。

ノート!

基本的なものはこのように定義できますが、複数のレンダリング パスの設計を適切なレベルにまで引き上げたい場合は、適切なレベルの抽象化を追加してポリモーフィズムを導入する必要があります。次に、DirectX または OpenGL レンダリング パスが現在使用されているかどうかにかかわらず、正しいことを行う統合レンダリング インターフェイスを定義し、派生クラスをインスタンス化し、指定されたインターフェイスすべてを含む抽象基本クラスへのポインターにそのアドレスを与えることができます。に準拠します。次に、基本的な API の選択に気づかずにレンダリングできます。

うまくいけば、これで現在の問題が解決します。また、グローバルを回避します。そしてハッピーコーディング。

于 2012-06-27T17:04:44.383 に答える
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);
   }
}

(私は「ゲッター」の大ファンではありません。)

于 2012-06-27T17:16:13.503 に答える
0

別のクラスに渡したい変数のアクセサ メソッドを提供する必要があります。

たとえば、Direct3dWin32 では、次のようにすることができます。

ID3d10Device* get_gpd3Device()
{
    return g_pd3Device;
}

次に、これを OpenGLWin32 に渡すことができます。

void useDevice (ID3d10Device* aDevice)
{
// do work
}

両方のクラスを使用するアプリケーションには、ギャップを埋める責任があります。

OpenGLWin32 openGL;
openGL.useDevice(direct3d.get_gpd3device());
于 2012-06-27T16:57:13.027 に答える