JNIEXPORT void JNICALL Java_com_sprd_opengl_test_MyNdk_processAndDraw
(JNIEnv *env, jobject obj, jobject bitmap) {
LOGD("processAndDraw");
glUseProgram(gl_cxt.program);
AndroidBitmapInfo bitmapInfo;
if (AndroidBitmap_getInfo(env, bitmap, &bitmapInfo) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! ");
return;
}
void *bmpPixels;
LOGD("processAndDraw1, format: %d, stride: %d", bitmapInfo.format, bitmapInfo.stride);
AndroidBitmap_lockPixels(env, bitmap, &bmpPixels);
LOGD("processAndDraw2");
unsigned int textureId;
glGenTextures(1, &textureId);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width = bitmapInfo.width;
int height = bitmapInfo.height;
#if 0
width = 256;
height = 256;
unsigned char *tData = (unsigned char *)malloc(width * height * 4);
unsigned char *ppData = tData;
for (int j = 0; j < width * height * 4; j++) {
*ppData++ = j % 255;
}
bmpPixels = (void*)tData;
#endif
LOGD("processAndDraw3");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bmpPixels);
unsigned char *pOri = (unsigned char *)bmpPixels;
LOGD("processAndDraw4 %d, %d, %d, %d, %d, %d, %d, %d", *(pOri), *(pOri+1), *(pOri+2), *(pOri+3),
*(pOri+114), *(pOri+115), *(pOri+116), *(pOri+117));
glBindTexture(GL_TEXTURE_2D, 0);
AndroidBitmap_unlockPixels(env, bitmap);
unsigned int offTexture, fbo;
glGenTextures(1, &offTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, offTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 没有这句调用, glCheckFramebufferStatus 返回 36054
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &fbo);
LOGD("fb status: %d, error: %d" , glCheckFramebufferStatus(GL_FRAMEBUFFER), glGetError());
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, offTexture, 0);
LOGD("fb status: %d, error: %d" , glCheckFramebufferStatus(GL_FRAMEBUFFER), glGetError());
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
/*顶点 纹理*/
float vertices[] = {-0.6f, -0.6f, 0.0f, 0.0f, 0.0f,
-0.6f, 0.6f, 0.0f, 0.0f, 1.0f,
0.6f, -0.6f, 0.0f, 1.0f, 0.0f,
0.6f, 0.6f, 0.0f, 1.0f, 1.0f};
unsigned int indices[] = {
0, 1, 2, // first triangle
1, 2, 3 // second triangle
};
// optimal
unsigned int VBO, EBO, VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)((0 + 3)*sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
glBindVertexArray(VAO);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw to offline texture.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//glViewport(0, 0, width, height);
LOGD("fb status: %d, error: %d" , glCheckFramebufferStatus(GL_FRAMEBUFFER), glGetError());
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glBindTexture(GL_TEXTURE_2D, 0);
//test glReadPixels
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
unsigned char *pData = NULL;
pData = (unsigned char *)malloc(width * height * 4);
memset(pData, 0xff, width * height * 4);
LOGD("before glReadPixels w: %d, h: %d, pData: %p", width, height, pData);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glReadBuffer (GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pData);
GLenum err = glGetError();
LOGD("after glReadPixels pData: %p, err: %d, status: %d", pData, err, status);
if (pData) {
int i = width * height / 2;
for(i = 0; i < width * height * 4; i++) {
if(*(pData+i) != 0)
break;
}
LOGD("i=%d", i);
i = 0;
LOGD("%d, %d, %d, %d", *(pData+i), *(pData+i+1), *(pData+i+2), *(pData+i+3));
// i = 1151048;
// LOGD("%d, %d, %d, %d, %d, %d, %d, %d", *(pData+i), *(pData+i+1), *(pData+i+2), *(pData+i+3),
// *(pData+i+114), *(pData+i+115), *(pData+i+116), *(pData+i+117));
free(pData);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// offline texture to screen
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, offTexture);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
eglSwapBuffers(gl_cxt.display, gl_cxt.winSurface);
}
如上代码中创建了两个texture,一个fbo;textureId 和 bitmap绑定,offTexture和fbo绑定,通过绑定fbo实现离屏渲染,将textureId对应的纹理渲染到offTexture上,最后将offTexture绘制到屏幕。
所有流程都正常,最后也绘制到屏幕了 ,但是当我想通过glReadPixel读取一下buffer看看的时候,发现buffer内容是0,找了半天没找到问题所在。
后面猜想可能数据正常读出来了,但是buffer前面一部分可能不是我想要的。
for(i = 0; i < width * height * 4; i++) {
if(*(pData+i) != 0)
break;
}
通过循环遍历看看buffer里面有没有非0的,然后重这非0的地方开始输出像素看看,发现确实和传入的一样,所以猜想是对的。
float vertices[] = {-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
于是猜想到可能是顶点坐标没有铺满导致的,原来是0.6,改成1.0 OK了,但是具体原因还是不清楚,希望懂得大佬指点一下