あなたの質問に完全に答えるには、私はテキストの壁を書かなければならないでしょう.私は最も重要な側面だけを指摘しようとします. これがあなたの知識を十分に活用し、おそらくさらに読んでそれを機能させるのに役立つことを願っています.
すべての変更は、OpenGL を初期化するクラスから行われます
オブジェクトのメソッドをカプセル化して、メインループで呼び出すことができupdate(time)
ます。draw()
電話する必要がありglEnableVertexAttribArray(1);
ますglDrawArrays(GL_POINTS, 0, 3);
か? 他に何がありますか?
すべてのパーティクルを 1 つの頂点配列に配置して、各パーティクルの後に異なる頂点配列が再バインドされるのを回避します。次に、 draw() 呼び出しでglBindVertexArray(vaid);
andを使用する必要があります。glDrawArrays(GL_POINTS, 0, vertexCount);
注意してくださいvertexCount
、それはフロートの数ではありません(あなたの質問が暗示しているように)が、あなたの例では1である必要がある頂点の数、または私の提案したアプローチでは粒子の数です(私が正しければ3
、 「私の頂点の x、y、および z」)。
また、粒子しかないので、glDrawElements(...);
おそらくすでにニーズに合っているでしょう。
OpenGL をインスタンス化し、メイン ループを処理した後で、パーティクルを制御するクラスをインスタンス化するのは正しいですか?
おそらく、インスタンス化の順序はそのように正しいでしょう。あなたの場合、メインループを呼び出す前に、すべてのインスタンス化を確実に行う必要があります。
パーティクルが以前に描画された位置を消去しながら、パーティクルが自分自身を描画するようにするにはどうすればよいですか?
最後の質問を正しく理解している場合: バッファ オブジェクト ( glBufferData(...);
) の要素を変更するだけです。各ループの後に画面をクリアしてバッファーをスワップするため、バッファーが移動します。update(time)
呼び出しで位置を更新するだけです。たとえばpos = pos + dir * time;
、新しい位置をバッファに入れ、そのバッファをglBufferData(...)
頂点配列にプッシュします。バッファをプッシュする前に頂点配列をバインドすることを忘れないでください。
私が指摘したいいくつかの追加事項。
glEnableVertexAttribArray(1);
シェーダー プログラムの頂点属性を有効にして、その属性にデータを渡すことができるようにすることです。シェーダー プログラムを作成する必要があります。
id = glCreateProgram()
// ... create and attach shaders here
// then bind attribute locations, e.g. positionMC
glBindAttribLocation(id, 0, "positionMC");
glLinkProgram(id);
頂点配列を初期化した後glGenVertexArrays();
、シェーダー プログラムで頂点配列に必要なすべての属性を有効にする必要があります。この例positionMC
ではロケーション 0 になるため、次のように呼び出します。
glUseProgram(pid);
glBindVertexArray(vaid);
glEnableVertexAttribArray(1);
glVertexAttribPointer(...);
OpenGL は特定の頂点配列ごとに状態を格納するため、これは 1 回だけ実行する必要があります。頂点配列を再バインドすると、その状態が復元されます。
メイン ループでは、更新メソッドと描画メソッドを呼び出すだけです。次に例を示します。
handleInputs();
update(deltaTime);
glClear(...);
draw();
swapBuffers();