2012-03-02 13 views
4

OpenGLオブジェクトを独自のクラスでラップする傾向があります。 OpenGLにはバインディングという概念があります。そこではオブジェクトをバインドし、それを使って何かを行い、バインドを解除します。たとえば、テクスチャ:OpenGLオブジェクトラッパーの自動バインド

glBindTexture(GL_TEXTURE_2D, TextureColorbufferName); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000); 
glBindTexture(GL_TEXTURE_2D, 0); 

ラッピングはこのようなものになります:

texture->bind(); 
    texture->setParameter(...); 
    texture->setParameter(...); 
texture->unBind(); 

ここでの問題は、私は(バインドを避けたいということです)、およびunbind()関数、およびだけではなく、 setメソッドを呼び出すことができ、GLObjectは自動的にバインドされます。

私は、すべてのメソッドの実装でそれを行うことができます:

public void Texture::setParameter(...) 
{ 
    this.bind(); 
    // do something 
    this.unBind(); 
} 

その後、私はすべての追加方法のためにそれをしなければならないけど!より良い方法はありますか?すべてのメソッドを追加する前後に自動的に行われます。

答えて

5

多分、コンテキストオブジェクトが役立つかもしれません。この小さなオブジェクトを検討します。このオブジェクトは、現在のスコープ内で使用されて

class TextureContext { 
public: 
    TextureContext(char* texname) { 
     glBindTexture(GL_TEXTURE_2D, texname); 
    } 
    ~TextureContext() { 
     glBindTexture(GL_TEXTURE_2D, 0); 
    } 
}; 

{ 
    TextureContext mycont(textname); 
    mytexture->setParameter(...); 
    mytexture->setParameter(...); 
    mytexture->setParameter(...); 
} 

オブジェクトmycontのみスコープに住んでいるし、そのデストラクタ(それぞれアンバインドメソッドアリ)を呼び出し、自動的に一度スコープは残されます。

EDIT

たぶん、あなたは、コンストラクタで代わりにあなたのTextureインスタンスを取るためにTextureContextクラスを調整し、テクスチャをバインドする前にテクスチャ名自体を取得することができます。

+0

ユーザが連続して設定したいテクスチャが複数ある場合は、問題が発生する可能性があります。したがって、TextureContextは "0"テクスチャを設定するべきではなく、以前に使用されたテクスチャ(対応するglGet呼び出しで取得)を設定するべきです。 – SigTerm

+0

私はプロフェッショナルなOpenGL開発者ではなく、もっと一般的な(C++プログラミングの)観点から質問に答えようとしました。 – Constantinius

2

ここでの問題、)(私はバインド()とバインド解除を避けたいということです

はほとんどの場合、あなたは完全にそれらを取り除くことができません機能します。

あなたはそれを行うべきではありません、あなたのために:glTexImage2Dは、私はちょうどすべてのメソッドの実装でそれを行うことができます(場合DirectXのスタイルの名前wnatロックを解除/またはロック)

をバインド/アンバインドが必要になります大規模なパフォーマンス低下が起こります。私が正しく覚えていれば、それは "州の掃除"と呼ばれています。複数のパラメータを変更する必要がある場合は、すべてを一度に変更する必要があります。バインド/バインドを頻繁に呼び出すことは非常に効率が悪く、私が見たパフォーマンスガイドライン(DirectX SDK、nvidiaドキュメント、ランダムGDCペンなど)ではお勧めできません。

もっと良い方法があるので、すべてのメソッドを追加する前後に自動的に行われますか?

はい、あります。複数の状態変更をキャッシュし、実際にOpenGLコールが必要になるまで遅延させます。

I.e.プログラムがMinフィルタ、Magフィルタ、wrap_s、wrap_t、その他のパラメータをglTexParameterに設定し、テクスチャが現在のtexutreステージにバインドされていない場合は、パラメータを設定しないでください。それらを内部リスト(この特定のテクスチャ内)に格納し、次にテクスチャがバインドされるときにそれらをすべて一度に設定します。リストが特定のサイズに達したとき、またはユーザーがglGetTexParameterを呼び出したとき。パラメータを設定し、テクスチャをバインドし、パラメータを設定し、必要に応じてバインドを解除します。時間は、テクスチャの状態を変更することに費やさ

  1. は、ビット予測不可能になる可能性があります:

    しかし、このアプローチには2つの潜在的な問題があります。 (正確な実際のOpenGL calがいつ実行されるかはわかりません)。

  2. この方法を使用してOpenGLエラーを検出するのは難しいかもしれません。
  3. 内部リストが動的に割り当てられたメモリを使用し、new/deleteを頻繁に呼び出すと、new/deleteへの呼び出しが遅くなる可能性があるため、ボトルネックが発生する可能性があります。これは、その内部リストに固定サイズの循環バッファを使用することで解決できます。
1

私は自分のクラスでOpenGLオブジェクトをラップする傾向があります。

男は医者に行き、「このように私の腕を上げるときはいつも痛い」と言う。医者はこう言います。「それでは、あなたの腕を上げるのを止めてください。

問題は、ではないオブジェクトベースのインターフェイスをオブジェクトベースで提供しようとしていることです。それは涙や痛みで終わるだけです。

あなたの抽象化のレベルを上げるのがはるかに良い解決策です。 OpenGLオブジェクトを直接ラップする代わりに、グラフィックスAPIをラップします。 OpenGLテクスチャオブジェクトを格納する「テクスチャ」のいくつかの外部概念があるかもしれませんが、そのテクスチャのパラメータを直接変更する関数は公開しません。または間接的にさえ。

あなたのAPIで約束しないでください。抽象化を、外部コードが単にテクスチャのフィルタリングモードと他のパラメータが何を気にしないかという点まで引き上げる。

また、フィルタリング(およびラッピング)をオブジェクトのコンストラクタの一部にすることもできます。作成時に固定値が設定されます。

関連する問題