私は OpenGL の学習を始めたので、C っぽいコードの過度の使用によって明らかに引き起こされている吐き気を避けるために、(自分用に) 小さな C++ フレームワークを作成したほうがよいと考えました。:)
私は Qt に固執するつもりなので、フレームワークはいくつかの Qt クラスを使用します。
最初に本当に必要だったのは、シェーダーとプログラムを簡単に使用する方法でした。これがシェーダークラスの私の考えです。
class Shader
{
public:
//create a shader with no source code
explicit Shader(GLenum shaderType);
//create a shader with source code and compile it
Shader(GLenum shaderType, const QString& sourceCode);
//create a shader from source file and compile it
Shader(GLenum shaderType, QFile& sourceFile);
~Shader();
//change the source code and recompile
void Source(QFile& sourceFile);
void Source(const QString& sourceCode);
GLuint get() const; //get the handle
private:
//common part for creation in different constructors
void createShader(GLenum shaderType);
//compile
void compile();
private:
GLuint handle;
};
さまざまな機能が何をしているかは明らかです。それぞれが関連する OpenGL ルーチンを呼び出し、エラーをチェックし、エラーが発生した場合は例外をスローします。コンストラクターは を呼び出しますglCreateShader
。今、トリッキーな部分です。デストラクタを呼び出す必要がありますglDeleteShader(handle);
が、この場合、ジレンマがあります。
オプション 1:割り当てとコピーを無効にします。これには、参照カウントを回避するという利点と、共有ポインタを使用してこれらをベクトルに配置し、一般的に渡す必要があるという欠点があります。
オプション 2:参照カウントを有効にします。これには、コピーを有効にして、コンテナーに格納できるという明らかな利点があります (後で、さまざまなシェーダーをプログラムに渡す必要があります)。欠点は次のとおりです。
Shader s1(GL_VERTEX_SHADER, QFile("MyVertexShader.vp"));
Shader s2(s1);
s2.Source(QFile("MyOtherVertexShader.vp"));
ご覧のとおり、s1 のソースを s2 経由で変更しました。これらは同じ内部シェーダー ハンドルを共有しているためです。正直なところ、ここでは大きな問題は見られません。私はクラスを書いたので、そのコピーセマンティクスがこのようなものであることはわかっており、問題ありません。問題は、この種の設計が受け入れられるかどうか確信が持てないことです。これはすべて Option1 + 共有ポインターで実現できますが、シェーダーを作成するたびに共有ポインターを持ちたくないという唯一の違いがあります (パフォーマンス上の理由ではなく、構文上の利便性のためです)。
Q1:オプションと、必要に応じてアイデア全体についてコメントしてください。1
Q2:オプション 2 を選択した場合、それを自分で実装する必要がありますか? または、boost または Qt に、派生またはメンバーを持つ準備ができたクラスがあり、無料の参照カウントを取得できますか?
Q3:Shader
抽象クラスを作成し、3 つの派生クラスVertexShader
、FragmentShader
、およびGeometryShader
を作成するのはやり過ぎだということに同意しますか?
1私に既存の C++ OpenGL フレームワークを紹介してくれるなら、それは非常に良いことですが (私は実際に見つけたことがなかったので)、それは私の質問への回答というよりは補足的なものにすべきです。また、ドキュメントのどこかに QGLShader クラスを見たことがありますが、私のバージョンの Qt には明らかに存在せず、今すぐアップグレードを避ける理由があります。
アップデート
答えてくれてありがとう。最終的に、ソース関数を削除して、シェーダー クラスを不変にすることにしました。シェーダーは作成時にコンパイルされ、const 以外のメンバー関数はありません。したがって、単純な参照カウントは、すべての問題を一度に解決します。