OK, so I have written my vertex buffer class how I thought it should be but it seems very messy for instance it needs the shader program id to know where the attributes are (this can only be a bad thing right, a vbo should be able to use multiple shaders easily) please can someone have a look and tell me what should be there and what shouldn't.
It also doesn't seem right that I'm having to come back in and call disableAttributes here after the draw call, there must be a cleaner way of doing things.
I think it's a case of not having clear responsibilities.
.h
#ifndef KVERTEXBUFFER_H
#define KVERTEXBUFFER_H
#include "KGraphicsLib.h"
#include "KShaderManager.h"
enum EFormatBitMask
{
FORMAT_POSITION = (1u << 0),
FORMAT_UV = (1u << 1),
FORMAT_NORMAL = (1u << 2),
FORMAT_TANGENT = (1u << 3)
};
class CVertexBuffer
{
public:
struct CAttrib
{
CAttrib(GLuint i, GLint s, int o)
{
index = i;
size = s;
offset = (GLvoid*)o;
}
GLuint index; // location that it's bound to
GLint size; // component count (float[2] has size 2)
GLvoid* offset;
};
CVertexBuffer();
virtual ~CVertexBuffer();
void init();
void destroy();
void uploadData(GLint programID, unsigned int format, float* data, int vertexCount);
void pointToData();
void disableAttributes();
private:
GLuint identifier;
GLsizei stride;
vector<CAttrib*> attribs;
};
#endif // #ifndef KVERTEXBUFER_H
.cpp
#include "KVertexBuffer.h"
CVertexBuffer::CVertexBuffer()
{
init();
}
CVertexBuffer::~CVertexBuffer()
{
destroy();
}
void CVertexBuffer::init()
{
glGenBuffers(1, &identifier);
GetError();
}
void CVertexBuffer::destroy()
{
glDeleteBuffers(1, &identifier);
}
void CVertexBuffer::pointToData()
{
CAttrib* attrib;
vector<CAttrib*>::iterator it = attribs.begin();
for (; it != attribs.end(); ++it) {
attrib = (*it);
glEnableVertexAttribArray(attrib->index);
glBindBuffer(GL_ARRAY_BUFFER, identifier);
glVertexAttribPointer(
attrib->index, // index
attrib->size, // component count
GL_FLOAT,
GL_FALSE, // normalized?
stride,
attrib->offset
);
GetError();
}
}
void CVertexBuffer::disableAttributes()
{
vector<CAttrib*>::iterator it = attribs.begin();
for (; it != attribs.end(); ++it) {
glDisableVertexAttribArray((*it)->index);
}
}
void CVertexBuffer::uploadData(GLint programID, unsigned int format, float* data, int vertexCount)
{
stride = 0;
CAttrib* attr;
if ((format & FORMAT_POSITION) == FORMAT_POSITION) {
attr = new CAttrib(glGetAttribLocation(programID, ""), 3, stride);
stride += attr->size * sizeof(GLfloat);
attribs.push_back(attr);
}
if ((format & FORMAT_UV) == FORMAT_UV) {
attr = new CAttrib(glGetAttribLocation(programID, ""), 2, stride);
stride += attr->size * sizeof(GLfloat);
attribs.push_back(attr);
}
if ((format & FORMAT_NORMAL) == FORMAT_NORMAL) {
attr = new CAttrib(glGetAttribLocation(programID, ""), 3, stride);
stride += attr->size * sizeof(GLfloat);
attribs.push_back(attr);
}
if ((format & FORMAT_TANGENT) == FORMAT_TANGENT) {
attr = new CAttrib(glGetAttribLocation(programID, ""), 4, stride);
stride += attr->size * sizeof(GLfloat);
attribs.push_back(attr);
}
glBindBuffer(GL_ARRAY_BUFFER, identifier);
glBufferData(GL_ARRAY_BUFFER, stride * vertexCount, data, GL_STATIC_DRAW);
}
Thank you
Jack