3

Android用OpenGLES2.0の1つのシェーダープログラムで、2つの異なるテクスチャを使用して2つのオブジェクトを描画しようとしています。最初のオブジェクトにはが必要texture0で、2番目のオブジェクトにはが必要texture1です。

フラグメントシェーダーには次のものがあります。

uniform sampler2D tex;

およびJavaコードの場合:

int tiu0 = 0;
int tiu1 = 1;
int texLoc = glGetUniformLocation(program, "tex");

glUseProgram(program);

// bind texture0 to texture image unit 0
glActiveTexture(GL_TEXTURE0 + tiu0);
glBindTexture(GL_TEXTURE_2D, texture0);

// bind texture1 to texture image unit 1
glActiveTexture(GL_TEXTURE0 + tiu1);
glBindTexture(GL_TEXTURE_2D, texture1);

glUniform1i(texLoc, tiu0);
// success: glGetError returns GL_NO_ERROR, glGetUniformiv returns 0 for texLoc

drawFirstObject(); // should have texture0

glUniform1i(texLoc, tiu1);
// success: glGetError returns GL_NO_ERROR, glGetUniformiv returns 1 for texLoc

drawSecondObject(); // should have texture1

Android2.3.3を搭載したSamsungGalaxyAceで実行すると、両方のオブジェクトが同じになりtexture0ます。同様のコードは、デスクトップコンピューターのOpenGL2.0で正しく実行されます。

を削除するdrawFirstObjectと、2番目のオブジェクトにはが含まれますtexture1

を削除するdrawSecondObjectと、最初のオブジェクトにはが含まれますtexture0

drawFirstObjectdrawSecondObject私がしばらくの間プログラムを変更した場合:

glUseProgram(0); // can be also any valid program other than the program from the next call
glUseProgram(program);

その場合、両方のオブジェクトに。がありtexture1ます。

とは異なるユニフォームの値sampler2Dは常に正しく設定されます。

オブジェクトを描画する前に、1つのテクスチャイメージユニットを使用して適切なテクスチャをそのテクスチャイメージユニットにバインドするだけで、異なるテクスチャの2つのオブジェクトを描画できることはわかっていますが、ここで何が起こっているのかも知りたいです。

私のコードに何か問題がありますか?OpenGL ES 2.0で、コードに示したようにテクスチャ画像ユニットを切り替えるだけで、異なるテクスチャのオブジェクトを描画することは可能ですか?それが不可能な場合、OpenGL 2.0(可能な場合)とOpenGL ES 2.0の違いはどこかに文書化されていますか?見つかりません。

4

1 に答える 1

3

何時間にもわたる調査の結果、この問題は、Samsung Galaxy Ace(GT-S5830)で使用されているAdreno200GPUに固有のものであることがわかりました。Adreno 200ドライバーは、描画関数の最初の呼び出しでサンプラーにテクスチャを割り当て、その後glUniform1i(samplerLocation, textureImageUnit)、2つのいずれかが発生するまでサンプラー値()の変更を無視するようです。

  • glUseProgram別のシェーダープログラムで呼び出され、
  • シェーダープログラムで使用されるテクスチャイメージユニットには、別のテクスチャがバインドされます。

Adreno 200 GPUの製造元のフォーラムには、まったく同じ問題を説明するスレッドがあります。

したがって、同じシェーダープログラムで、前にバインドされた異なるテクスチャを使用して描画関数を複数回呼び出す場合、説明されている問題には2つの回避策があります。

  1. glUseProgram(0); glUseProgram(yourDrawingProgram);すべての描画関数の前に呼び出します。

  2. すべての描画呼び出しの前に、シェーダープログラムで使用される少なくとも1つのテクスチャイメージユニットに異なるテクスチャをバインドします。テクスチャイメージユニットにすでにバインドされているのと同じテクスチャをバインドすると、問題が残るため、このソリューションを維持するのは難しい場合があります。したがって、この場合の最も簡単な解決策は、すべての描画呼び出しの前に、サンプラー値を変更せず、シェーダープログラムによって使用されるすべてのテクスチャイメージユニットのテクスチャをバインドすることです。

于 2012-12-03T19:23:41.397 に答える