glCheckFramebufferStatus возвращает ноль на интегрированную графику

Я пишу 2D OpenGL-движок, и недавно я включил класс оболочки фреймбуфера, который я использую для создания атласа текстуры во время выполнения. Он отлично работал и улучшил производительность, пока я не протестировал его на интегрированной графике моего ноутбука.

По-видимому, при работе на интегрированной графике 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 
#include 

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(&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);
    }
}
0
nl ja de

2 ответы

Из официальной документации:

«Возвращаемое значение - GL_FRAMEBUFFER_COMPLETE, если фреймбуфер, привязанный к цели, завершен. В противном случае возвращаемое значение определяется следующим образом:

...

Кроме того, если возникает ошибка, возвращается ноль. "

Итак, у вас есть ошибка, произошла ошибка. Возможно, glGetError имеет дополнительную информацию.

Если фреймбуферы не поддерживаются, и вы хотите использовать его для рендеринга в текстуру, вы можете увидеть, поддерживаются ли pbuffers, иначе glReadPixels?

4
добавлено
Hmm glError также возвращает ноль. Я попытаюсь посмотреть, не является ли это GL_TEXTURE_RECTANGLE_ARB, который не поддерживается и кодирует резервную реализацию с помощью glReadPixels, которые должны работать даже на картах с надстройкой.
добавлено автор Francesco Noferi, источник
Ну, похоже, что GL_TEXTURE_RECTANGLE_ARB отлично работает, я думаю, я посмотрю, смогу ли я закодировать поведение, подобное кадру, без использования фреймбуферов для возврата.
добавлено автор Francesco Noferi, источник

Я предполагаю, что целевая видеокарта может не поддерживать GL_TEXTURE_RECTANGLE_ARB. В этом случае вам может потребоваться переключиться на 2 текстуры.

1
добавлено
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

pro.graphon (and gamedev)
pro.graphon (and gamedev)
389 участник(ов)

Обсуждаем стандарты консорциума Khronos: OpenGL, OpenCL и пр., предлагаем различные работы, туторы, интересные материалы по этим стандартам (и помечаем их тегами). Правила чата и инфо по системе тегов – /rules. Реклама только по согласованию с @AlexFails.

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest