在Android 2.通过调用glReadPixels + FBO从帧缓冲区读取。但是,字节数组是0。有趣的是,当我删除绑定代码(保留glReadPixels)时,它可以工作。
这让我怀疑我是否没有正确绑定缓冲区,尽管当我检查框架缓冲区状态(glCheckFramebufferStatus)时,我得到了GLES20.GL_FRAMEBUFFER_COMPLETE。知道我做错了什么吗?
int frameIdIndex=0,renderIdIndex=1,textureIdIndex=2;
int[] bufferId=new int[3];
Bitmap takeOne(Context cntxt) {
DisplayMetrics dm = cntxt.getResources().getDisplayMetrics();
int width = dm.widthPixels;
int height = dm.heightPixels;
//id index 0 frameId, 1 renderId 2 textureId;
GLES20.glGenFramebuffers(1,bufferId,frameIdIndex);
GLES20.glGenRenderbuffers(1, bufferId, renderIdIndex);
GLES20.glGenTextures(1, bufferId, textureIdIndex);
// bind texture and load the texture mip-level 0
// texels are RGB565
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,bufferId[textureIdIndex]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,0,GLES20.GL_RGBA,width,height,0,GLES20.GL_RGBA,GLES20.GL_UNSIGNED_SHORT_5_6_5,null);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
// bind renderbuffer and create a 16-bit depth buffer
// width and height of renderbuffer = width and height of
// the texture
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, bufferId[renderIdIndex]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,GLES20.GL_DEPTH_COMPONENT16,width,height);
//bind the frameBuffer;
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,bufferId[frameIdIndex]);
//specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,GLES20.GL_COLOR_ATTACHMENT0,GLES20.GL_TEXTURE_2D,bufferId[textureIdIndex],0);
//specify renderbuffer as depth_attachment
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,GLES20.GL_DEPTH_ATTACHMENT,GLES20.GL_RENDERBUFFER,bufferId[renderIdIndex]);
//check for framebuffer complete
int status= GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if(status !=GLES20.GL_FRAMEBUFFER_COMPLETE) {
throw new RuntimeException("status:"+status+", hex:"+Integer.toHexString(status));
}
int screenshotSize = width * height;
ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
bb.order(ByteOrder.nativeOrder());
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA,
GL10.GL_UNSIGNED_BYTE, bb);
int pixelsBuffer[] = new int[screenshotSize];
bb.asIntBuffer().get(pixelsBuffer);
final Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.RGB_565);
bitmap.setPixels(pixelsBuffer, screenshotSize - width, -width,
0, 0, width, height);
pixelsBuffer = null;
short sBuffer[] = new short[screenshotSize];
ShortBuffer sb = ShortBuffer.wrap(sBuffer);
bitmap.copyPixelsToBuffer(sb);
// Making created bitmap (from OpenGL points) compatible with
// Android
// bitmap
for (int i = 0; i < screenshotSize; ++i) {
short v = sBuffer[i];
sBuffer[i] = (short) (((v & 0x1f) << 11) | (v & 0x7e0) | ((v & 0xf800) >> 11));
}
sb.rewind();
bitmap.copyPixelsFromBuffer(sb);
// cleanup
GLES20.glDeleteRenderbuffers(1, bufferId,renderIdIndex);
GLES20.glDeleteFramebuffers(1, bufferId ,frameIdIndex);
GLES20.glDeleteTextures(1, bufferId,textureIdIndex);
return bitmap;
}
发布于 2014-07-10 17:28:32
您的格式和类型有些混淆。这个glTexImage2D()
应该已经给你打了一个GL_INVALID_OPERATION
电话,如果你检查了glGetError()
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0,
GLES20.GL_RGBA, width, height, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_SHORT_5_6_5, null);
GL_UNSIGNED_SHORT_5_6_5
只能与GL_RGB
格式一起使用。来自文档
如果类型为GL_UNSIGNED_SHORT_5_6_5而格式不是GL_RGB,则生成GL_RGB。
为了避免这种错误情况,调用需要如下:
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0,
GLES20.GL_RGB, width, height, 0,
GLES20.GL_RGB, GLES20.GL_UNSIGNED_SHORT_5_6_5, null);
在我看来,glReadPixels()
调用本身是很好的,所以我相信一旦你有了一个有效的纹理就可以使用它了。
bitmap.setPixels()
调用可能有问题。文档说,它需要ARGB颜色,您将在这里使用RGBA。但这超出了你问题的主要范围。
https://stackoverflow.com/questions/24681908
复制相似问题