2013-01-09 16 views
0

我正在寫一個2D OpenGL引擎,我最近包括一個framebuffer包裝類,我用它來在運行時生成紋理圖集。它工作得非常好,性能提高很多,直到我在筆記本電腦的集成顯卡上測試它爲止。glCheckFramebufferStatus返回零集成圖形

顯然,在集成圖形上運行時,glCheckFramebufferStatus返回零。不,它不返回GL_FRAMEBUFFER_UNSUPPORTED。它返回ZERO。我真的不認爲我的集成顯卡不支持幀緩衝區,因爲它們不是那麼古老。 我也嘗試延遲幀緩衝區的初始化,以在主GLUT循環內完成它,但它沒有解決問題。我也嘗試使用framebufferEXT而不是framebuffer,但沒有任何改變。 如果我忽略這個錯誤,當我嘗試繪製framebuffer的紋理時,它不繪製任何東西。 另外:如果視頻卡不支持幀緩衝區,我應該回退到什麼位置,而且我絕對需要它們?

這裏是我的幀緩衝區類的代碼:

framebuffer.hpp:

#pragma once 

#include "sprite.hpp" 

namespace core 
{ 
    class framebuffer 
    { 
    public: 
     framebuffer(); 
     virtual ~framebuffer(); 
     bool initialized(); 
     void initialize(int width, int height); 
     int width(); 
     int height(); 
     sprite *getframe(); 
     void begin(); 
     void end(); 

    protected: 
     GLubyte *pixels; 
     int w, h; 
     GLuint id, tex; 
     sprite frame; 
    }; 
} 

framebuffer.cpp:

#include "framebuffer.hpp" 
#include <iostream> 
#include <cmath> 

namespace core 
{ 
    framebuffer::framebuffer() 
     : pixels(NULL), w(0), h(0) 
    { 
     // empty 
    } 

    framebuffer::~framebuffer() 
    { 
     glDeleteFramebuffers(1, &id); 

     if (pixels) 
     { 
      // TODO: convert to smart pointer once everything works ok 
      delete [] pixels; 
      pixels = NULL; 
     } 
    } 

    bool framebuffer::initialized() 
    { 
     return w != 0 && h != 0; 
    } 

    void framebuffer::initialize(int width, int height) 
    { 
     w = width; 
     h = height; 
     //std::cout << "framebuffer.initialize: w = " << w << "\nh = " << h << std::endl; 
    } 

    int framebuffer::width() 
    { 
     return w; 
    } 

    int framebuffer::height() 
    { 
     return h; 
    } 

    sprite *framebuffer::getframe() 
    { 
     GLuint oldtex; 

     glBindFramebuffer(GL_FRAMEBUFFER, id); 
     glEnable(GL_TEXTURE_RECTANGLE_ARB); 
     glGetIntegerv(GL_TEXTURE_RECTANGLE_ARB, reinterpret_cast<GLint *>(&oldtex)); // store old bound texture 
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); // bind framebuffer texture 
     glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // get framebuffer pixels 
     frame.fromtexture(tex, GL_RGBA, w, h, GL_RGBA, pixels); // create a sprite object from raw pixels 
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, oldtex); // re-bind the old texture 
     glDisable(GL_TEXTURE_RECTANGLE_ARB); 
     glBindFramebuffer(GL_FRAMEBUFFER, 0); 

     return &frame; 
    } 

    void framebuffer::begin() // call this to start drawing to the framebuffer 
    { 
     if (!pixels) 
     { 
      GLenum result; 

      // initialize the frame buffer if it isn't already 

      glGenTextures(1, &tex); // generate the texture that will store the frame 

      glEnable(GL_TEXTURE_RECTANGLE_ARB); 
      glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); 

      // reserve video memory for the framebuffer image 
      pixels = new GLubyte[w * h * 4]; 
      glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
      glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

      glGenFramebuffers(1, &id); // create frame buffer 
      glBindFramebuffer(GL_FRAMEBUFFER, id); 

      // assign the texture to the framebuffer 
      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0); 

      result = glCheckFramebufferStatus(GL_FRAMEBUFFER); 

      if (result != GL_FRAMEBUFFER_COMPLETE) 
      { 
       if (result == GL_FRAMEBUFFER_UNSUPPORTED) 
       { 
        // todo: handle errors as exceptions and cleanup everything gracefully 
        std::cout << "framebuffer.begin: your video card doesn't seem to support framebuffers" << std::endl; 
        exit(0); 
       } 

       std::cout << "framebuffer.begin: failed to initialize framebuffer | error " << result << std::endl; 
       exit(0); 
      } 

      glDisable(GL_TEXTURE_RECTANGLE_ARB); 
     } 

     glBindFramebuffer(GL_FRAMEBUFFER, id); // bind the framebuffer 
     glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); 
     glViewport(0, 0, w, h); // adjust viewport to the fbo's size 
     glLoadIdentity(); // reset modelview matrix 

     glMatrixMode(GL_PROJECTION); 
     glPushMatrix(); // store the non-flipped matrix 
     glLoadIdentity(); 
     glOrtho(0, w, 0, h, -1, 1); // stupid fbo's flipping stuff upside down 

     glMatrixMode(GL_MODELVIEW); 
     glEnable(GL_BLEND); 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    } 

    void framebuffer::end() // call this to stop drawing to the framebuffer 
    { 
     glPopAttrib(); 
     glBindFramebuffer(GL_FRAMEBUFFER, 0); 
     glMatrixMode(GL_PROJECTION); 
     glPopMatrix(); // restore old matrix 
     glMatrixMode(GL_MODELVIEW); 
    } 
} 

回答

4

從官方文檔:

「的迴歸如果綁定到目標的幀緩衝區已完成,則值爲GL_FRAMEBUFFER_COMPLETE明智的,返回值被確定如下:

...

此外,如果發生錯誤,則返回0「。

所以你有它,出現錯誤。也許glGetError有額外的信息。

如果不支持幀緩衝區,並且您希望將其用於渲染到紋理,則可以看看是否支持pbuffers,否則glReadPixels?

+0

嗯glError也返回零。我會試着看看它是不是被支持的GL_TEXTURE_RECTANGLE_ARB,並且編寫了一個glReadPixels的後備實現,即使在superold卡上也可以工作。 –

+0

好吧,它看起來像GL_TEXTURE_RECTANGLE_ARB工作正常,我想我會看看如果我可以編碼類似幀緩衝的行爲,而不使用幀緩衝區來回退。 –

1

我假設目標圖形卡可能不支持GL_TEXTURE_RECTANGLE_ARB。在這種情況下,您可能不得不切換到2紋理的冪。