2011-09-06 14 views
5

En una Mac, tengo una configuración de OpenGL que funciona muy bien, aparte de los framebuffers, texturas, etc. Así que sé que la textura está habilitada, Tengo un contexto válido, etc. Todo funciona sin problemas hasta que intento crear un framebuffer.OpenGL framebuffer: puede borrarlo, pero no puede extraerlo

Creé un framebuffer con glGenFramebuffers, glBindFramebuffer y glFramebufferTexture2D, y glCheckFramebufferStatus está devolviendo GL_FRAMEBUFFER_COMPLETE. Si luego llamo a glClear, seguido de una llamada a glGetTexImage, los datos devueltos muestran que glClear actuó en la textura vinculada al framebuffer como debería. Puedo establecer glClearColor en todo lo que quiero, y glClear establece los datos de textura correctamente.

Pero ahí es donde se detiene la buena noticia. No puedo extraer nada en el framebuffer, ya sea que use VBO o glBegin/glEnd. Los datos de textura de la textura vinculada al framebuffer no se tocan con las llamadas al sorteo (aunque los resultados glClear aún aparecen). Esto es cierto incluso si llamo a glFlush y glFinish antes de la llamada glGetTexImage. Además, glGetError no devuelve ningún error en ninguna de mis llamadas.

He publicado a continuación un ejemplo de código que agregué en un punto relevante del programa solo para tratar de trabajar en este tema, en caso de que le dé a alguien una idea. (Esto no incluye la llamada glClear, pero sé por pruebas separadas en el mismo punto que eso funciona bien).

glGenFramebuffers(1, &fb); 
glBindFramebuffer(GL_FRAMEBUFFER, fb); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbTexID, 0); 
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
if(status != GL_FRAMEBUFFER_COMPLETE) 
    Debugger(); 

glEnable(GL_TEXTURE_2D); 
glCullFace(GL_NONE); 
glGenTextures(1,(GLuint*)&tex); 
glBindTexture(GL_TEXTURE_2D,tex); 
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1024,1024,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0, 1024, 1024, 0, -5000, 5000); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
glViewport(0, 0, 1024, 1024); 
glColor4f(1,1,1,1); 
glBegin(GL_TRIANGLES); 
    glTexCoord2f(0, 0); 
    glVertex2f(0, 0); 
    glTexCoord2f(1, 0); 
    glVertex2f(1024, 0); 
    glTexCoord2f(0, 1); 
    glVertex2f(0, 1024); 
glEnd(); 
glFlush(); 
glFinish(); 
unsigned char *dd = new unsigned char[1024*1024*4]; 
glBindTexture(GL_TEXTURE_2D, fbTexID); //I've tried calling glBindFramebuffer(GL_FRAMEBUFFER,0) before this bind - makes no difference 
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, dd); 
delete dd; 
+0

¿Dónde creas 'fbTexID'? ¿Dónde usas 'tex'? – genpfault

+0

Tanto fbTexID como tex son solo GLuints, definidos anteriormente. (En mi código actual son miembros de una estructura más grande, sustituí los nombres más simples en mi publicación aquí por simplicidad y claridad. Gracias. – RedMarbleGames

+0

Solo para lectores futuros y porque acabo de tropezar con esto: Multisampling y FBO podrían producir problemas, también. –

Respuesta

5

OK, respondió mi propia pregunta. Parece que la textura que genera como la superficie a la que se basa el búfer de trama debe generarse después de se genera el búfer de trama. Por lo tanto, esto funciona:

glGenFramebuffers... 
glBindFramebuffer... 
glGenTextures... 
glBindTexture... 
glTexParameterf etc. 
glFramebufferTexture2D... 

pero esto no es así:

glGenTextures... 
glBindTexture... 
glGenFramebuffers 
glBindFramebuffer... 
glFramebufferTexture2D... 

no veo esta dirigida en cualquier lugar, y parece sorprendente, pero mi código pasó de no trabajar a trabajar con sólo mover la generación de la textura.

1

Ésta es una prueba OBF que escribí hace algún tiempo:

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

#include <cmath> 
#include <iostream> 

using namespace std; 

namespace render 
{ 
    int width, height; 
    float aspect; 

    void init(); 
    void reshape(int width, int height); 
    void display(); 

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

    GLuint fb, color, depth; 
}; 

void idle(); 

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

    glutCreateWindow("FBO test"); 
    glutDisplayFunc(render::display); 
    glutReshapeFunc(render::reshape); 
    glutIdleFunc(idle); 

    glewInit(); 

    render::init(); 
    glutMainLoop(); 

    return 0; 
} 

