С тех пор, как я начал изучать 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, и у меня есть причины избегать обновления прямо сейчас.
ОБНОВЛЕНИЕ
Спасибо за ответы. В конце концов я решил сделать свой класс шейдера неизменяемым, удалив исходные функции. Шейдер компилируется при создании и не имеет неконстантных функций-членов. Таким образом, простой подсчет ссылок решает сразу все мои проблемы.