に私たちは10ネクサス10 - 外部レンダーターゲットにレンダリングするには、唯一の風景
ライブ壁紙は、それらの間でピンポンレンダリングを行うために2小(128×128)の外部フレームバッファを使用していますネクサス上のOpenGL ES 2.0とのライブ壁紙を開発している作品画像をぼかします。
Nexus 10でこれが問題になります。これは、デバイスが(老化したMotorola Milestoneであっても)完璧に機能しますが、デバイスが横向きの場合にのみ機能します。デバイスを他の任意の位置(90度、180度または270度)で回転させると、フレームバッファの色が鮮明になります。私はglClearColor
を赤色に設定しているので、これらのフレームバッファがクリアされていても何も描画されていないことがはっきりとわかります。
私はTegra 2、Tegra 3、Adreno 200、Adreno 320,2 PowerVR GPUでテストしましたが、うまく動作します。
これはいくつかの不思議なドライバのバグのようですが、Maliドライバのいくつかの特徴かもしれません。ご意見をお聞かせください。
コード抜粋。
初期フレームバッファ:
private void initBloomStuff() {
mBloomTextureID = loadTexture("textures/empty128.png");
mBloomVertTextureID = loadTexture("textures/empty128.png");
mBloomFBHeight = 128;
mBloomFBWidth = 128;
float blurSize = 1.0f;
// Texel offset for blur filter kernel
m_fTexelOffset = 1.0f/mBloomFBWidth/blurSize;
ByteBuffer tmpFB, tmpRB;
IntBuffer handle, renderbuffers;
int result;
tmpFB = ByteBuffer.allocateDirect(4);
tmpFB.order(ByteOrder.nativeOrder());
handle = tmpFB.asIntBuffer();
GLES20.glGenFramebuffers(1, handle);
framebufferHandle = handle.get(0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferHandle);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mBloomTextureID, 0);
checkGlError("FB 1");
tmpRB = ByteBuffer.allocateDirect(4);
renderbuffers = tmpRB.asIntBuffer();
GLES20.glGenRenderbuffers(1, renderbuffers);
checkGlError("FB 1 - glGenRenderbuffers");
depthbufferHandle = renderbuffers.get(0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthbufferHandle);
checkGlError("FB 1 - glBindRenderbuffer");
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mBloomFBWidth, mBloomFBHeight);
checkGlError("FB 1 - glRenderbufferStorage");
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthbufferHandle);
checkGlError("FB 1 - glFramebufferRenderbuffer");
result = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (result != GLES20.GL_FRAMEBUFFER_COMPLETE) {
Log.d(TAG, "Error creating framebufer 1: " + result);
} else {
Log.d(TAG, "Created framebufer 1: " + result);
}
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
tmpFB = ByteBuffer.allocateDirect(4);
tmpFB.order(ByteOrder.nativeOrder());
handle = tmpFB.asIntBuffer();
GLES20.glGenFramebuffers(1, handle);
framebufferVertHandle = handle.get(0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomVertTextureID);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferVertHandle);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mBloomVertTextureID, 0);
checkGlError("FB 2");
tmpRB = ByteBuffer.allocateDirect(4);
renderbuffers = tmpRB.asIntBuffer();
GLES20.glGenRenderbuffers(1, renderbuffers);
checkGlError("FB 2 - glGenRenderbuffers");
depthbufferVertHandle = renderbuffers.get(0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthbufferVertHandle);
checkGlError("FB 2 - glBindRenderbuffer");
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mBloomFBWidth, mBloomFBHeight);
checkGlError("FB 2 - glRenderbufferStorage");
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthbufferVertHandle);
checkGlError("FB 2 - glFramebufferRenderbuffer");
result = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (result != GLES20.GL_FRAMEBUFFER_COMPLETE) {
Log.d(TAG, "Error creating framebufer 2: " + result);
} else {
Log.d(TAG, "Created framebufer 2: " + result);
}
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
mTriangleVerticesVignette = ByteBuffer.allocateDirect(mQuadTriangles.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleVerticesVignette.put(mQuadTriangles).position(0);
}
FBにレンダリング:
GLES20.glUseProgram(mProgram);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mStemTextureID);
drawBird();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mSphereTextureID);
drawSphere();
GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferHandle);
// GLES20.glBindRenderbuffer(GLES20.GL_FRAMEBUFFER, depthbufferHandle);
GLES20.glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mStemTextureID);
drawBird();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mSphereTextureID);
drawSphere();
GLES20.glViewport(0, 0, screenWidth, screenHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// GLES20.glBindRenderbuffer(GLES20.GL_FRAMEBUFFER, 0);
ピンポンは、画像をぼかす2つのFBの間のレンダリング:バグを再現する
GLES20.glUseProgram(mBloomProgram);
GLES20.glUniform1i(mBloom_sTexture, 0);
GLES20.glUniform1f(mBloom_bloomFactor, 0.8f);
GLES20.glActiveTexture(GL10.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID);
GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferVertHandle);
GLES20.glUniform1f(mBloom_TexelOffsetX, m_fTexelOffset);
GLES20.glUniform1f(mBloom_TexelOffsetY, 0.0f);
GLES20.glActiveTexture(GL10.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
drawBloom();
GLES20.glViewport(0, 0, screenWidth, screenHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glActiveTexture(GL10.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomVertTextureID);
GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferHandle);
GLES20.glUniform1f(mBloom_TexelOffsetX, 0.0f);
GLES20.glUniform1f(mBloom_TexelOffsetY, m_fTexelOffset);
GLES20.glActiveTexture(GL10.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomVertTextureID);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
drawBloom();
GLES20.glViewport(0, 0, screenWidth, screenHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glActiveTexture(GL10.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID);
GLES20.glViewport(0, 0, mBloomFBWidth, mBloomFBHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferVertHandle);
GLES20.glUniform1f(mBloom_TexelOffsetX, m_fTexelOffset/2);
GLES20.glUniform1f(mBloom_TexelOffsetY, m_fTexelOffset/2);
GLES20.glActiveTexture(GL10.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBloomTextureID);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
drawBloom();
GLES20.glViewport(0, 0, screenWidth, screenHeight);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
テストアプリケーション
ここにテストAPKをダウンロードすることができます:https://dl.dropboxusercontent.com/u/7197208/LiveWallpaperAnimTest.apk ライブ壁紙アプリです。インストールし、「テスト」ライブ壁紙(バラのアイコン付き)を選択します。
デフォルトの横向きの向きでは、2つのフレームバッファの間でピンポンレンダリングによって実装される鳥の周りに「ブルーム」効果が表示されます。それ以外のデバイスの向きでは機能しませんし、FBをクリアカラー(赤色)で塗りつぶします。
追加リンク
私もマリデベロッパーセンターとGoogle Codeのにこの問題を掲載しました:
http://code.google.com/p/android/issues/detail?id=57391