void idle() 
{ 
    glutPostRedisplay(); 
} 

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 */ 
     throw "Framebuffer Error"; 
    } 
} 

namespace render 
{ 
    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_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); 

     CHECK_FRAMEBUFFER_STATUS(); 
    } 

    void reshape(int width, int height) 
    { 
     render::width=width; 
     render::height=height; 
     aspect=float(width)/float(height); 
     glutPostRedisplay(); 
    } 

    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; 

     glBindFramebuffer(GL_FRAMEBUFFER, 0); 

     glViewport(0,0, width, 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(); 
    } 
} 

Tal vez esta referencia ayuda

0

Aquí hay un "punto de referencia" FBO Me escribió una while ago. set_fbo_size() tiene una secuencia de creación que funciona para mí (TM).

///////////////////////////////////////////////////////////////////////////// 
// INCLUDES ///////////////////////////////////////////////////////////////// 

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

#include <iostream> 
#include <iomanip> 
#include <sstream> 

using namespace std; 


///////////////////////////////////////////////////////////////////////////// 
// CLASSES ////////////////////////////////////////////////////////////////// 

// http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average 
class ExpAvg 
{ 
public: 
    ExpAvg(float initial, unsigned int time_periods) : avg(initial), alpha(2.0f/(time_periods + 1)) {} 
    void Update(float nextval) { avg = alpha*nextval + (1.0f-alpha)*avg; } 
    float Get() { return avg; } 
private: 
    float avg; 
    float alpha; 
}; 

class gl2D 
{ 
public: 
    gl2D() { 
     int viewport[4]; 
     glGetIntegerv(GL_VIEWPORT, viewport); 
     glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); 
     gluOrtho2D(0, viewport[2], 0, viewport[3]); 
     glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); 
    } 
    ~gl2D() { 
     glMatrixMode(GL_PROJECTION); glPopMatrix(); 
     glMatrixMode(GL_MODELVIEW); glPopMatrix(); 
    } 
}; 


///////////////////////////////////////////////////////////////////////////// 
// GLOBALS ////////////////////////////////////////////////////////////////// 

int screen_width = 1024; 
int screen_height = 768; 
int mouse_x, mouse_y; 
bool mouse_left, mouse_right; 
float camera_angle_x = 45; 
float camera_angle_y = 45; 
float camera_distance = 0; 

int texture_width, texture_height; 
GLuint tex, fbo, rbo; // object IDs 


///////////////////////////////////////////////////////////////////////////// 
// UTILITIES //////////////////////////////////////////////////////////////// 

bool get_fbo_status() 
{ 
    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 
    switch(status) { 
    case GL_FRAMEBUFFER_COMPLETE_EXT: 
     cout << "Framebuffer complete." << endl; return true; 
    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: 
     cerr << "[ERROR] Attachment is NOT complete." << endl; return false; 
    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: 
     cerr << "[ERROR] No image is attached to FBO." << endl; return false; 
    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: 
     cerr << "[ERROR] Attached images have different dimensions." << endl; return false; 
    case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: 
     cerr << "[ERROR] Color attached images have different internal formats." << endl; return false; 
    case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: 
     cerr << "[ERROR] Draw buffer." << endl; return false; 
    case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: 
     cerr << "[ERROR] Read buffer." << endl; return false; 
    case GL_FRAMEBUFFER_UNSUPPORTED_EXT: 
     cerr << "[ERROR] Unsupported by FBO implementation." << endl; return false; 
    default: 
     cerr << "[ERROR] Unknow error." << endl; return false; 
    } 
} 

