私は 2D OpenGL エンジンを作成しており、最近、実行時にテクスチャ アトラスを生成するために使用するフレームバッファ ラッパー クラスを含めました。ラップトップの統合グラフィックスでテストするまでは、非常にうまく機能し、パフォーマンスが大幅に向上しました。
どうやら、統合グラフィックスで実行している場合、glCheckFramebufferStatus はゼロを返します。いいえ、GL_FRAMEBUFFER_UNSUPPORTED を返しません。ゼロを返します。フレームバッファはそれほど古くないので、統合グラフィックスがフレームバッファをサポートしていないとは本当に思いません。また、メインの GLUT ループ内でフレームバッファの初期化を遅らせようとしましたが、問題は解決しませんでした。また、framebuffer の代わりに framebufferEXT を使用してみましたが、何も変わりませんでした。エラーを無視すると、フレームバッファのテクスチャを描画しようとしても何も描画されません。また、ビデオ カードがフレームバッファをサポートしておらず、絶対に必要な場合は、何にフォールバックすればよいですか?
私のフレームバッファクラスのコードは次のとおりです。
フレームバッファ.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;
};
}
フレームバッファ.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);
}
}