2012-03-02 2 views
4

Я склонен обертывать объекты OpenGL в своих классах. В 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(); 

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

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

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

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

ответ

5

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

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 живет только в объеме и вызывает его деструктор (муравей отвязать метод соответственно) автоматически, как только объем остается.

EDIT:

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

+0

Возможно возникновение проблем при наличии нескольких текстур, которые пользователь хочет установить последовательно. Поэтому TextureContext не должен устанавливать текстуру «0», а тот, который ранее использовался (получить с помощью соответствующего вызова glGet). – SigTerm

+0

Я не профессиональный разработчик OpenGL, я попытался ответить на вопрос с более общей (C++-программирования) точки зрения. – Constantinius

2

Проблема здесь в том, что я хочу, чтобы избежать привязки() и UNBIND() функции

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

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

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

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

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

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

Есть две потенциальные проблемы с этим подходом, хотя:

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

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

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

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

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

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

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

Смежные вопросы