私はAndroid上でOpenGL ES 2.0を使用していますが、この質問は一般的なOpenGLの質問です。glVertexAttribPointerとglEnableVertexAttribArrayの有効範囲は何ですか?
私はOpenGLを学んだし、一度だけに対して、APIはフレームごとに呼ばれるように持っている正確に理解しようとしています。私は当初、毎フレームglVertexAttribPointer
とglEnableVertexAttribArray
を呼び出していましたが、テストプログラムを変更してShaderプログラムごとに呼び出すようにしたとき、私は期待した動作ではありません。
glVertexAttribPointer
とglEnableVertexAttribArray
は、特定のShaderプログラムのコンテキスト内でのみ意味があるため、すべてのフレームではなく、一度呼び出す必要があります。これはglVertexAttribPointer
がの最初のパラメータで、glGetAttribLocation
から返され、シェーダプログラムの変数名に対応する文字列を指定するためです。したがって、データは特定のシェイダープログラムの特定の「属性」変数に関連付けられているようです。
私のテストプログラムは、異なるフラグメントシェーダソース、異なる頂点シェーダソース、glLinkProgram
などの別々の呼び出しなど、全く異なる2つのプログラムを使用して、2つの互いに素なシェイプ(三角形)をレンダリングします。予想どおり - 両方の図形が正しく描画されているのがわかります。
m_glhook.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Shape/Program 1
m_glhook.glUseProgram(m_iGlProgramId);
int iPositionLocation = m_glhook.glGetAttribLocation(m_iGlProgramId, "a_Position");
m_bfVertices.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices);
m_glhook.glEnableVertexAttribArray(iPositionLocation);
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
// Shape/Program 2
m_glhook.glUseProgram(m_iGlProgramId2);
int iPositionLocation2 = m_glhook.glGetAttribLocation(m_iGlProgramId2, "a_Position");
m_bfVertices2.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation2, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices2);
m_glhook.glEnableVertexAttribArray(iPositionLocation2);
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
次に、すべてのフレームに対して行われた呼び出しを以下のように変更しました。 m_bFirstDraw
は最初のフレームではtrue、連続するフレームではfalseです。
m_glhook.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Shape/Program 1
m_glhook.glUseProgram(m_iGlProgramId);
if (m_bFirstDraw)
{
int iPositionLocation = m_glhook.glGetAttribLocation(m_iGlProgramId, "a_Position");
m_bfVertices.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices);
m_glhook.glEnableVertexAttribArray(iPositionLocation);
}
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
// Shape/Program 2
m_glhook.glUseProgram(m_iGlProgramId2);
if (m_bFirstDraw)
{
int iPositionLocation2 = m_glhook.glGetAttribLocation(m_iGlProgramId2, "a_Position");
m_bfVertices2.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation2, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices2);
m_glhook.glEnableVertexAttribArray(iPositionLocation2);
}
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
m_bFirstDraw = false;
私は上記のコードを参照して動作が(最初のフレームのための呼び出しシーケンスがまったく同じであるため、理にかなっている)最初のフレームのすべてのために、まだ罰金であるということです。しかし、連続するフレームの場合、Shape1はShape2の頂点で描画されます。だからShape2はShape1の上に正確に描画されるので、私はShape2しか見ることができません。
は、なぜ一つのプログラムのためのデータ(形状頂点)の設定は、連続フレーム内の別のプログラムによって使用されるデータには影響を与えない...私はこれを理解する助けてください? GLSLプログラム(特に頂点シェーダは)あなたが実際に頂点ポインタでGLSLプログラムを提供しない、一般的なスロット番号に基づいて、頂点の属性を使用していますが、私は...
Answer Andonに感謝します。仕様を見ると、VAOはOpenGL ES 2.0では利用できないので、私はそれらを使うことはできません。ですから、VAOがなければ、プログラムを切り替えるたびに 'glVertexAttribPointer'と' glEnableVertexAttribArray'を呼び出す必要があります。私はすべてのフレーム(同じ順序で)を実行する複数のプログラムを持っている場合、これは効果的に私はすべてのプログラムのために、これらの関数を永遠のフレームのために呼び出さなければならないことを意味します。あれは正しいですか? –
@DavidStone:異なる頂点バッファを使用して描画する場合や、シェイダーに正しいバインディング位置に適切なデータを供給するために、属性ポインタを別の場所にマップする必要がある場合にのみ、これを行う必要があります。 –
OK私は今理解していると思います。私の2つのシェーダは、異なる頂点で動作する必要があり、同じ順序で、すべてのフレームで実行されます。したがって、その場合は、すべてのフレームに対して 'glVertexAttribPointer' **を2回**呼び出す必要があります。何らかの理由で、私が 'glGetAttribLocation'を呼び出してOpenGLに私の頂点属性インデックスを選択させると、常に0が選択されるので、私は両方の頂点属性に同じインデックスを使用しています。しかし、私は 'glBindAttribLocation' **がOpenGL ES 2.0で利用可能であることを発見しました。そして、この問題を避けて、2つのプログラムに異なるインデックスを指定することができます。 –