Как настроить и использовать постоянный объект кадрового буфера для выбора уникального цвета? - PullRequest
2 голосов
/ 12 декабря 2011

Этот вопрос сильно изменился с тех пор, как его впервые спросили, потому что я не понимал, как мало я знал о том, что спрашиваю. И одна проблема, касающаяся изменения размера, омрачала мою способность понимать более крупную проблему создания и использования кадрового буфера. Если вам просто нужен кадровый буфер, перейдите к ответу ... для истории, я оставил оригинальный вопрос без изменений.


Новичок вопрос. У меня есть проект GL, над которым я работаю, и пытаюсь разработать стратегию выбора, используя уникальные цвета. Большинство дискуссий / руководств вращаются вокруг рисования выбираемых объектов в заднем буфере и вычисления выбора, когда пользователь щелкает где-то. Я хочу, чтобы буфер выделения был постоянным, чтобы я мог быстро рассчитывать попадания при любом движении мыши и не перерисовывать буфер выбора, пока не изменится отображение или геометрия объекта.

Казалось бы, лучшим выбором будет выделенный объект фреймбуфера. Вот моя проблема. Помимо того, что я совершенно новичок в объектах кадрового буфера, мне любопытно. Мне лучше удалить и воссоздать объект frambuffer на событиях размера окна или создать его один раз при максимальном разрешении экрана, а затем использовать то, что может быть только небольшой его частью. Мои события работают должным образом, чтобы вызывать подпрограмму framebuffer только один раз для того, что может быть потоком многих событий изменения размера, но я обеспокоен фрагментацией памяти GPU или другими проблемами, воссоздающими буфер, возможно, много раз.

Кроме того, будет ли объект кадрового буфера (текстура и глубина) даже вести себя согласованно при использовании только его части.

Идеи? Я полностью вне базы?

EDIT: У меня есть мой объект framebuffer, настроенный и работающий теперь с размерами окон, и я изменяю его размер с помощью окна. Я думаю, что моя проблема была классической "переосмысление". Хотя, безусловно, верно, что по возможности следует избегать удаления / воссоздания объектов на графическом процессоре. Пока он обрабатывается правильно, размеры относительно невелики.

Что я нашел, так это установить флаг и пометить буфер как грязный при изменении размера окна, затем дождаться обычного события мыши, прежде чем изменять размер буфера. Обычная мышь вводит или перемещает сигналы, вы перетаскиваете окно до нужного размера и готовы вернуться к работе. Буферы воссоздали один раз. Кроме того, поскольку размер основного кадрового буфера обычно изменяется для каждого события размера окна в конвейере, вполне понятно, что изменение размера кадрового буфера не приведет к прожиганию дыры в вашем ноутбуке.

Кризис предотвращен, продолжайте!

1 Ответ

3 голосов
/ 14 декабря 2011

Я упомянул в вопросе, что я переосмыслил проблему.Основная причина этого в том, что проблема была больше, чем вопрос.Проблема была в том, что я не только не знал, как управлять кадровым буфером, но и не знал, как его создать.Вариантов так много, и ни один из веб-ресурсов, похоже, не посвящен тому, что я пытался сделать, поэтому я боролся с этим.Если вы также боретесь с тем, как перенести процедуру выбора в уникальную цветовую схему с постоянным буфером, или просто в полном недоумении по поводу кадровых буферов и закадрового рендеринга, читайте дальше.

У меня естьмой холст OpenGL определен как класс, и мне нужен «объект буфера выбора».Я добавил это к закрытым членам класса.

unsigned int sbo;
unsigned int sbo_pixels;
unsigned int sbo_depth;
bool sbo_dirty;
void setSelectionBuffer();

И в моем обработчике изменения размера, и в инициализации OpenGL я установил грязный флаг для буфера выбора.

sbo_dirty = true;

В началев моем обработчике мыши я проверяю грязный бит и setSelectionBuffer();, если необходимо.

if(sbo_dirty) setSelectionBuffer();

Это решает мои первоначальные опасения по поводу множественного удаления / воссоздания буфера.Размер буфера не изменяется до тех пор, пока указатель мыши не войдет в клиентскую область после изменения размера окна.Теперь мне просто нужно выяснить буфер ...

void BFX_Canvas::setSelectionBuffer()
{
    if(sbo != 0) // delete current selection buffer if it exists
    {
        glDeleteFramebuffersEXT(1, &sbo);
        glDeleteRenderbuffersEXT(1, &sbo_depth);
        glDeleteRenderbuffersEXT(1, &sbo_pixels);
        sbo = 0;
    }

    // create depth renderbuffer
    glGenRenderbuffersEXT(1, &sbo_depth);
    // bind to new renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, sbo_depth);
    // Set storage for depth component, with width and height of the canvas
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, canvas_width, canvas_height);
    // Set it up for framebuffer attachment
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, sbo_depth);
    // rebind to default renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

    // create pixel renderbuffer
    glGenRenderbuffersEXT(1, &sbo_pixels);
    // bind to new renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, sbo_pixels);
    // Create RGB storage space(you might want RGBA), with width and height of the canvas
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, canvas_width, canvas_height);
    // Set it up for framebuffer attachment
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, sbo_pixels);
    // rebind to default renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

    // create framebuffer object
    glGenFramebuffersEXT(1, &sbo);
    // Bind our new framebuffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sbo);
    // Attach our pixel renderbuffer
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, sbo_pixels);
    // Attach our depth renderbuffer
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, sbo_depth);

    // Check that the wheels haven't come off
    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    {
        // something went wrong
        // Output an error to the console
        cout << "Selection buffer creation failed" << endl;
        // restablish a coherent state and return
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        sbo_dirty = false;
        sbo = 0;
        return;
    }

    // rebind back to default framebuffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    // cleanup and go home
    sbo_dirty = false;
    Refresh(); // force a screen draw
}

Затем в конце своей функции рендеринга я проверяю sbo и обращаюсь к нему, если он кажется готовым.

if((sbo) && (!sbo_dirty)) // test that sbo exists and is ready
{
    // disable anything that's going to affect color such as...
    glDisable(GL_LIGHTING);
    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_POINT_SMOOTH);
    glDisable(GL_POLYGON_SMOOTH);

    // bind to our selection buffer
    // it inherits current transforms/rotations
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sbo);
    // clear it
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // draw selectables
    // for now i'm just drawing my object
    if (object) object->draw();

    // reenable that stuff from before
    glEnable(GL_POLYGON_SMOOTH);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_LIGHTING);

    // blit to default framebuffer just to see what's going on
    // delete this bit once selection is setup and working properly.
    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, sbo);
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
    glBlitFramebufferEXT(0, 0, canvas_width, canvas_height,
                         0, 0, canvas_width/3, canvas_height/3,
                         GL_COLOR_BUFFER_BIT, GL_LINEAR);

    // We're done here, bind back to default buffer.
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

Это дает мне это ...

screenshot

На данный момент я считаю, что все готово для рисования выбираемых элементов в буфере, ииспользовать события перемещения мыши для проверки попаданий.И у меня есть миниатюра на экране, чтобы показать, как взрываются плохие вещи.

Надеюсь, это помогло бы вам так же, как и мне неделю назад.:)

...