我已经能够从修改 NDK 示例“GL2JNIActivity”的帧缓冲区执行 glReadPixels。
我刚刚更改了 gl_code.cpp,我在其中添加了一个初始化函数:
char *pixel = NULL;
GLuint fbuffer, rbuffers[2];
int width, height;
bool setupMyStuff(int w, int h) {
// Allocate the memory
if(pixel != NULL) free(pixel);
pixel = (char *) calloc(w * h * 4, sizeof(char)); //4 components
if(pixel == NULL) {
LOGE("memory not allocated!");
return false;
}
// Create and bind the framebuffer
glGenFramebuffers(1, &fbuffer);
checkGlError("glGenFramebuffer");
glBindFramebuffer(GL_FRAMEBUFFER, fbuffer);
checkGlError("glBindFramebuffer");
glGenRenderbuffers(2, rbuffers);
checkGlError("glGenRenderbuffers");
glBindRenderbuffer(GL_RENDERBUFFER, rbuffers[0]);
checkGlError("glGenFramebuffer[color]");
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, w, h);
checkGlError("glGenFramebuffer[color]");
glBindRenderbuffer(GL_RENDERBUFFER, rbuffers[1]);
checkGlError("glGenFramebuffer[depth]");
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
checkGlError("glGenFramebuffer[depth]");
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbuffers[0]);
checkGlError("glGenFramebuffer[color]");
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuffers[1]);
checkGlError("glGenFramebuffer[depth]");
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOGE("Framebuffer not complete");
return false;
}
// Turn this on to confront the results in pixels when the fb is active with the ones obtained from the screen
if(false) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
checkGlError("glBindFramebuffer");
}
width = w;
height = h;
return true;
}
它只是初始化帧缓冲区并为输出分配空间,我在最后调用
bool setupGraphics(int w, int h);
和一个块将输出保存在我的像素数组中(我显然在
checkGlError("glDrawArrays");
renderFrame() 中的语句:
{
// save the output of glReadPixels somewhere... I'm a noob about JNI however, so I leave this part as an exercise for the reader ;-)
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
checkGlError("glReadPixel(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel)");
int end = width * height * 4 - 1;
// This function returns the same results regardless of where the data comes from (screen or fbo)
LOGI("glReadPixel => (%hhu,%hhu,%hhu,%hhu),(%hhu,%hhu,%hhu,%hhu),(%hhu,%hhu,%hhu,%hhu),..., (%hhu, %hhu, %hhu, %hhu)",
pixel[0], pixel[1], pixel[2], pixel[3],
pixel[4], pixel[5], pixel[6], pixel[7],
pixel[8], pixel[9], pixel[10], pixel[11],
pixel[end - 3], pixel[end - 2], pixel[end - 1], pixel[end]);
}
无论您是在帧缓冲区还是在屏幕上绘制,logcat 中的结果都是相同的:
I/libgl2jni( 5246): glReadPixel => (0,4,0,255),(8,4,8,255),(0,4,0,255),..., (0, 4, 0, 255)
I/libgl2jni( 5246): glReadPixel => (8,4,8,255),(8,8,8,255),(0,4,0,255),..., (8, 8, 8, 255)
I/libgl2jni( 5246): glReadPixel => (8,8,8,255),(8,12,8,255),(8,8,8,255),..., (8, 8, 8, 255)
I/libgl2jni( 5246): glReadPixel => (8,12,8,255),(16,12,16,255),(8,12,8,255),..., (8, 12, 8, 255)
I/libgl2jni( 5246): glReadPixel => (16,12,16,255),(16,16,16,255),(8,12,8,255),..., (16, 16, 16, 255)
[...]
在 Froyo(手机)和 4.0.3 平板电脑上进行了测试。
您可以在原始 NDK 示例 (GL2JNIActivity) 中找到所有其他详细信息。
希望这可以帮助
编辑:还要确保检查:
Android NDK glReadPixels() 来自屏幕外缓冲区
海报似乎有你相同的症状(并解决了从正确的线程调用 glReadPixels 的问题)。