Разработка класса шейдера

С тех пор, как я начал изучать OpenGL, я подумал, что с таким же успехом напишу небольшой фреймворк C ++ (для себя), чтобы избежать тошноты, которую, очевидно, вызывает чрезмерное использование кода C-ish. :) Поскольку я собираюсь придерживаться Qt, фреймворк использует некоторые классы Qt.

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

class Shader
{
public:
    //create a shader with no source code 
    explicit Shader(GLenum shaderType);
    //create a shader with source code and compile it
    Shader(GLenum shaderType, const QString& sourceCode);
    //create a shader from source file and compile it
    Shader(GLenum shaderType, QFile& sourceFile);
    ~Shader();

    //change the source code and recompile
    void Source(QFile& sourceFile);
    void Source(const QString& sourceCode);

    GLuint get() const; //get the handle

private:
    //common part for creation in different constructors
    void createShader(GLenum shaderType); 
    //compile
    void compile();

private:
    GLuint handle;
};

Должно быть довольно очевидно, что делают разные функции. Каждый вызывает соответствующие процедуры OpenGL, проверяет наличие ошибок и выдает исключения в случае сбоя. Конструктор вызывает glCreateShader . А теперь самое сложное. Деструктору необходимо вызвать glDeleteShader (handle); , но в этом случае у меня возникнет дилемма:

Вариант 1: Отключить присваивание и копирование. У этого есть преимущество, заключающееся в избежании подсчета ссылок, и недостаток, заключающийся в необходимости использования shared_pointers для помещения их в векторы и передачи в целом.

Вариант 2: Включить подсчет ссылок. Это имеет очевидный положительный момент, поскольку позволяет копировать и, следовательно, хранить в контейнерах (которые мне понадобятся позже, чтобы передать программе ряд шейдеров). Обратной стороной является следующее:

Shader s1(GL_VERTEX_SHADER, QFile("MyVertexShader.vp"));
Shader s2(s1);
s2.Source(QFile("MyOtherVertexShader.vp"));

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

Q1: Прокомментируйте, пожалуйста, варианты и, возможно, всю идею. 1
Q2: Если бы я выбрал вариант 2, должен ли я реализовать его сам, или есть готовый класс в boost или Qt, который Я мог бы быть производным от или иметь член, и я бы получил бесплатный подсчет ссылок?
Q3: Вы согласны с тем, что сделать Shader абстрактным классом и иметь три производных класса VertexShader , FragmentShader и GeometryShader были бы излишними?

1 Если вы порекомендуете мне существующий фреймворк C ++ OpenGL, это очень хорошо (так как я его на самом деле не нашел), но это должно быть побочное примечание, чем ответ на мои вопросы. Также обратите внимание, что я видел где-то в документации класс QGLShader, но он явно отсутствует в моей версии Qt, и у меня есть причины избегать обновления прямо сейчас.

ОБНОВЛЕНИЕ

Спасибо за ответы. В конце концов я решил сделать свой класс шейдера неизменяемым, удалив исходные функции. Шейдер компилируется при создании и не имеет неконстантных функций-членов. Таким образом, простой подсчет ссылок решает сразу все мои проблемы.

5
задан Armen Tsirunyan 28 August 2011 в 17:13
поделиться