glCheckFramebufferStatus在集成图形上返回零

glCheckFramebufferStatus returns zero on integrated graphics

本文关键字:返回 图形 集成 glCheckFramebufferStatus      更新时间:2023-10-16

我正在编写一个2D OpenGL引擎,我最近包含了一个framebuffer包装类,我使用它在运行时生成纹理图集。它工作得非常好,性能也有了很大的提高,直到我在笔记本电脑的集成显卡上进行了测试。

显然,当在集成图形上运行时,glCheckFramebufferStatus返回零。不,它不返回GL_FRAMEBUFFER_UNSUPPORTED。它返回0。我真的不认为我的集成图形不支持帧缓冲区,因为它们不是那么老。我还尝试延迟framebuffer的初始化,以便在主GLUT循环中进行初始化,但这并没有解决问题。我还尝试使用framebufferEXT而不是framebuffer,但没有任何改变。如果我忽略这个错误,当我尝试绘制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);
    }
}

来自官方文档:

"如果绑定到目标的帧缓冲区已经完成,返回值是GL_FRAMEBUFFER_COMPLETE。否则,返回值确定如下:

另外,如果发生错误,返回0。"

就这样,出错了。也许glGetError有其他信息

如果framebuffers不支持,你想使用它的渲染到纹理,你可以看看是否支持pbuffers,否则glReadPixels?

我假设目标显卡可能不支持GL_TEXTURE_RECTANGLE_ARB。在这种情况下,你可能需要切换到2次的纹理