Автоматическое связывание в обёртке объекта OpenGL - PullRequest
4 голосов
/ 02 марта 2012

Я склонен оборачивать объекты OpenGL в свои собственные классы. В OpenGL есть концепция связывания, где вы связываете свой объект, что-то делаете с ним, а затем отвязываете его. Например, текстура:

 glBindTexture(GL_TEXTURE_2D, TextureColorbufferName);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
 glBindTexture(GL_TEXTURE_2D, 0);

Упаковка будет выглядеть примерно так:

texture->bind();
    texture->setParameter(...);
    texture->setParameter(...);
texture->unBind();

Проблема здесь в том, что я хочу избежать функций bind () и unBind (), а вместо этого просто иметь возможность вызывать методы set, и GLObject будет связан автоматически.

Я мог бы просто сделать это в каждой реализации метода:

public void Texture::setParameter(...)
{
    this.bind();
    // do something
    this.unBind();
}

Хотя тогда я должен делать это для каждого добавленного метода! Есть ли лучший способ, чтобы он выполнялся автоматически до и после добавления каждого метода?

Ответы [ 3 ]

5 голосов
/ 02 марта 2012

Может быть, здесь может помочь контекстный объект. Рассмотрим этот маленький объект:

class TextureContext {
public:
    TextureContext(char* texname) {
        glBindTexture(GL_TEXTURE_2D, texname);
    }
    ~TextureContext() {
        glBindTexture(GL_TEXTURE_2D, 0);
    }
};

Этот объект теперь используется в области видимости:

{
    TextureContext mycont(textname);
    mytexture->setParameter(...);
    mytexture->setParameter(...);
    mytexture->setParameter(...);
}

объект mycont живет только в области видимости и вызывает его деструктор (и соответственно метод unbind) автоматически после выхода из области видимости.

РЕДАКТИРОВАТЬ :

Возможно, вы можете настроить класс TextureContext так, чтобы вместо него в конструкторе использовался ваш экземпляр Texture, и он получает само имя текстуры перед привязкой текстуры.

2 голосов
/ 02 марта 2012

Проблема в том, что я хочу избежать функций bind () и unBind ()

Скорее всего, вы не сможете полностью от них избавиться.Для glTexImage2D потребуется bind / unBind (или блокировка / разблокировка, если вы используете имена в стиле DirectX)

Я мог бы просто сделать это в каждой реализации метода:

Вы не должнысделать это, потому что вы получите значительное снижение производительности.Это называется "государственная разборка", если я правильно помню.Если вам нужно изменить несколько параметров, вы должны изменить их все за один раз.Вызов «bind» / «unbind» часто будет крайне неэффективным и не рекомендуется в рекомендациях по производительности, которые я видел (например, DirectX SDK, документация nvidia, случайные документы GDC и т. Д.).

Есть лилучше, так что это делается автоматически до и после каждого добавленного метода?

Да, есть.Кэшируйте множественные изменения состояния и задерживайте фактические вызовы OpenGL, пока они не станут абсолютно необходимыми.

Т.е. если ваша программа запрашивает установку фильтра Min, фильтра Mag, wrap_s, wrap_t и других параметров для glTexParameter, и ваша текстура неВ настоящее время не привязан к какой-либо стадии texutre, не устанавливайте параметры сейчас.Сохраните их во внутреннем списке (в пределах этой конкретной текстуры) и установите их все сразу при следующем связывании текстуры.Или когда список достигает определенного размера, или когда пользователь вызывает glGetTexParameter.Когда пришло время установить параметры, связать текстуру, установить параметры и отсоединить ее, если это необходимо.

Однако при таком подходе есть две потенциальные проблемы:

  1. Время, затрачиваемое наизменение состояния текстуры может стать немного непредсказуемым.(потому что вы не будете уверены, когда именно будет выполнен фактический вызов OpenGL).
  2. Возможно, будет сложнее обнаружить ошибки OpenGL с помощью этого метода.
  3. Если внутренний список использует динамически выделяемую память и часто вызывает new / delete, это может привести к узкому месту, поскольку вызовы new / delete могут быть медленными.Эту проблему можно решить с помощью кругового буфера фиксированного размера для этого внутреннего списка.
1 голос
/ 02 марта 2012

Я склонен оборачивать объекты OpenGL в их собственные классы.

Парень идет к врачу и говорит: «Больно, когда я так поднимаю руку». Итак, доктор говорит: «Тогда перестань так поднимать руку».

Ваша проблема в том, что вы пытаетесь предоставить объектно-ориентированный интерфейс для системы, не объектно-ориентированной. Это закончится только слезами и / или болью.

Гораздо лучшим решением было бы поднять уровень вашей абстракции. Вместо того, чтобы оборачивать объекты OpenGL напрямую, оберните ваш графический API. У вас может быть какое-то внешнее понятие «текстура», в котором будет храниться объект текстуры OpenGL, но вы не станете предоставлять функции, которые изменяют параметры этой текстуры напрямую. Или даже косвенно.

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

В качестве альтернативы, фильтрация (и обертка) должны быть частью конструктора объекта, фиксированное значение устанавливается во время создания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...