void gl_print(const char *str, int x, int y, void *font) 
{ 
    glPushAttrib(GL_ENABLE_BIT); 
    glDisable(GL_LIGHTING);  // need to disable lighting for proper text color 
    glDisable(GL_TEXTURE_2D); 
    glRasterPos2i(x, y);  // place text position 
    while(*str) glutBitmapCharacter(font, *str++); 
    glPopAttrib(); 
} 

void textured_cube() 
{ 
    glBegin(GL_QUADS); 
    glColor4f(1, 1, 1, 1); 

    // face v0-v1-v2-v3 
    glNormal3f(0,0,1); 
    glTexCoord2f(1, 1); glVertex3f(1,1,1); 
    glTexCoord2f(0, 1); glVertex3f(-1,1,1); 
    glTexCoord2f(0, 0); glVertex3f(-1,-1,1); 
    glTexCoord2f(1, 0); glVertex3f(1,-1,1); 

    // face v0-v3-v4-v5 
    glNormal3f(1,0,0); 
    glTexCoord2f(0, 1); glVertex3f(1,1,1); 
    glTexCoord2f(0, 0); glVertex3f(1,-1,1); 
    glTexCoord2f(1, 0); glVertex3f(1,-1,-1); 
    glTexCoord2f(1, 1); glVertex3f(1,1,-1); 

    // face v0-v5-v6-v1 
    glNormal3f(0,1,0); 
    glTexCoord2f(1, 0); glVertex3f(1,1,1); 
    glTexCoord2f(1, 1); glVertex3f(1,1,-1); 
    glTexCoord2f(0, 1); glVertex3f(-1,1,-1); 
    glTexCoord2f(0, 0); glVertex3f(-1,1,1); 

    // face v1-v6-v7-v2 
    glNormal3f(-1,0,0); 
    glTexCoord2f(1, 1); glVertex3f(-1,1,1); 
    glTexCoord2f(0, 1); glVertex3f(-1,1,-1); 
    glTexCoord2f(0, 0); glVertex3f(-1,-1,-1); 
    glTexCoord2f(1, 0); glVertex3f(-1,-1,1); 

    // face v7-v4-v3-v2 
    glNormal3f(0,-1,0); 
    glTexCoord2f(0, 0); glVertex3f(-1,-1,-1); 
    glTexCoord2f(1, 0); glVertex3f(1,-1,-1); 
    glTexCoord2f(1, 1); glVertex3f(1,-1,1); 
    glTexCoord2f(0, 1); glVertex3f(-1,-1,1); 

    // face v4-v7-v6-v5 
    glNormal3f(0,0,-1); 
    glTexCoord2f(0, 0); glVertex3f(1,-1,-1); 
    glTexCoord2f(1, 0); glVertex3f(-1,-1,-1); 
    glTexCoord2f(1, 1); glVertex3f(-1,1,-1); 
    glTexCoord2f(0, 1); glVertex3f(1,1,-1); 
    glEnd(); 
} 

bool set_fbo_size(int width, int height) 
{ 
    int max_size; 
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size); 
    if(width > max_size) return false; 
    if(height > max_size) return false; 

    texture_width = width; texture_height = height; 

    // create FBO 
    if(fbo) glDeleteFramebuffersEXT(1, &fbo); 
    glGenFramebuffersEXT(1, &fbo); 
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);  

    // create and attach a new texture as the FBO's color buffer 
    if(tex) glDeleteTextures(1, &tex); 
    glGenTextures(1, &tex); 
    glBindTexture(GL_TEXTURE_2D, tex); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0); 

    // create and attach a new depth buffer to currently bound FBO 
    if(rbo) glDeleteRenderbuffersEXT(1, &rbo); 
    glGenRenderbuffersEXT(1, &rbo); 
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo); 
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); 
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo); 

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // unbind fbo 
    if(!get_fbo_status()) exit(1); 
    return true; 
} 


///////////////////////////////////////////////////////////////////////////// 
// GLUT CALLBACKS /////////////////////////////////////////////////////////// 

void CB_Idle() 
{ 
    glutPostRedisplay(); 
} 

