Я работаю над созданием системы рендеринга для 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;
В идеале я хотел бы ограничить фактические типы, доступные для использования в этом рендерере, типами вершин, которые были определены.
Я думаю, что одним из способов сделать это было то, что этот, а затем вызов метода 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;
};
Я набрал кучу вещей, но я все еще не уверен, какова ваша цель или вопрос. Вы, кажется, пытаетесь создать один объект, который инкапсулирует все, что может сделать OpenGL. Мое первое предложение — не делать этого.
Я предлагаю класс Mesh, который содержит VAO и программу и знает, как визуализировать себя:
glUseProgram(mProgramID);
glBindVertexArray(mVAO);
glDrawArrays(mDrawMode, 0, mNumPrimitives);
Я думаю, это то, что вы пытаетесь достичь.
Вместо шаблонов для всего я предлагаю подклассы. Есть много работы (и, возможно, различные подклассы, параметризованные функции или перегрузка), чтобы установить его, но как только он настроен, рендеринг становится простым.
Если вы не можете использовать шаблоны, то специализация шаблонов может помочь вам преодолеть разрыв. Но я не вижу здесь хорошего использования шаблонов; Такое чувство, что ты пытаешься их подковать.
Других решений пока нет …