2011-09-06 96 views
5

在Mac上,我有一個OpenGL設置,除了幀緩衝區 - 紋理工作等,還可以工作得很好。所以我知道紋理處於啓用狀態,我有一個有效的上下文等,所有作品完美無瑕,直到我嘗試創建幀緩衝區。OpenGL framebuffer:可以清除它,但不能繪製它

我用glGenFramebuffers,glBindFramebuffer和glFramebufferTexture2D創建了一個幀緩衝區,glCheckFramebufferStatus返回GL_FRAMEBUFFER_COMPLETE。如果我然後調用glClear,然後調用glGetTexImage,則返回的數據顯示glClear正如其應該那樣作用於綁定到幀緩衝區的紋理。我可以將glClearColor設置爲任何我想要的,glClear正確設置紋理數據。

但這就是好消息停止的地方。無論我使用VBOs還是使用glBegin/glEnd,我都無法在framebuffer中繪製任何東西。來自紋理綁定到幀緩衝區的紋理數據不受繪製調用的影響(儘管glClear結果仍然出現)。即使我在glGetTexImage調用之前調用glFlush和glFinish,也是如此。另外,對於我的任何調用,glGetError都沒有返回任何錯誤。

我已經在下面發佈了一些示例代碼,我在程序中的相關位置添加了一些示例代碼,以便嘗試解決此問題,以防給任何人一個想法。 (這不包括glClear調用,但我知道在同一點單獨的測試,那工作正常)。

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

你在哪裏創建'fbTexID'?你在哪裏使用'tex'? – genpfault

+0

fbTexID和tex都只是前面定義的GLuints。 (在我的實際代碼中,它們是更大結構的成員;爲了簡單和清晰起見,我在此處用簡單的名稱代替了此處的文章)謝謝 – RedMarbleGames

+0

僅供未來的讀者使用,因爲我偶然發現:多采樣和FBO可能產生問題也是如此。 –

回答

5

好的,回答了我自己的問題。看起來你生成的紋理是幀緩衝區繪製的表面,必須在產生幀緩衝區後生成。所以,這個工程:

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

但這並不:

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

我沒有看到這個解決任何地方,似乎令人驚訝,但我的代碼無法正常工作時通過移動只是去工作紋理的生成。

1

這是一個FBO測試我寫了前段時間:

#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(); 
    } 
} 

也許這有助於參考

0

這裏有一個FBO 「基準」 我寫了一個while agoset_fbo_size()具有Works For Me(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

你的紋理不工作,因爲它被綁定! 你不能有一個綁定作爲一個rendertarget FBO的紋理工作! 這是沒有很好記錄的東西,但是當你想到它時有意義 驅動程序開發人員也需要一些保護措施,以防萬一你做了一些奇怪的事情,如同時讀取和寫入相同的紋理

相關問題