【问题标题】:Why does the frambuffer attachment is being cleared when its unbound为什么帧缓冲区附件在未绑定时被清除
【发布时间】:2023-01-21 07:06:30
【问题描述】:

我在屏幕外绘制一些图元到纹理,以供以后用作渲染到主帧缓冲区 (0) 的着色器的纹理输入。 离屏渲染器看起来像这样:

void render_offscreen(GLuint tex, int w, int h){

    static GLuint shader, vertex_array_object, texture, framebuffer etc
    if(first_run){
        create_gl_resources(&shader, &vertex_array_object, &texture, &framebuffer ...);
        first_run = 0;
    }


    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glViewport(0, 0, w, h);
    glClear(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    // render
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glUseProgram(shader);
    glBindVertexArray(vertex_array_object);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
    // unbind
    glBindVertexArray(0);
    glUseProgram(0);
    glBindTextureUnit(0, 0);
    glDisable(GL_BLEND);
    tex = texture;
}

并在绘制循环中调用它:

    ...
    static GLuint tex;
    if(redraw){
        render_offscreen(&tex, 128, 512);
        glBindFramebuffer(GL_FRAMEBUFFER, 0)
        redraw = 0;
    }
    int w, h;
    glfw_get_framebuffer_size(&w, &h);
    glViewport(0, 0, w, h);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glBindTextureUnit(0, tex);
    glUseProgram(quad_shader);
    glUniform1i(texture_loc, 0);
    glBindVertexArray(vertex_array_object);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
    glfw_swap_buffers();
    glfw_poll_events();
    ...

它正确绘制第一帧,然后绘制黑色。如果我在绘制循环中删除这个glClear(GL_COLOR_BUFFER_BIT);,那么它又可以正常工作了。 当使用纹理作为帧缓冲区的附件时,我的印象是我必须渲染一次并重新使用纹理,因为它的值被保留了。另一个问题可能是我使用 GL_ONE_MINUS_SRC_ALPHA 不正确,因为我之前渲染过屏幕外纹理,这个问题从来没有出现在我身上,如果它是混合的,那么我不知道 glClear(GL_COLOR_BUFFER_BIT); 如何清除纹理数据。 提前感谢您的帮助!

【问题讨论】:

    标签: c opengl framebuffer


    【解决方案1】:

    我仍然无法追踪问题出在哪里,但在重构我的代码后,一切似乎都呈现得很好。不管怎样,这里是渲染离屏图像的完整代码:

    实际的 draw_my_scene() 被省略了,因为它在此上下文中不相关

    void bind_frame(GLuint * texture, int width, int height){
        static int _width, _height;
        static int _state;
        static GLuint framebuffer, color_attachment;
        if(_width != width || _height != height) _state = 1;
        if(_state == 1){ // = 1 recreate resources
            if(width < 1 || height < 1) printf("error offscreen width or height is less than 1
    ");
            // delete if necessery
            opengl_delete_texture(texture);
            opengl_delete_framebuffer(&framebuffer);
            // texture
            opengl_create_texture(&color_attachment, width, height, GL_RGBA8);
            opengl_texture_tile_no_repeat(color_attachment);
            opengl_texture_filter_smooth(color_attachment);
            // framebuffer
            opengl_create_framebuffer(&framebuffer, width, height);
            opengl_framebuffer_color(framebuffer, color_attachment);
            _width = width, _height = height;
            _state = 0;
        }
        // prepare frame for drawing
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
        glViewport(0, 0, width, height);
        *texture = color_attachment;
    }
    
    void draw_frame(GLuint frame, mat4 transform){
    
        static GLuint   vertex_array, vertex_buffer, index_buffer,
                        program,
                        texture_loc, model_loc;
    
        static int _state = 1;
        if(_state == 1){
            // attributes
            int num_of_attribs = 2;
            int location [] = {0, 1};
            int count []    = {2, 2};
            int offset []   = {0, 2};
            int binding []  = {0, 0};
            // vertex_array
            opengl_create_vertex_array(&vertex_array);
            for(int i = 0; i < num_of_attribs; i++){
                opengl_vertex_array_enable_attrib(vertex_array, location[i], GL_FLOAT, sizeof(float)*count[i], count[i], offset[i], binding[i]);
            }
            // vertex_data
            const float vertex_data[] = {
                // pos           tex
               -1.0f, -1.0f,     0.0f,  0.0f,
               -1.0f,  1.0f,     0.0f,  1.0f,
                1.0f, -1.0f,     1.0f,  0.0f,
                1.0f,  1.0f,     1.0f,  1.0f
            };
            // vertex_buffer
            opengl_create_buffer(&vertex_buffer, (void*)&vertex_data, sizeof(vertex_data));
            opengl_vertex_array_vertex_buffer(vertex_array, vertex_buffer, 0, sizeof(float)*4, 0);
            // index_buffer
            const int index_data[] = {0, 1, 2, 1, 3, 2};
            opengl_create_buffer(&index_buffer, (void*)&index_data, sizeof(index_data));
            opengl_vertex_array_element_buffer(vertex_array, index_buffer);
    
            // vertex_shader_code
            static const char * vertex_shader_code = 
            "#version 460 core
    "
            "uniform mat4 model;
    "
            "layout (location = 0) in vec2 vPos;
    "
            "layout (location = 1) in vec2 vTexCoord;
    "
            "out vec2 texCoord;
    "
            "void main()
    "
            "{
    "
            // "gl_Position = vec4(vPos, 0.0, 1.0);
    "
            "gl_Position = model * vec4(vPos, 0.0, 1.0);
    "
            // "texCoord = vTexCoord * vec2(1.0, -1.0);
    " // flip y
            "texCoord = vTexCoord;
    "
            "}
    ";
            // fragment_shader_code
            static const char * fragment_shader_code = 
            "#version 460 core
    "
            "uniform sampler2D tex;
    "
            "in vec2 texCoord;
    "
            "out vec4 FragColor;
    "
            "void main(){
    "
                "FragColor = texture(tex, texCoord);
    "
            "}
    ";
            // vertex & fragment shaders
            GLuint vertex_shader, fragment_shader;
            opengl_compile_shader(&vertex_shader, GL_VERTEX_SHADER, vertex_shader_code);
            opengl_compile_shader(&fragment_shader, GL_FRAGMENT_SHADER, fragment_shader_code);
            // program
            opengl_create_program(&program, vertex_shader, fragment_shader);
            // uniform location
            texture_loc = glGetUniformLocation(program, "tex");
            model_loc = glGetUniformLocation(program, "model");
            _state = 0;
        }
        
        glBindTextureUnit(1, frame);
        glUseProgram(program);
        glUniform1i(texture_loc, 1);
        glUniformMatrix4fv(model_loc, 1, GL_FALSE, (const GLfloat*)transform);
        glBindVertexArray(vertex_array);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
    }
    
    int main(){
        if(glfw_create_window_opengl(512, 512)) return -1;
        if(opengl_init()) return -1;
        
        // glEnable(GL_MULTISAMPLE);
        // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        // glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
        // glPolygonMode(GL_FRONT_AND_BACK, GL_TRIANGLES);
        // glEnable(GL_DEPTH_TEST); // this one fixes assimp models displaying incorrectly (wrong z-buffer)
        // glEnable(GL_CULL_FACE);
        // glDisable(GL_CULL_FACE);
        // glCullFace(GL_BACK);
        // glCullFace(GL_FRONT);
        // glFrontFace(GL_CW);  // clockwise
        // glFrontFace(GL_CCW); // counter-clockwise - default
        // glEnable(GL_SCISSOR_TEST);
    
        GLuint frame0;
        mat4 frame0_transform;
        glm_mat4_identity(frame0_transform);
    
        while(!glfw_window_should_close()){
            int w, h;
            glfw_get_frame_size(&w, &h);
            glViewport(0, 0, w, h);
            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            bind_frame(&frame0, 128, 128);
            // draw everything as usual
            draw_my_scene();
    
            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
            draw_frame(frame0, frame0_transform);
    
            glfw_swap_buffers();
            glfw_poll_events();
        }
    
        opengl_quit(); // free gl resources
        glfw_quit();
        return 0;
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-11
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多