RAII wrapper for OpenGL objects(OpenGL 对象的 RAII 包装器)
问题描述
我想为我注意到的 OpenGL 对象(纹理、帧缓冲区等)编写一个简单的 RAII 包装器,所有 glGen* 和 glDelete* 函数共享相同的签名,所以我的第一次尝试是这样的:
I want to write a simple RAII wrapper for OpenGL objects (textures, frame buffers, etc.) I have noticed, that all glGen* and glDelete* functions share the same signature, so my first attempt was like this:
typedef void (__stdcall *GLGenFunction)(GLsizei, GLuint *);
typedef void (__stdcall *GLDelFunction)(GLsizei, const GLuint *);
template <GLGenFunction glGenFunction, GLDelFunction glDelFunction>
class GLObject
{
GLuint m_name;
public:
GLObject()
{
glGenFunction(1, &m_name);
}
~GLObject()
{
glDelFunction(1, &m_name);
}
GLuint getName() {return m_name;}
};
typedef GLObject<glGenTextures, glDeleteTextures> GLTexture;
它适用于纹理,但不适用于帧缓冲区:glGenFramebuffers 和 glDeleteFramebuffers 函数地址在编译时未知,不能用作模板参数.所以我做了第二个版本:
It works fine for textures, but fails for frame buffers: glGenFramebuffers and glDeleteFramebuffers function addresses are not known at compile time, and cannot be used as template arguments. So I made second version:
class GLObjectBase
{
GLuint m_name;
GLDelFunction m_delFunction;
public:
GLObjectBase(GLGenFunction genFunc, GLDelFunction delFunction)
: m_delFunction(delFunction)
{
genFunc(1, &m_name);
}
GLuint getName()
{
return m_name;
}
protected:
~GLObjectBase()
{
m_delFunction(1, &m_name);
}
};
class GLFrameBuffer : public GLObjectBase
{
public:
GLFrameBuffer() : GLObjectBase(glGenFramebuffers, glDeleteFramebuffers) {}
};
但我不喜欢它,因为我必须在每个实例中存储在运行时不会改变的 del 函数指针.
But I don't like it since I have to store del function pointer in each instance that will not change at run-time.
如何制作仅在每个实例中存储对象名称的包装类,而无需创建一堆几乎复制粘贴的类?
How do I make wrapper class that stores only object name in each instance without resorting to create a bunch of almost copy-pasted classes?
我可以这样做:
template <int N>
class GLObject2
{
GLuint m_name;
static GLDelFunction glDelFunction;
public:
GLObject2(GLGenFunction genFunction, GLDelFunction delFunc)
{
genFunction(1, &m_name);
if ( glDelFunction == nullptr )
glDelFunction = delFunc;
ASSERT(glDelFunction == delFunc);
}
GLuint getName() {return m_name;}
protected:
~GLObject2()
{
glDelFunction(1, &m_name);
}
};
template <int N>
GLDelFunction GLObject2<N>::glDelFunction = nullptr;
class GLTexture: public GLObject2<1>
{
public:
GLTexture(): GLObject2<1>(glGenTextures, glDeleteTextures) {}
};
class GLRenderBuffer: public GLObject2<2>
{
public:
GLRenderBuffer(): GLObject2<2>(glGenRenderbuffers, glDeleteRenderbuffers) {}
};
谁能提出更优雅的解决方案?
Can anyone suggest more elegant solution?
推荐答案
真的,您会像 C 程序员一样思考这个问题.您正在使用 C++,因此请按照 C++ 程序员的方式解决它.使用特征类:
Really, you're thinking about this like a C programmer. You're using C++, so solve it the way a C++ programmer would. With a traits class:
struct VertexArrayObjectTraits
{
typedef GLuint value_type;
static value_type Create();
static void Destroy(value_type);
};
就像一个适当的 C++ 特征类,我们让每个对象声明它自己的 value_type.这将允许您使其适应不使用 GLuint 的 OpenGL 对象,例如 同步对象(尽管创建/销毁界面无论如何都不适合它们,所以你可能不应该打扰).
Like a proper C++ traits class, we have each object declare it's own value_type. This will allow you to adapt it to OpenGL objects that don't use GLuints, like sync objects (though the Create/Destroy interface wouldn't be good for them anyway, so you probably shouldn't bother).
因此,您为每种类型的 OpenGL 对象编写了一个特征类.您的 Create 和 Destroy 函数会将调用适当地转发到 C API.
So you write one traits class for each type of OpenGL object. Your Create and Destroy functions will forward the calls on to the C API appropriately.
这样做之后,您只需要一个围绕那些接口的 RAII 包装器:
After doing that, all you need is a RAII-wrapper around those interfaces:
template<typename T>
class OpenGLObject
{
public:
OpenGLObject() : m_obj(T::Create()) {}
~OpenGLObject() {T::Destroy(m_obj);}
operator typename T::value_type() {return m_obj;}
private:
typename T::value_type m_obj;
};
OpenGLObject 将持有 VAO.
这篇关于OpenGL 对象的 RAII 包装器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:OpenGL 对象的 RAII 包装器
基础教程推荐
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 我有静态或动态 boost 库吗? 2021-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 常量变量在标题中不起作用 2021-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 在 C++ 中计算滚动/移动平均值 2021-01-01
