added Buffer class to handle VBOs, EBOs and UBOs
This commit is contained in:
parent
4dcef0d4e3
commit
d07541e8ea
85
src/buffer.cpp
Normal file
85
src/buffer.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "buffer.h"
|
||||
#include "glassert.h"
|
||||
#include <cstdio>
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
template <typename T>
|
||||
GLenum Buffer<T>::getGLEnum(BufferType type)
|
||||
{
|
||||
GLenum typeEnum;
|
||||
|
||||
switch(m_type)
|
||||
{
|
||||
case VBO :
|
||||
typeEnum = GL_ARRAY_BUFFER;
|
||||
break;
|
||||
case EBO :
|
||||
typeEnum = GL_ELEMENT_ARRAY_BUFFER;
|
||||
break;
|
||||
case UBO :
|
||||
typeEnum = GL_UNIFORM_BUFFER;
|
||||
break;
|
||||
}
|
||||
|
||||
return typeEnum;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Buffer<T>::BufferEditor::BufferEditor(Buffer *b)
|
||||
{
|
||||
if(b->isDynamic())
|
||||
{
|
||||
GLenum m_typeEnum = getGLEnum(b->getType());
|
||||
glAssert(glBindBuffer(m_typeEnum, b->getId()));
|
||||
glAssert(ptr = (T*)glMapBuffer(m_typeEnum, GL_WRITE_ONLY));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Buffer data can't be edited, this buffer is static\n");
|
||||
ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Buffer<T>::BufferEditor::~BufferEditor()
|
||||
{
|
||||
glUnmapBuffer(m_typeEnum);
|
||||
glAssert(glBindBuffer(m_typeEnum, 0));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Buffer<T>::Buffer(const std::vector<T> &data, BufferType type, bool isDynamic) :
|
||||
m_type(type),
|
||||
m_isDynamic(isDynamic)
|
||||
{
|
||||
// TODO : allow stream draw
|
||||
GLenum draw_type = isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
|
||||
GLenum typeEnum = getGLEnum(m_type);
|
||||
glAssert(glGenBuffers(1, m_id));
|
||||
glAssert(glBindBuffer(typeEnum, m_id));
|
||||
glAssert(glBufferData(typeEnum, data.size() * sizeof(T), data.data(), draw_type));
|
||||
glAssert(glBindBuffer(typeEnum, 0));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Buffer<T>::setVertexAttrib(int location, int nbComponents, int offset, int instanceDivisor)
|
||||
{
|
||||
if(m_type == VBO)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, m_id));
|
||||
glAssert(glEnableVertexAttribArray(location));
|
||||
if(instanceDivisor)
|
||||
glAssert(glVertexAttribDivisor(location, instanceDivisor));
|
||||
glAssert(glVertexAttribPointer(location, nbComponents, GL_FLOAT, GL_FALSE, sizeof(T), BUFFER_OFFSET(offset)));
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "WTF\n");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Buffer<T>::~Buffer()
|
||||
{
|
||||
glAssert(glDeleteBuffers(1, m_id));
|
||||
}
|
47
src/buffer.h
Normal file
47
src/buffer.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef BUFFER_H
|
||||
#define BUFFER_H
|
||||
|
||||
#include "glew.h"
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
enum BufferType
|
||||
{
|
||||
VBO,
|
||||
EBO,
|
||||
UBO
|
||||
};
|
||||
|
||||
class BufferEditor
|
||||
{
|
||||
GLenum m_typeEnum;
|
||||
T *ptr;
|
||||
|
||||
public:
|
||||
BufferEditor(Buffer *b);
|
||||
~BufferEditor();
|
||||
|
||||
T* getPointer();
|
||||
};
|
||||
|
||||
Buffer(const std::vector<T> &data, BufferType type, bool isDynamic = false);
|
||||
~Buffer();
|
||||
|
||||
void setVertexAttrib(int location, int nbComponents, int offset = 0, int instanceDivisor = 0);
|
||||
|
||||
GLuint getId() {return m_id;}
|
||||
BufferType getType() {return m_type;}
|
||||
bool isDynamic() {return m_isDynamic;}
|
||||
|
||||
private:
|
||||
GLuint m_id;
|
||||
BufferType m_type;
|
||||
bool m_isDynamic;
|
||||
|
||||
GLenum getGLEnum(BufferType type);
|
||||
};
|
||||
|
||||
#endif // BUFFER_H
|
195
src/mesh.cpp
195
src/mesh.cpp
@ -4,8 +4,7 @@
|
||||
#include "glassert.h"
|
||||
#include "sparrowrenderer.h"
|
||||
#include "material.h"
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
#include "buffer.h"
|
||||
|
||||
const char* const Mesh::flagStr[Mesh::NB_FLAGS] =
|
||||
{
|
||||
@ -33,8 +32,9 @@ const char* const Mesh::flagStr[Mesh::NB_FLAGS] =
|
||||
Mesh::Mesh() :
|
||||
material(NULL),
|
||||
isDoubleSided(false),
|
||||
isBillboard(false),
|
||||
depth(0),
|
||||
vao(0),
|
||||
nb_buffers(0),
|
||||
primitive_type(GL_TRIANGLES)
|
||||
{}
|
||||
|
||||
@ -43,59 +43,75 @@ Mesh::~Mesh()
|
||||
destroyGL();
|
||||
}
|
||||
|
||||
void Mesh::initGL(bool isDynamic)
|
||||
void Mesh::initGL()
|
||||
{
|
||||
destroyGL();
|
||||
|
||||
GLenum buffer_type = isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
|
||||
|
||||
// create VAO
|
||||
glAssert(glGenVertexArrays(1, &vao));
|
||||
glAssert(glBindVertexArray(vao));
|
||||
|
||||
// create VBOs
|
||||
glAssert(glGenBuffers(NB_BUFFERS, vbo));
|
||||
Buffer *b;
|
||||
|
||||
// init indices vbos
|
||||
glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFER]));
|
||||
glAssert(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), buffer_type));
|
||||
|
||||
// init positions vbo
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER]));
|
||||
glAssert(glBufferData(GL_ARRAY_BUFFER, positions3D.size() * sizeof(glm::vec3), positions3D.data(), buffer_type));
|
||||
|
||||
if(hasNormals())
|
||||
// init positions VBO
|
||||
if(!positions3D.empty())
|
||||
{
|
||||
b = new Buffer(positions3D, Buffer::VBO);
|
||||
b->setVertexAttrib(0, 3);
|
||||
buffers.push_back(b);
|
||||
|
||||
// init normals vbo
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER]));
|
||||
glAssert(glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), buffer_type));
|
||||
}
|
||||
|
||||
if(hasTexCoords())
|
||||
{
|
||||
// init texCoords vbo
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER]));
|
||||
glAssert(glBufferData(GL_ARRAY_BUFFER, texCoords.size() * sizeof(glm::vec2), texCoords.data(), buffer_type));
|
||||
}
|
||||
|
||||
if(hasTangents())
|
||||
{
|
||||
if(!normals.empty())
|
||||
{
|
||||
b = new Buffer(normals, Buffer::VBO);
|
||||
b->setVertexAttrib(1, 3);
|
||||
buffers.push_back(b);
|
||||
}
|
||||
// init tangents vbo
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER]));
|
||||
glAssert(glBufferData(GL_ARRAY_BUFFER, tangents.size() * sizeof(glm::vec3)*2, tangents.data(), buffer_type));
|
||||
if(!tangents.empty())
|
||||
{
|
||||
b = new Buffer(tangents, Buffer::VBO);
|
||||
b->setVertexAttrib(3, 3);
|
||||
b->setVertexAttrib(4, 3);
|
||||
buffers.push_back(b);
|
||||
}
|
||||
}
|
||||
|
||||
if(hasInstances() && SparrowRenderer::isModernOpenGLAvailable())
|
||||
else if(!positions2D.empty())
|
||||
{
|
||||
// init instances vbo
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[INSTANCE_BUFFER]));
|
||||
glAssert(glBufferData(GL_ARRAY_BUFFER, instances_offsets.size() * sizeof(glm::vec3), instances_offsets.data(), GL_DYNAMIC_DRAW));
|
||||
b = new Buffer(positions2D, Buffer::VBO);
|
||||
b->setVertexAttrib(0, 2);
|
||||
buffers.push_back(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR : Mesh can't be initialized without position data");
|
||||
return;
|
||||
}
|
||||
// init texCoords vbo
|
||||
if(!texCoords.empty())
|
||||
{
|
||||
b = new Buffer(texCoords, Buffer::VBO);
|
||||
b->setVertexAttrib(2, 2);
|
||||
buffers.push_back(b);
|
||||
}
|
||||
|
||||
// init instances vbo
|
||||
if(!instances_offsets.empty())
|
||||
{
|
||||
b = new Buffer(instances_offsets, Buffer::VBO);
|
||||
b->setVertexAttrib(5, 3, 0, 1);
|
||||
buffers.push_back(b);
|
||||
}
|
||||
|
||||
// init EBO
|
||||
if(!indices.empty())
|
||||
{
|
||||
b = new Buffer(indices, Buffer::EBO);
|
||||
buffers.push_back(b);
|
||||
}
|
||||
|
||||
// unbind vao
|
||||
glAssert(glBindVertexArray(0));
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
void Mesh::draw(Shader* shader, bool drawNormals, bool drawTexCoord, bool drawTangents)
|
||||
@ -107,75 +123,41 @@ void Mesh::draw(Shader* shader, bool drawNormals, bool drawTexCoord, bool drawTa
|
||||
bool crappy = (shader == NULL);
|
||||
material->bindAttributes(shader);
|
||||
glAssert(glBindVertexArray(vao));
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER]));
|
||||
|
||||
if(crappy)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER]));
|
||||
glAssert(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glAssert(glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
glAssert(glEnableVertexAttribArray(0));
|
||||
glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0)));
|
||||
}
|
||||
if(hasNormals() && drawNormals)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER]));
|
||||
if(crappy)
|
||||
{
|
||||
glAssert(glEnableClientState(GL_NORMAL_ARRAY));
|
||||
glAssert(glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
glAssert(glEnableVertexAttribArray(1));
|
||||
glAssert(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0)));
|
||||
}
|
||||
}
|
||||
if(hasTexCoords() && drawTexCoord)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER]));
|
||||
if(crappy)
|
||||
glAssert(glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0))); // TODO : check 2D positions
|
||||
if(!texCoords.empty() && drawTexCoord)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER]));
|
||||
glAssert(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
glAssert(glTexCoordPointer(2, GL_FLOAT, 0, BUFFER_OFFSET(0)));
|
||||
}
|
||||
else
|
||||
if(!normals.empty() && drawNormals)
|
||||
{
|
||||
glAssert(glEnableVertexAttribArray(2));
|
||||
glAssert(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(0)));
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER]));
|
||||
glAssert(glEnableClientState(GL_NORMAL_ARRAY));
|
||||
glAssert(glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(0)));
|
||||
}
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
if(hasTangents() && drawTangents && !crappy)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER]));
|
||||
glAssert(glEnableVertexAttribArray(3));
|
||||
glAssert(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(0)));
|
||||
glAssert(glEnableVertexAttribArray(4));
|
||||
glAssert(glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(sizeof(glm::vec3))));
|
||||
}
|
||||
glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getEBO()));
|
||||
if(!instances_offsets.empty() && !crappy)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[INSTANCE_BUFFER]));
|
||||
glAssert(glEnableVertexAttribArray(5));
|
||||
glAssert(glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0)));
|
||||
glAssert(glVertexAttribDivisor(5, 1));
|
||||
glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFER]));
|
||||
glAssert(glDrawElementsInstanced(primitive_type, indices.size(), GL_UNSIGNED_INT, NULL, instances_offsets.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFER]));
|
||||
glAssert(glDrawElements(primitive_type, indices.size(), GL_UNSIGNED_INT, NULL));
|
||||
}
|
||||
|
||||
if(crappy)
|
||||
{
|
||||
glAssert(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
if(hasNormals() && drawNormals)
|
||||
if(!normals.empty() && drawNormals)
|
||||
glAssert(glDisableClientState(GL_NORMAL_ARRAY));
|
||||
if(hasTexCoords() && drawTexCoord)
|
||||
if(!texCoords.empty() && drawTexCoord)
|
||||
glAssert(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
}
|
||||
|
||||
glAssert(glBindVertexArray(0));
|
||||
if(isDoubleSided)
|
||||
{
|
||||
@ -187,27 +169,17 @@ void Mesh::destroyGL()
|
||||
{
|
||||
if(vao != 0)
|
||||
{
|
||||
glAssert(glDeleteBuffers(NB_BUFFERS, vbo));
|
||||
glAssert(glDeleteVertexArrays(1, &vao));
|
||||
vao = 0;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3* Mesh::beginUpdateBuffer(int buffer)
|
||||
{
|
||||
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[buffer]));
|
||||
glAssert(glm::vec3* ptr = (glm::vec3*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Mesh::endUpdateBuffer()
|
||||
{
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
for(Buffer *b : buffers)
|
||||
delete(b);
|
||||
buffers.clear();
|
||||
}
|
||||
|
||||
unsigned int Mesh::getFlags()
|
||||
{
|
||||
unsigned int flags = material->getFlags() << MESH_NB_FLAGS;
|
||||
unsigned int flags = material->getFlags();
|
||||
|
||||
if(!indices.empty())
|
||||
flags |= 1 << MESH_INDEXED;
|
||||
@ -228,26 +200,7 @@ unsigned int Mesh::getFlags()
|
||||
else
|
||||
flags |= 1 << MESH_2D;
|
||||
|
||||
|
||||
return flags;
|
||||
|
||||
// Mesh type
|
||||
MESH_3D,
|
||||
MESH_2D,
|
||||
|
||||
// 3D Geometric properties
|
||||
MESH_TANGENT_SPACE,
|
||||
MESH_BILLBOARD,
|
||||
|
||||
// simple textures properties
|
||||
MATERIAL_DIFFUSE_TEXTURE,
|
||||
MATERIAL_ALPHA_MASK,
|
||||
|
||||
// 3D phong-like materials :
|
||||
MATERIAL_AMBIENT_TEXTURE,
|
||||
MATERIAL_SPECULAR_TEXTURE,
|
||||
MATERIAL_NORMAL_MAP,
|
||||
MATERIAL_BUMP_MAP,
|
||||
}
|
||||
|
||||
struct VertexComparator
|
||||
|
43
src/mesh.h
43
src/mesh.h
@ -6,11 +6,10 @@
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
class Buffer;
|
||||
class Material;
|
||||
class Shader;
|
||||
|
||||
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
public:
|
||||
@ -70,27 +69,31 @@ public:
|
||||
std::vector<glm::vec3> instances_offsets;
|
||||
std::vector<Tangents> tangents;
|
||||
std::vector<GLuint> indices;
|
||||
|
||||
|
||||
std::vector<Buffer*> buffers;
|
||||
|
||||
enum {
|
||||
// required buffers
|
||||
// required buffer
|
||||
POSITION_BUFFER,
|
||||
|
||||
// indices buffers
|
||||
INDICES_BUFFER,
|
||||
|
||||
// optionnal buffers :
|
||||
NORMAL_BUFFER, TEXCOORD_BUFFER, TANGENT_BUFFER,
|
||||
NORMAL_BUFFER,
|
||||
TEXCOORD_BUFFER,
|
||||
TANGENT_BUFFER,
|
||||
|
||||
// instanciation buffer
|
||||
INSTANCE_BUFFER,
|
||||
|
||||
NB_BUFFERS
|
||||
};
|
||||
|
||||
GLuint vao; // TODO : this is supposed to be protected
|
||||
|
||||
GLuint vao;
|
||||
|
||||
protected:
|
||||
|
||||
int nb_buffers;
|
||||
GLuint vbo[NB_BUFFERS];
|
||||
GLenum primitive_type;
|
||||
|
||||
public:
|
||||
@ -98,28 +101,19 @@ public:
|
||||
Mesh();
|
||||
virtual ~Mesh();
|
||||
|
||||
void initGL(bool isDynamic = false);
|
||||
void initGL();
|
||||
void draw(Shader* shader = NULL, bool drawNormals = true, bool drawTexCoord = true, bool drawTangents = true);
|
||||
void destroyGL();
|
||||
|
||||
/**
|
||||
* @brief beginUpdateBuffer can be used to change the contents of a VBO dynamically
|
||||
* @return a pointer to the buffer's data
|
||||
*
|
||||
* endUpdateBuffer() must be called when the modifications are over
|
||||
*/
|
||||
glm::vec3* beginUpdateBuffer(int buffer);
|
||||
void endUpdateBuffer();
|
||||
|
||||
/**
|
||||
* @brief getFlags returns the flags that defines the specificities of the mesh and his material
|
||||
*/
|
||||
unsigned int getFlags();
|
||||
|
||||
/**
|
||||
* this class is intended to be used with the default GL_TRIANGLES primitive,
|
||||
* the methods mergeVertices, computeNormals, and computeTangents will probably have
|
||||
* unpredictable behavior with other primitive types.
|
||||
* this class is intended to be used with a 3D mesh of the default GL_TRIANGLES primitives,
|
||||
* the methods mergeVertices, computeNormals, and computeTangents will not
|
||||
* work with other primitive types.
|
||||
*/
|
||||
void setPrimitiveType(GLenum type) {primitive_type = type;}
|
||||
|
||||
@ -137,11 +131,6 @@ public:
|
||||
* compute tangent space from a textured indexed mesh (positions + normals + texcoords + indices)
|
||||
*/
|
||||
void computeTangents();
|
||||
|
||||
bool hasNormals() const {return !normals.empty();}
|
||||
bool hasTexCoords() const {return !texCoords.empty();}
|
||||
bool hasTangents() const {return !tangents.empty();}
|
||||
bool hasInstances() const {return !instances_offsets.empty();}
|
||||
};
|
||||
|
||||
#endif // MESH_H
|
||||
|
@ -126,7 +126,7 @@ void PostEffectModule::renderGL(Camera* myCamera, Scene* scene)
|
||||
|
||||
glAssert(glBindVertexArray(vao));
|
||||
|
||||
// threasholding the luminance to isolate high luminance pixels for bloom
|
||||
// thresholding the luminance to isolate high luminance pixels for bloom
|
||||
luminanceStep();
|
||||
|
||||
// blur the high luminance pixels
|
||||
|
Loading…
x
Reference in New Issue
Block a user