我正在寫一個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);
}
}
嗯glError也返回零。我會試着看看它是不是被支持的GL_TEXTURE_RECTANGLE_ARB,並且編寫了一個glReadPixels的後備實現,即使在superold卡上也可以工作。 –
好吧,它看起來像GL_TEXTURE_RECTANGLE_ARB工作正常,我想我會看看如果我可以編碼類似幀緩衝的行爲,而不使用幀緩衝區來回退。 –