GLES学习笔记--glReadpixels 读取数据全是0

发布时间:2023年12月20日
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了,但是具体原因还是不清楚,希望懂得大佬指点一下

文章来源:https://blog.csdn.net/cfc1243570631/article/details/135100160
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。