FBO渲染问题 - 在相同的应用程序中使用生成的FBO颜色/深度进行绘图使用GLSL

时间:2014-05-26 12:10:46

标签: opengl graphics opengl-es opengl-es-2.0 fbo

**Output With BLIT Call - Test Code**

**Output Without Using BLIT CALL Test Code**

带有两个立方体的图像是使用BLIT Call - Test Code

带有一个多维数据集的图像是不使用BLIT CALL - 测试代码

民间, 请按照附图和&代码如下..

过去2天挣扎于此......

在下面的代码中使用FBO时遇到问题,我可以附加&成功渲染到FBo,但有些人不能在同一个程序中使用它作为纹理(颜色和深度缓冲区),渲染到FBO后调用MY glReadpixel向我显示所有Zero的数据......

当生成FBO(颜色,深度)用于GLSL着色器代码时,从Draw2()函数调用该函数会显示没有纹理的混合白色立方体。

请建议......,下面是完整的代码...,我正在创建一个FBO&使用2个着色器一个用于Normal渲染&另一个使用颜色&来自FBO的深度已经处理过了..

这是我的SHADER代码

        init_gl()
        {

此片段着色器代码用于在draw()下的程序中使用的正常渲染

            static const char *fragment_shader_source =
                "precision mediump float;           \n"
                "                                   \n"
                "varying vec4 vVaryingColor;        \n"
                "                                   \n"
                "void main()                        \n"
                "{                                  \n"
                "    gl_FragColor = vVaryingColor;  \n"
                "}                                  \n";

此片段着色器代码在draw2()

下的Program2中使用
                static const char *fragment_shader_source2 =
                "precision mediump float;           \n"
                "                                   \n"
                "varying vec4 vVaryingColor;        \n"
                "uniform sampler2D color;       \n"
                "uniform sampler2D depth;       \n"
                "                                   \n"
                "void main()                        \n"
                "{                                  \n"
                "float r = pow(texture2D(color, gl_FragCoord.xy / vec2(256, 256)).a, 128.0); \n"
                "float g = texture2D(depth, gl_FragCoord.xy / vec2(256, 256)).a;\n"
                "float b = pow(texture2D(depth, gl_FragCoord.xy / vec2(256, 256)).a, 128.0); \n"
                "gl_FragColor = vec4(r, g, b, 1.);   \n"
                "}                                  \n";

我在FBO上的第一张图

    static void draw(uint32_t i)
    {

            EGL_CHECK(glEnable(GL_DEPTH_TEST)); 
        glEnable(GL_TEXTURE_2D);
        EGL_CHECK(glDepthFunc(GL_ALWAYS));
            EGL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fboInfo.id));
        EGL_CHECK(glUseProgram(program));

        //CUBE DRAWING

在此处执行Read Pixel,它返回所有零

        GLubyte *pixels = malloc(4 * 256 * 256);
        EGL_CHECK(glReadBuffer(GL_COLOR_ATTACHMENT0));
        EGL_CHECK(glReadPixels(0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, pixels));

            //**TO TEST my FBO , IF ITS HAVING SOME RENDER DATA**
        EGL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
        glBindFramebuffer(GL_READ_FRAMEBUFFER, fboInfo.id); 
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
        glBlitFramebuffer(0, 0, 256, 256, 0, 0, 256, 256, GL_COLOR_BUFFER_BIT, GL_NEAREST);
        glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
            //TEST CODE ONLY

        glBindTexture(GL_TEXTURE_2D, fboInfo.id);
            glGenerateMipmap(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, 0);

        draw2(i);

    }

没有FBO的第二次绘图(但这使用可以访问FBO数据颜色,深度的FRAG SHADER)

    static void draw2(uint32_t i)
    {

        glUseProgram(program2);

        //Draw Same Kind of Cube , Which we draw in draw() function

    }

这些是创建FBO(颜色,深度)

的功能
         GLuint createTexture2D(const int w, const int h, GLint internalFormat, GLenum format, GLenum type)
            {
                GLuint textureIdX;
                EGL_CHECK(glGenTextures(1, &textureIdX));
                EGL_CHECK(glBindTexture(GL_TEXTURE_2D, textureIdX));

                EGL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
                EGL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
                EGL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
                EGL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
                if (GL_DEPTH_COMPONENT == format) {
                    EGL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE));
                    EGL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY));
                }
                EGL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, 0));
                EGL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
                return textureIdX;
            }

            int createFBO(void)
            {
                int result = 0;
                unsigned int fb = 0;

                fboInfo.color = createTexture2D(WINDOW_WIDTH, WINDOW_HEIGHT, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
                fboInfo.depth = createTexture2D(WINDOW_WIDTH, WINDOW_HEIGHT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT);

                EGL_CHECK(glGenFramebuffers(1, &fboInfo.id));
                EGL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fboInfo.id));


                EGL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboInfo.color, 0));
                EGL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboInfo.depth, 0));

                int data = EGL_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER));
                if (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)) {
                    printf("FBO %d set up successfully\n", fboInfo.id);
                    result = 1;
                }
                else {
                    printf("FBO %d NOT set up properly!\n", fboInfo.id);
                }

                EGL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
                return result;
            }

这就是我的FBO Struct看起来像

typedef struct {
    GLuint id;
    GLuint color;
    GLuint depth;
}FBOInfo;

我的主要功能在下面我创建FBO&然后调用我的绘图功能&交换缓冲区..

            unsigned long i = 0;
            int ret = init_gl();
            ret = createFBO();
            draw(i);
            EGL_CHECK(eglSwapBuffers(eglDisplay, eglSurface));

1 个答案:

答案 0 :(得分:1)

由于这是相当多的代码,并且您建议问题在于FBO设置,我专注于该部分。我确实发现了设置附件的代码部分中的一个严重问题:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboInfo.depth, 0);

如果在此之后调用glGetError(),则会看到返回错误,因为GL_RENDERBUFFER不是第3个参数的有效值。唯一有效的参数是GL_TEXTURE_2DGL_TEXTURE_CUBE_MAP_*值。在这种情况下,您必须使用GL_TEXTURE_2D

如果你从不将它用作纹理,那么使用渲染缓冲区实际上可能会更好。但要做到这一点,你必须使用所有相应的调用:

  • 使用glGenRenderbuffers创建ID。
  • glBindRenderbuffer绑定。
  • 使用glRenderbufferStorage分配。
  • 使用glFramebufferRenderbuffer
  • 将其附加到FBO