void CB_Reshape(int width, int height) 
{ 
    screen_width = width; 
    screen_height = height; 
    glViewport(0, 0, (GLsizei)width, (GLsizei)height); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(60.0f, (float)(width)/height, 1.0f, 1000.0f); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 

void CB_Mouse(int button, int state, int x, int y) 
{ 
    mouse_x = x; mouse_y = y; 
    if(button == GLUT_LEFT_BUTTON) 
     mouse_left = (state == GLUT_DOWN); 
    else if(button == GLUT_RIGHT_BUTTON) 
     mouse_right = (state == GLUT_DOWN); 
} 

void CB_Motion(int x, int y) 
{ 
    if(mouse_left) { 
     camera_angle_y += (x - mouse_x); 
     camera_angle_x += (y - mouse_y); 
     mouse_x = x; mouse_y = y; 
    } 
    if(mouse_right) { 
     camera_distance += (y - mouse_y) * 0.2f; 
     mouse_y = y; 
    } 
} 

void CB_Keyboard(unsigned char key, int x, int y) 
{ 
    static int drawMode = 0; 
    static int tex_size = 0; 
    bool ret = false; 

    switch(key) { 
    case 27: // ESCAPE 
     exit(0); 
     break; 
    case ' ': 
     while(!ret) { 
      tex_size = (tex_size+1) % 7; 
      switch(tex_size) { 
       case 0: ret = set_fbo_size(128,128); break; 
       case 1: ret = set_fbo_size(256,256); break; 
       case 2: ret = set_fbo_size(512,512); break; 
       case 3: ret = set_fbo_size(1024,1024); break; 
       case 4: ret = set_fbo_size(2048,2048); break; 
       case 5: ret = set_fbo_size(4096,4096); break; 
       case 6: ret = set_fbo_size(8192,8192); break; 
       default: ; break; 
      } 
     } 
     break; 
    default: 
     break; 
    } 
    glutPostRedisplay(); 
} 

void CB_Init() 
{ 
    GLenum err = glewInit(); 
    if(GLEW_OK != err) { 
     cerr << "Error: " << glewGetErrorString(err) << endl; 
     exit(1); 
    } 

    if(!GLEW_EXT_framebuffer_object) { 
     cerr << "Requires EXT_framebuffer_object" << endl; 
     exit(1); 
    } 

    tex = fbo = rbo = 0; 

    glShadeModel(GL_SMOOTH); 
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_LIGHTING); 
    glEnable(GL_TEXTURE_2D); 
    glEnable(GL_CULL_FACE); 

    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 
    glEnable(GL_COLOR_MATERIAL); 
    glClearColor(0, 0, 0, 0); 

    GLfloat lightKa[] = {.2f, .2f, .2f, 1.0f}; // ambient light 
    GLfloat lightKd[] = {.7f, .7f, .7f, 1.0f}; // diffuse light 
    GLfloat lightKs[] = {1, 1, 1, 1};   // specular light 
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightKa); 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightKd); 
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightKs); 
    float lightPos[4] = {0, 0, 20, 1};   // positional light 
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos); 
    glEnable(GL_LIGHT0); 

    set_fbo_size(128, 128); 
} 

void CB_Exit() 
{ 
    glDeleteTextures(1, &tex); 
    glDeleteFramebuffersEXT(1, &fbo); 
    glDeleteRenderbuffersEXT(1, &rbo); 
} 

