0

私は 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);
    }
}
4

2 に答える 2

4

公式ドキュメントから:

「ターゲットにバインドされたフレームバッファが完全な場合、戻り値は GL_FRAMEBUFFER_COMPLETE です。それ以外の場合、戻り値は次のように決定されます。

...

また、エラーが発生した場合はゼロが返されます。」

エラーが発生しました。おそらく glGetError に追加情報があります。

フレームバッファがサポートされておらず、テクスチャへのレンダリングに使用したい場合は、pbuffers がサポートされているかどうかを確認できます。

于 2013-01-09T14:55:06.823 に答える
1

ターゲットのグラフィック カードが GL_TEXTURE_RECTANGLE_ARB をサポートしていない可能性があると思います。その場合、テクスチャの 2 乗に切り替える必要があるかもしれません。

于 2013-01-09T15:01:13.513 に答える