glCheckFramebufferStatus在集成图形上返回零

时间:2013-01-09 14:43:38

标签: c++ opengl fbo

我正在编写一个2D OpenGL引擎,我最近加入了一个framebuffer包装类,用于在运行时生成纹理图集。它在我的笔记本电脑的集成显卡上进行了测试后,效果非常好并且性能得到了很大提升。

显然,当在集成图形上运行时,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);
    }
}

2 个答案:

答案 0 :(得分:4)

来自官方文件:

“如果绑定到目标的帧缓冲完成,则返回值为GL_FRAMEBUFFER_COMPLETE。否则,返回值的确定如下:

...

此外,如果发生错误,则返回零。“

所以你有它,发生了一个错误。也许glGetError有其他信息。

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

答案 1 :(得分:1)

我假设目标显卡可能不支持GL_TEXTURE_RECTANGLE_ARB。在这种情况下,您可能必须切换到2纹理的力量。