我正在为 OpenGL 3.1 设计一个渲染系统(目前仅限于 2D)。我想做的是真正考虑优雅的设计模式,这样我就不必担心一些维护和调试很痛苦的乱七八糟的东西。
起初,我的想法类似于有一个模板化的基类,它带有接受不同类型名作为参数的函数。然后子类将从基类继承,在派生时发送它们将使用的类型作为模板参数。
所以,我有点卡住了,我应该如何正确地设计这个而不只是把东西弄掉。问题是我正在使用我自己的顶点结构,它围绕glm
向量类,所以我可以在一个结构中拥有顶点对,并在调用glVertexAttribPointer()
.
换句话说,
typedef struct colorVertex_d
{
glm::vec3 Position;
glm::vec4 Color;
}
colorVertex_t;
typedef struct textureVertex_d
{
glm::vec3 Position;
glm::vec2 UV;
}
textureVertex_t;
理想情况下,我想做的是将可用于此渲染器的实际类型限制为已定义的顶点类型。
我认为这样做的一种方法是按照 this 的方式做一些事情,然后如果发送给类的类型无效,则调用 Shutdown 方法(有点像异常,只是不是异常......)。
尽管如此,我什至不确定在这种情况下这是否可以被认为是一个好的实现。
我真正在寻找的是一种方法,它可以支持多种缓冲区类型(例如顶点、索引、法线、颜色等),这些缓冲区类型符合上面显示的顶点结构等类型。
原始来源
/**
* Is an abstract class to inherit from for defining custom buffer handler classes,
* the type name specified is the type of data stored in the buffer specifically, e.g. textureVertex_t or colorVertex_t
*/
template < typename DataT, typename ContainerT >
class RenderBuffer
{
public:
enum RenderMethod
{
Stream, // used for writing data into the buffer once per render
Dynamic, // values in the buffer are changed from time to time
Static // data is set only once, then rendered as many times as it needs to be
};
enum DrawMode
{
Triangle,
TriangleStrip,
Line,
LineStrip
};
enum BufSetType
{
Alloc,
Update
};
RenderBuffer( RenderMethod rm, DrawMode dm )
{
switch( rm )
{
case Stream: mRenderMethod = GL_STREAM_DRAW; break;
case Dynamic: mRenderMethod = GL_DYNAMIC_DRAW; break;
case Static: mRenderMethod = GL_STATIC_DRAW; break;
}
switch( dm )
{
case Triangle: mDrawMode = GL_TRIANGLES; break;
case TriangleStrip: mDrawMode = GL_TRIANGLE_STRIP; break;
case Line: mDrawMode = GL_LINES; break;
case LineStrip: mDrawMode = GL_LINE_STRIP; break;
}
}
virtual ~RenderBuffer( void )
{
}
virtual void Reserve( size_t sz ) = 0; // Reserve space for whatever container used to store the buffer data.
virtual void Bind( void ) const = 0;
virtual void UnBind( void ) const = 0;
template < typename DataT, ContainerT >
virtual void SetBufferData( const ShaderProgram& program, const ContainerT& data, BufSetType m )
{
}
template < typename DataT, ContainerT >
virtual void SetBufferData( const ShaderProgram& program, const DataT* data, const size_t len, BufSetType m )
{
}
virtual void Render( void ) const = 0;
size_t VertexCount;
protected:
GLenum mDrawMode, mRenderMethod;
};