void CB_Display() 
{ 
    static ExpAvg ft_fbo(0, 19); 
    static ExpAvg ft_overall(0, 19); 

    int before = glutGet(GLUT_ELAPSED_TIME); 

    // compute rotation angle 
    const float ANGLE_SPEED = 90; // degree/s 
    float angle = ANGLE_SPEED * (glutGet(GLUT_ELAPSED_TIME)/1000.0f); 

    // render using fbo ///////////////////////////////////////////// 
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // bind fbo 

    // adjust viewport and projection matrix to texture dimension 
    glViewport(0, 0, texture_width, texture_height); 
    glMatrixMode(GL_PROJECTION); glLoadIdentity(); 
    gluPerspective(60.0f, (float)(texture_width)/texture_height, 1.0f, 100.0f); 
    glMatrixMode(GL_MODELVIEW); glLoadIdentity(); 

    // clear buffer 
    glClearColor(1, 1, 1, 0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glTranslatef(0,0,-3); 
    glPushMatrix(); 
    glRotatef(angle*0.5f, 1, 0, 0); 
    glRotatef(angle, 0, 1, 0); 
    glRotatef(angle*0.7f, 0, 0, 1); 

    // set up teapot colors 
    float shininess = 15.0f; 
    float diffuseColor[3] = {0.929524f, 0.796542f, 0.178823f}; 
    float specularColor[4] = {1.00000f, 0.980392f, 0.549020f, 1.0f}; 
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); // range 0 ~ 128 
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor); 
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 
    glColor3fv(diffuseColor); 

    glBindTexture(GL_TEXTURE_2D, 0); 
    glFrontFace(GL_CW); 
    glutSolidTeapot(1.0); 
    glFrontFace(GL_CCW); 
    glPopMatrix(); 

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // unbind fbo 
    glFinish(); 

    ft_fbo.Update((float)(glutGet(GLUT_ELAPSED_TIME) - before)); 

    // normal rendering /////////////////////////////////// 

    // back to normal viewport and projection matrix 
    glViewport(0, 0, screen_width, screen_height); 
    glMatrixMode(GL_PROJECTION); glLoadIdentity(); 
    gluPerspective(60.0f, (float)(screen_width)/screen_height, 1.0f, 100.0f); 
    glMatrixMode(GL_MODELVIEW); glLoadIdentity(); 

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

    glTranslatef(0,0,-4); 
    glPushMatrix(); 
    glTranslatef(0, 0, camera_distance); 
    glRotatef(camera_angle_x, 1, 0, 0); 
    glRotatef(camera_angle_y, 0, 1, 0); 

    // draw a cube with the dynamic texture 
    glBindTexture(GL_TEXTURE_2D, tex); 
    textured_cube();  
    glPopMatrix(); 

    { 
     gl2D two_dee; // set 2D mode 
     glDisable(GL_DEPTH_TEST); 
     stringstream ss; 
     glColor3f(1,1,0); 
     ss << fixed << setprecision(3); 
     int pos = 1; 

     ss.str(""); ss << "Texture size: " << texture_width << "x" << texture_height; 
     gl_print(ss.str().c_str(), 10, screen_height - (pos++ * 20), GLUT_BITMAP_8_BY_13); 
     ss.str(""); ss << "Overall frame time: " << ft_overall.Get() << " ms"; 
     gl_print(ss.str().c_str(), 10, screen_height - (pos++ * 20), GLUT_BITMAP_8_BY_13); 
     ss.str(""); ss << " FBO frame time: " << ft_fbo.Get() << " ms"; 
     gl_print(ss.str().c_str(), 10, screen_height - (pos++ * 20), GLUT_BITMAP_8_BY_13); 
     ss.str(""); ss << "Press space to change texture size; mouse moves/zooms cube"; 
     gl_print(ss.str().c_str(), 10, 10, GLUT_BITMAP_8_BY_13); 
     glEnable(GL_DEPTH_TEST); 
    } 

    glutSwapBuffers(); 
    ft_overall.Update((float)(glutGet(GLUT_ELAPSED_TIME) - before)); 
} 


///////////////////////////////////////////////////////////////////////////// 
// MAIN ///////////////////////////////////////////////////////////////////// 

int main(int argc, char *argv[]) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); 
    glutInitWindowSize(screen_width, screen_height); 
    glutInitWindowPosition(100, 100); 
    glutCreateWindow("FBO Test"); 

    glutDisplayFunc(CB_Display); 
    glutIdleFunc(CB_Idle); 
    glutReshapeFunc(CB_Reshape); 
    glutKeyboardFunc(CB_Keyboard); 
    glutMouseFunc(CB_Mouse); 
    glutMotionFunc(CB_Motion); 
    atexit(CB_Exit); 

    CB_Init(); 
    glutMainLoop(); 
    return 0; 
} 
9

¡Tu textura no funcionó porque estaba encuadernada! No puede tener un encuadernado textura trabajo en un FBO como un rendertarget! Esto es algo que no está muy documentado, pero tiene sentido cuando lo piensas Los desarrolladores de controladores también necesitan algunas protecciones, en caso de que hagas algo extraño como leer y escribir en la misma textura al mismo tiempo

Cuestiones relacionadas