自从我开始学习 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"));
如您所见,我通过 s2 更改了 s1 的来源,因为它们共享相同的内部着色器句柄。老实说,我认为这里没有什么大问题。我写了这门课,所以我知道它的复制语义是这样的,我可以接受。问题是我不确定这种设计是否可以接受。所有这一切都可以通过 Option1 + 共享指针来实现,唯一的区别是我不想每次创建着色器时都有一个共享指针(不是出于性能原因 - 只是为了语法方便)。
Q1:请评论选项和可选的整个想法。1
Q2:如果我要选择选项 2,我是否必须自己实现它,或者在 boost 或 Qt 中有一个现成的类,我可以从中派生或拥有它的成员,并且我会获得免费的引用计数?
Q3:您是否同意创建Shader
一个抽象类并拥有三个派生类VertexShader
, FragmentShader
, 和GeometryShader
是矫枉过正?
1如果您应该向我推荐一个现有的 C++ OpenGL 框架,那很好(因为我实际上还没有找到一个),但这应该是一个旁注,而不是我的问题的答案。另请注意,我在文档的某处看到了 QGLShader 类,但它显然不存在于我的 Qt 版本中,我有理由立即避免升级。
更新
感谢您的回答。我最终决定通过删除源函数使我的着色器类不可变。着色器在创建时被编译并且没有非常量成员函数。因此,一个简单的引用计数一下子解决了我所有的问题。