在Android上 - ES 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;
}
答案 0 :(得分:0)
您的格式和类型有些混乱。如果您使用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
格式。来自documentation:
如果type为GL_UNSIGNED_SHORT_5_6_5且格式不是GL_RGB,则会生成GL_INVALID_OPERATION。
要避免此错误情况,请致电:
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。但这超出了你问题的主要范围。