首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在单独的视口和默认的框架缓冲区中使用框架缓冲区?

如何在单独的视口和默认的框架缓冲区中使用框架缓冲区?
EN

Stack Overflow用户
提问于 2019-03-15 08:57:06
回答 1查看 167关注 0票数 1

我想了解Framebuffers是如何工作的。AFAIK,AFAIK缓冲器可以将渲染存储为纹理,具有存储深度信息的渲染缓冲区和存储颜色信息的颜色缓冲区。这里有一个默认的框架缓冲区,然后是我可能为存储单独呈现而创建的任何其他框架缓冲区。现在,我希望在整个屏幕上呈现默认的框架缓冲区,而在一个小的侧视图端口上,应该有一个由我的新框架缓冲区存储的呈现。在下面的源代码中没有发生这种情况。

代码:

代码语言:javascript
复制
#include <GL/glew.h>  
#include <GLFW/glfw3.h> 
#include <stdio.h>

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

int main() {
    GLFWwindow *window = NULL;
    GLuint vao;
    GLuint vbo;

    GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f };

    const char *vertex_shader = "#version 410\n"
                                "in vec3 vp;"
                                "void main () {"
                                "  gl_Position = vec4(vp, 1.0);"
                                "}";

    const char *fragment_shader = "#version 410\n"
                                "out vec4 frag_colour;"
                                "void main () {"
                                "  frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
                                "}";

    GLuint vert_shader, frag_shader;
    GLuint shader_programme;

    if ( !glfwInit() ) {
        fprintf( stderr, "ERROR: could not start GLFW3\n" );
        return 1;
    }

    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 6 );
    glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
    glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );

    window = glfwCreateWindow( WINDOW_WIDTH, WINDOW_HEIGHT, "Hello Triangle", NULL, NULL );
    if ( !window ) {
        fprintf( stderr, "ERROR: could not open window with GLFW3\n" );
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent( window );

    glewExperimental = GL_TRUE;
    glewInit();

    glEnable( GL_DEPTH_TEST ); /* enable depth-testing */
    glDepthFunc( GL_LESS );

    glGenBuffers( 1, &vbo );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, 9 * sizeof( GLfloat ), points, GL_STATIC_DRAW );
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    glEnableVertexAttribArray( 0 );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );

    vert_shader = glCreateShader( GL_VERTEX_SHADER );
    glShaderSource( vert_shader, 1, &vertex_shader, NULL );
    glCompileShader( vert_shader );
    frag_shader = glCreateShader( GL_FRAGMENT_SHADER );
    glShaderSource( frag_shader, 1, &fragment_shader, NULL );
    glCompileShader( frag_shader );
    shader_programme = glCreateProgram();
    glAttachShader( shader_programme, frag_shader );
    glAttachShader( shader_programme, vert_shader );
    glLinkProgram( shader_programme );


    GLuint g_fb;
    GLuint g_fb_tex;
    glGenFramebuffers( 1, &g_fb );
    glGenTextures( 1, &g_fb_tex );
    glBindTexture( GL_TEXTURE_2D, g_fb_tex );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
    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_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glBindFramebuffer( GL_FRAMEBUFFER, g_fb );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_fb_tex, 0 );
    GLuint rb = 0;
    glGenRenderbuffers( 1, &rb );
    glBindRenderbuffer( GL_RENDERBUFFER, rb );
    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2 );
    glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb );
    GLenum draw_bufs[] = { GL_COLOR_ATTACHMENT0 };
    glDrawBuffers( 1, draw_bufs );
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );



    while ( !glfwWindowShouldClose( window ) ) {
        glBindFramebuffer(GL_FRAMEBUFFER, g_fb);
        glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glUseProgram( shader_programme );
        glBindVertexArray( vao );
        glDrawArrays( GL_TRIANGLES, 0, 3 );

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glUseProgram( shader_programme );
        glBindVertexArray( vao );
        glDrawArrays( GL_TRIANGLES, 0, 3 );

        glfwPollEvents();
        glfwSwapBuffers( window );
    }

    glfwTerminate();
    return 0;
}

在这里,只呈现最后提到的缓冲区。我该怎么纠正呢?此外,我正在写一个场景类和渲染类在我的项目。是否应该在每个呈现器对象中存储框架缓冲区,还是应该将任何呈现器实例的所有帧缓冲区存储在场景类中?主要是,存储多个fbos需要多少存储/计算?

