1

OpenGL 3.1 用のレンダリング システムの設計に取り組んでいます (現在は 2D のみに限定されています)。私がやりたいのは、エレガントなデザインパターンについて本当に考えて、保守とデバッグが面倒なハッキングされた混乱を心配する必要がないようにすることです.

最初は、さまざまな型名を引数として受け入れる関数を持つテンプレート化された基本クラスを持つという方針に沿って何かを考えていました。子クラスは基本クラスから継承し、派生時にテンプレート引数として使用する型を送信します。

それから、これは基本的に不可能であることがわかりました

ですから、ハッキングするだけでなく、これを適切に設計する方法について、私は少し行き詰まっています。問題は、ベクトル クラスをラップする独自の頂点構造を使用しているglmため、構造内に頂点ペアを持ち、呼び出し時にメモリ オフセットを使用してそれらをまたぐことができることglVertexAttribPointer()です。

言い換えると、

typedef struct colorVertex_d
{
    glm::vec3 Position;
    glm::vec4 Color;
}
colorVertex_t;

typedef struct textureVertex_d
{
    glm::vec3 Position;
    glm::vec2 UV;
}
textureVertex_t;

理想的には、この Renderer で使用できる実際のタイプを定義済みの頂点タイプに制限することです。

これを行う1つの方法は、 thisの行に沿って何かを実行し、クラスに送信された型が有効でない場合に Shutdown メソッド(例外のようなもので、例外ではありません...)を呼び出すことでした。

それでも、これがこのコンテキストで適切な実装と見なされるかどうかはわかりません。

私が本当に探しているのは、上記の頂点構造のような型に準拠する複数のバッファー型 (頂点、インデックス、法線、色など) をサポートできる手段です。

元のソース

/**
  * Is an abstract class to inherit from for defining custom buffer handler classes,
  * the type name specified is the type of data stored in the buffer specifically, e.g. textureVertex_t or colorVertex_t
  */

template < typename DataT, typename ContainerT >
class RenderBuffer
{
public:
    enum RenderMethod
    {
        Stream,             // used for writing data into the buffer once per render
        Dynamic,            // values in the buffer are changed from time to time
        Static              // data is set only once, then rendered as many times as it needs to be
    };

    enum DrawMode
    {
        Triangle,
        TriangleStrip,
        Line,
        LineStrip
    };

    enum BufSetType
    {
        Alloc,
        Update
    };

    RenderBuffer( RenderMethod rm, DrawMode dm )
    {
        switch( rm )
        {
        case Stream:    mRenderMethod = GL_STREAM_DRAW;     break;
        case Dynamic:   mRenderMethod = GL_DYNAMIC_DRAW;    break;
        case Static:    mRenderMethod = GL_STATIC_DRAW;     break;
        }

        switch( dm )
        {
        case Triangle:      mDrawMode = GL_TRIANGLES;       break;
        case TriangleStrip: mDrawMode = GL_TRIANGLE_STRIP;  break;
        case Line:          mDrawMode = GL_LINES;           break;
        case LineStrip:     mDrawMode = GL_LINE_STRIP;      break;
        }
    }

    virtual ~RenderBuffer( void )
    {
    }

    virtual void Reserve( size_t sz ) = 0; // Reserve space for whatever container used to store the buffer data.

    virtual void Bind( void ) const = 0;

    virtual void UnBind( void ) const = 0;

    template < typename DataT, ContainerT >
    virtual void SetBufferData( const ShaderProgram& program, const ContainerT& data, BufSetType m )
    {
    }

    template < typename DataT, ContainerT >
    virtual void SetBufferData( const ShaderProgram& program, const DataT* data, const size_t len, BufSetType m )
    {
    }

    virtual void Render( void ) const = 0;

    size_t VertexCount;

protected:
    GLenum mDrawMode, mRenderMethod;
};
4

1 に答える 1

1

たくさんのことを入力しましたが、あなたの目標や質問が何であるかはまだわかりません. OpenGL が実行できるすべてをカプセル化する1 つのオブジェクトを作成しようとしているようです。私の最初の提案は、それをしないことです。

VAO とプログラムを含み、それ自体をレンダリングする方法を知っている Mesh クラスをお勧めします。

glUseProgram(mProgramID);
glBindVertexArray(mVAO);
glDrawArrays(mDrawMode, 0, mNumPrimitives);

それがあなたが達成しようとしていることだと思います。

すべてのテンプレートではなく、サブクラスをお勧めします。セットアップには多くの作業 (および場合によっては別のサブクラス、パラメーター化された関数、またはオーバーロード) がありますが、セットアップが完了すると、レンダリングは簡単になります。

テンプレートの使用に固執している場合は、テンプレートの特殊化がギャップを埋めるのに役立つ場合があります。しかし、ここではテンプレートの適切な使用法はあまり見当たりません。あなたが彼らを押し込もうとしているように感じます.

于 2013-10-08T20:25:18.700 に答える