将我的场景渲染到帧缓冲对象 (FBO) 然后将该 FBO 渲染到屏幕需要哪些步骤? [英] What are the steps necessary to render my scene to a Framebuffer Object(FBO) and then render that FBO to the screen?

查看:37
本文介绍了将我的场景渲染到帧缓冲对象 (FBO) 然后将该 FBO 渲染到屏幕需要哪些步骤?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当复杂的场景,需要渲染许多 GL_POINTS.场景在很大程度上是静态的,所以我想将它渲染到一个帧缓冲对象,然后只在我的场景实际发生变化时才更新该 FBO.然后我想在每一帧都将 FBO 渲染到屏幕上.

I've got a fairly complicated scene with many GL_POINTS that I need to render. The scene will be largely static, so I'd like to render it to a Framebuffer Object and then only update that FBO when my scene actually changes. I'd then like to render the FBO to the screen each frame.

我找到了将 FBO 渲染为纹理的示例.我找到了将 FBO 渲染到 RenderBuffer 的示例(仍然不太确定那是什么).我不确定实现这一目标的步骤是什么.我需要渲染到纹理并将纹理绘制到屏幕上吗?

I've found examples that render an FBO into a texture. I've found examples that render an FBO into a RenderBuffer (still not quite sure what that is). I'm not sure what the steps are to achieve this. Do I need to render to a texture and the draw the texture to the screen?

能否请您列举将我的场景渲染到 FBO,然后将该 FBO 绘制到屏幕上的步骤(最好是伪代码或实际代码).

Can you please enumerate the steps (ideally even in pseudocode or actual code) to render my scene to an FBO and then draw that FBO to the screen.

draw() 足以作为我自己的绘图函数的占位符.

draw() is sufficient for a placeholder for my own drawing functions.

推荐答案

我提供了一个 最小 FBO 示例 仅用于此

I provide a minimal FBO example just for this

基本上步骤是:创建带有深度渲染缓冲区和颜色纹理附件的 FBO.要渲染到 FBO,取消绑定目标纹理,绑定 FBO,渲染到 FBO.解绑 FBO,绑定纹理,渲染.

Basically the steps are: Create FBO with depth renderbuffer and color texture attachment. To render to FBO unbind the target texture, bind FBO, render to FBO. Unbind FBO, bind texture, render.

#include <GL/glew.h>
#include <GL/glut.h>

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

void init();
void display();

int const fbo_width = 512;
int const fbo_height = 512;

GLuint fb, color, depth;

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );

    glutCreateWindow("FBO test");
    glutDisplayFunc(display);
    glutIdleFunc(glutPostRedisplay);

    glewInit();

    init();
    glutMainLoop();

    return 0;
}

void CHECK_FRAMEBUFFER_STATUS()
{                                                         
    GLenum status;
    status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 
    switch(status) {
    case GL_FRAMEBUFFER_COMPLETE:
        break;

    case GL_FRAMEBUFFER_UNSUPPORTED:
    /* choose different formats */
        break;

    default:
        /* programming error; will fail on all hardware */
        fputs("Framebuffer Error
", stderr);
        exit(-1);
    }
}

float const light_dir[]={1,1,1,0};
float const light_color[]={1,0.95,0.9,1};

void init()
{
    glGenFramebuffers(1, &fb);
    glGenTextures(1, &color);
    glGenRenderbuffers(1, &depth);

    glBindFramebuffer(GL_FRAMEBUFFER, fb);

    glBindTexture(GL_TEXTURE_2D, color);
    glTexImage2D(   GL_TEXTURE_2D, 
            0, 
            GL_RGBA, 
            fbo_width, fbo_height,
            0, 
            GL_RGBA, 
            GL_UNSIGNED_BYTE, 
            NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);

    glBindRenderbuffer(GL_RENDERBUFFER, depth);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbo_width, fbo_height);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);

    CHECK_FRAMEBUFFER_STATUS();
}

void prepare()
{
    static float a=0, b=0, c=0;

    glBindTexture(GL_TEXTURE_2D, 0);
    glEnable(GL_TEXTURE_2D);
    glBindFramebuffer(GL_FRAMEBUFFER, fb);

    glViewport(0,0, fbo_width, fbo_height);

    glClearColor(1,1,1,0);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, 1, 1, 10);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);

    glTranslatef(0,0,-5);

    glRotatef(a, 1, 0, 0);
    glRotatef(b, 0, 1, 0);
    glRotatef(c, 0, 0, 1);

    glutSolidTeapot(0.75);

    a=fmod(a+0.1, 360.);
    b=fmod(b+0.5, 360.);
    c=fmod(c+0.25, 360.);
}

void final()
{
    static float a=0, b=0, c=0;

    const int win_width  = glutGet(GLUT_WINDOW_WIDTH);
    const int win_height = glutGet(GLUT_WINDOW_HEIGHT);
    const float aspect = (float)win_width/(float)win_height;

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glViewport(0,0, win_width, win_height);

    glClearColor(1.,1.,1.,0.);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, aspect, 1, 10);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0,0,-5);

    glRotatef(b, 0, 1, 0);

    b=fmod(b+0.5, 360.);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, color);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glDisable(GL_LIGHTING);

    float cube[][5]=
    {
        {-1, -1, -1,  0,  0},
        { 1, -1, -1,  1,  0},
        { 1,  1, -1,  1,  1},
        {-1,  1, -1,  0,  1},

        {-1, -1,  1, -1,  0},
        { 1, -1,  1,  0,  0},
        { 1,  1,  1,  0,  1},
        {-1,  1,  1, -1,  1},
    };
    unsigned int faces[]=
    {
        0, 1, 2, 3,
        1, 5, 6, 2,
        5, 4, 7, 6,
        4, 0, 3, 7,
        3, 2, 6, 7,
        4, 5, 1, 0
    };

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, 5*sizeof(float), &cube[0][0]);
    glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), &cube[0][3]);

    glCullFace(GL_BACK);
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, faces);

    glCullFace(GL_FRONT);
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, faces);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

}

void display()
{
    prepare();
    final();

    glutSwapBuffers();
}

这篇关于将我的场景渲染到帧缓冲对象 (FBO) 然后将该 FBO 渲染到屏幕需要哪些步骤?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