编辑:我在答案中提到了新的纹理,但我仍然只得到最后渲染的结果。请指出错误。我是否需要为新的帧缓冲区使用新的着色器?如果是的话,为什么不能重复使用早期的着色器呢?

代码:

代码语言:javascript
复制
#include <GL/glew.h>  
#include <GLFW/glfw3.h> 
#include <stdio.h>

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

int main() {
    GLFWwindow *window = NULL;
    GLuint vao;
    GLuint vbo;

    GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f };

    const char *vertex_shader = "#version 410\n"
                                "in vec3 vp;"
                                "void main () {"
                                "  gl_Position = vec4(vp, 1.0);"
                                "}";

    const char *fragment_shader = "#version 410\n"
                                "out vec4 frag_colour;"
                                "void main () {"
                                "  frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
                                "}";

    GLuint vert_shader, frag_shader;
    GLuint shader_programme;

    if ( !glfwInit() ) {
        fprintf( stderr, "ERROR: could not start GLFW3\n" );
        return 1;
    }

    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 6 );
    glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
    glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );

    window = glfwCreateWindow( WINDOW_WIDTH, WINDOW_HEIGHT, "Hello Triangle", NULL, NULL );
    if ( !window ) {
        fprintf( stderr, "ERROR: could not open window with GLFW3\n" );
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent( window );

    glewExperimental = GL_TRUE;
    glewInit();

    glEnable( GL_DEPTH_TEST ); /* enable depth-testing */
    glDepthFunc( GL_LESS );

    glGenBuffers( 1, &vbo );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, 9 * sizeof( GLfloat ), points, GL_STATIC_DRAW );
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    glEnableVertexAttribArray( 0 );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );

    vert_shader = glCreateShader( GL_VERTEX_SHADER );
    glShaderSource( vert_shader, 1, &vertex_shader, NULL );
    glCompileShader( vert_shader );
    frag_shader = glCreateShader( GL_FRAGMENT_SHADER );
    glShaderSource( frag_shader, 1, &fragment_shader, NULL );
    glCompileShader( frag_shader );
    shader_programme = glCreateProgram();
    glAttachShader( shader_programme, frag_shader );
    glAttachShader( shader_programme, vert_shader );
    glLinkProgram( shader_programme );


    GLuint g_fb;
    GLuint g_fb_tex;
    glGenFramebuffers( 1, &g_fb );
    glGenTextures( 1, &g_fb_tex );
    glBindTexture( GL_TEXTURE_2D, g_fb_tex );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
    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_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glBindFramebuffer( GL_FRAMEBUFFER, g_fb );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_fb_tex, 0 );
    GLuint rb = 0;
    glGenRenderbuffers( 1, &rb );
    glBindRenderbuffer( GL_RENDERBUFFER, rb );
    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2 );
    glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb );
    GLenum draw_bufs[] = { GL_COLOR_ATTACHMENT0 };
    glDrawBuffers( 1, draw_bufs );
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );



    while ( !glfwWindowShouldClose( window ) ) {
        glBindFramebuffer(GL_FRAMEBUFFER, g_fb);
        glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glUseProgram( shader_programme );
        glBindVertexArray( vao );
        glDrawArrays( GL_TRIANGLES, 0, 3 );

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glUseProgram( shader_programme );
        glBindVertexArray( vao );
        glDrawArrays( GL_TRIANGLES, 0, 3 );


        GLuint m_vbo, m_vao;
        GLfloat points[] = { 
            -0.5f,  0.5f, 0.0f, 
             0.5f,  0.5f, 0.0f, 
            -0.5f, -0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
             0.5f,  0.5f, 0.0f,
             0.5f, -0.5f, 0.0f
        };

        glGenBuffers(1, &m_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), points, GL_STATIC_DRAW);
        glGenVertexArrays(1, &m_vao);
        glBindVertexArray(m_vao);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        glBindTexture(GL_TEXTURE_2D, g_fb_tex);

        glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glUseProgram( shader_programme );
        glBindVertexArray( m_vao );
        glDrawArrays( GL_TRIANGLES, 0, 6 );

        glfwPollEvents();
        glfwSwapBuffers( window );
    }

    glfwTerminate();
    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-15 09:18:01

呈现循环的第一个块呈现给g_fb。结果是g_fb_tex。如果您想在窗口(= framebuffer 0)的“一个小视口”上显示此纹理,则应该呈现一个大小适当的矩形,并使用从g_fb_tex中获取的阴影。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55178831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档