Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 7cbd30d7 authored by schultezub's avatar schultezub
Browse files

Started implementing tgt OpenGL 3+ wrappers:

 * BufferObject for VBOs
 * VertexArrayObject and VertexAttribute fpr VAOs

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@266 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent e8e5d8f1
......@@ -28,7 +28,7 @@ SET(TGT_SOURCES
assert.cpp
bounds.cpp
bspline.cpp
# buffer.cpp
buffer.cpp
camera.cpp
catmullromspline.cpp
curve.cpp
......@@ -60,6 +60,7 @@ SET(TGT_SOURCES
textureunit.cpp
tgt_gl.cpp
timer.cpp
vertexarrayobject.cpp
#event
event/eventhandler.cpp
event/eventlistener.cpp
......
#include "buffer.h"
namespace tgt {
BufferObject::BufferObject()
: _id(0)
, _size(0)
, _numElements(0)
{
glGenBuffers(1, &_id);
if (_id == 0) {
throw new tgt::Exception("Could not create OpenGL Buffer object.");
}
}
BufferObject::~BufferObject() {
tgtAssert(_assignedAttributes.empty(), "Destructing a BufferObject, that is still bound to a VertexAttribute.");
if (_id != 0)
glDeleteBuffers(1, &_id);
}
void BufferObject::bind(TargetType target) {
glBindBuffer(target, _id);
}
void BufferObject::data(TargetType target, UsageType usage, const void* data, size_t numBytes) {
bind(target);
glBufferData(target, numBytes, data, usage);
}
void BufferObject::subdata(TargetType target, UsageType usage, size_t offset, const void* data, size_t numBytes) {
bind(target);
glBufferSubData(target, offset, numBytes, data);
}
void BufferObject::bindToVertexAttribute(const VertexAttribute* va) {
_assignedAttributes.insert(va);
}
void BufferObject::unbindFromVertexAttribute(const VertexAttribute* va) {
_assignedAttributes.erase(va);
}
}
\ No newline at end of file
#ifndef BUFFER_H__
#define BUFFER_H__
#include "tgt/exception.h"
#include "tgt/tgt_gl.h"
#include <set>
namespace tgt {
class VertexAttribute;
class BufferObject {
friend class VertexAttribute;
public:
enum TargetType {
ARRAY_BUFFER = GL_ARRAY_BUFFER
};
enum UsageType {
USAGE_STATIC_DRAW = GL_STATIC_DRAW,
USAGE_STATIC_READ = GL_STATIC_READ,
USAGE_STATIC_COPY = GL_STATIC_COPY,
USAGE_DYNAMIC_DRAW = GL_DYNAMIC_DRAW,
USAGE_DYNAMIC_READ = GL_DYNAMIC_READ,
USAGE_DYNAMIC_COPY = GL_DYNAMIC_COPY,
USAGE_STREAM_DRAW = GL_STREAM_DRAW,
USAGE_STREAM_READ = GL_STREAM_READ,
USAGE_STREAM_COPY = GL_STREAM_COPY
};
enum BaseType {
BYTE = GL_BYTE,
UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
SHORT = GL_SHORT,
UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
INT = GL_INT,
UNSIGNED_INT = GL_UNSIGNED_INT,
FLOAT = GL_FLOAT,
DOUBLE = GL_DOUBLE
};
/**
* Creates a new OpenGL buffer object and generates an ID for it.
* \throw tgt::Exception when OpenGL buffer generation failed.
*/
BufferObject() throw (tgt::Exception);
/**
* Disposes and deletes the OpenGL buffer object.
*/
virtual ~BufferObject();
BaseType getBaseType() const;
size_t getElementSize() const;
/**
* Binds the buffer object to the current OpenGL context.
* \param target Target type of buffer object
*/
void bind(TargetType target);
/**
* Binds the buffer, reserves space on the OpenGL device and initializes it with the given data in \a data.
* \param target Target type of buffer object.
* \param usage Usage of data.
* \param data Pointer to host memory containing the data.
* \param numBytes Size of \a data in bytes.
*/
void data(TargetType target, UsageType usage, const void* data, size_t numBytes);
/**
* Updates a subset of the buffer's data.
* \param target Target type of buffer object.
* \param usage Usage of data.
* \param offset Offset where to start writing in buffer's data in bytes.
* \param data Pointer to host memory containing the data.
* \param numBytes Size of \a data in bytes.
*/
void subdata(TargetType target, UsageType usage, size_t offset, const void* data, size_t numBytes);
protected:
/**
* To be called from VertexAttribute's constructor, to keep track of the VBO-VA bindings.
* \param va The VertexAttribute this BufferObject was bound to.
*/
void bindToVertexAttribute(const VertexAttribute* va);
/**
* To be called from VertexAttribute destructor, to keep track of the VBO-VA binding.
* \param va The VertexAttribute this BufferObject is no longer bound to.
*/
void unbindFromVertexAttribute(const VertexAttribute* va);
GLuint _id; ///< OpenGL ID of this buffer
BaseType _baseType;
size_t _elementSize;
size_t _size; ///< Buffer size in bytes
size_t _numElements; ///< Number of elements in this buffer
std::set<const VertexAttribute*> _assignedAttributes; ///< Set of all VertexAttributes this buffer is assigned to (used for debugging purposes).
};
}
#endif // BUFFER_H__
#include "vertexattribute.h"
#include "tgt/assert.h"
#include "tgt/buffer.h"
#include "tgt/shadermanager.h"
namespace tgt {
const std::string VertexAttribute::loggerCat_ = "tgt.VertexAttribute";
VertexAttribute::VertexAttribute(size_t index, BufferObject* bufferObject, size_t stride, size_t offset)
: _index(index)
, _stride(stride)
, _offset(offset)
, _bufferObject(bufferObject)
{
tgtAssert(_bufferObject != 0, "BufferObject must not be 0.");
_bufferObject->bindToVertexAttribute(this);
// Todo: implement normalized flag if needed
glVertexAttribPointer(_index, _bufferObject->getElementSize(), _bufferObject->getBaseType(), false, _stride, reinterpret_cast<void*>(_offset));
}
VertexAttribute::~VertexAttribute() {
_bufferObject->unbindFromVertexAttribute(this);
}
// ================================================================================================
const std::string VertexArrayObject::loggerCat_ = "tgt.VertexArrayObject";
VertexArrayObject::VertexArrayObject(bool autoBind)
: _id(0)
{
glGenVertexArrays(1, &_id);
if (_id == 0) {
throw new tgt::Exception("Could not create OpenGL Vertex Array.");
}
if (autoBind)
bind();
}
VertexArrayObject::~VertexArrayObject() {
glDeleteVertexArrays(1, &_id);
}
void VertexArrayObject::bind() {
if (!_initialized)
initStaticMembers();
if (_currentlyBoundVertexArray != _id) {
glBindVertexArray(_id);
_currentlyBoundVertexArray = _id;
}
}
void VertexArrayObject::unbind() {
if (!_initialized)
initStaticMembers();
if (_currentlyBoundVertexArray != 0) {
glBindVertexArray(0);
_currentlyBoundVertexArray = 0;
}
}
size_t VertexArrayObject::addVertexAttribute(AttributeType attributeType, BufferObject* bufferObject, size_t stride /*= 0*/, size_t offset /*= 0*/, bool enableNow /*= true*/) {
if (_attributes.size() > 16) {
// TODO: The better way would be to check glGet(GL_MAX_VERTEX_ATTRIBS), but the standard says 16 is the minimum
// number to be supported and that should be enough and I currently feel lazy. If you're reading this,
// feel free to improve this check...
LERROR("Could not add VertexAttribute: Tried to add more Vertex Attributes than supported.");
return 0;
}
tgtAssert(
attributeType != UnspecifiedAttribute && _attributeTypeMap.find(attributeType) != _attributeTypeMap.end(),
"Tried to add two VertexAttributes with the same type. This is currently not supported.");
// bind and create VertexAttribute
bind();
size_t index = _attributes.size();
_attributes.push_back(VertexAttribute(index, bufferObject, stride, offset));
// add to attribute-type map
if (attributeType != UnspecifiedAttribute)
_attributeTypeMap.insert(std::make_pair(attributeType, index));
// enable if wanted
if (enableNow)
enableVertexAttribute(index);
return index;
}
void VertexArrayObject::updateVertexAttribute(size_t index, BufferObject* bufferObject, size_t stride /*= 0*/, size_t offset /*= 0*/) {
tgtAssert(index < _attributes.size(), "Index out of bounds.");
bind();
_attributes[index] = VertexAttribute(index, bufferObject, stride, offset);
}
void VertexArrayObject::enableVertexAttribute(size_t index) {
tgtAssert(index < _enabledAttributes.size(), "Index out of bounds.");
if (!_initialized)
initStaticMembers();
glEnableVertexAttribArray(index);
_enabledAttributes[index] = true;
}
void VertexArrayObject::disableVertexAttribute(size_t index) {
tgtAssert(index < _enabledAttributes.size(), "Index out of bounds.");
if (!_initialized)
initStaticMembers();
glDisableVertexAttribArray(index);
_enabledAttributes[index] = false;
}
void VertexArrayObject::initStaticMembers() {
// TODO: The better way would be to us glGet(GL_MAX_VERTEX_ATTRIBS) as dimension, but the standard says 16
// is the minimum number to be supported and that should be enough and I currently feel lazy. If
// you're reading this, feel free to improve this allocation...
_enabledAttributes = std::vector<bool>(16, false);
_currentlyBoundVertexArray = 0;
_initialized = true;
}
size_t VertexArrayObject::getVertexAttributeIndexByType(AttributeType type) const {
tgtAssert(type != UnspecifiedAttribute, "Type most not be UnspecifiedAttribute, those attributes are not tracked.");
std::map<AttributeType, size_t>::const_iterator it = _attributeTypeMap.find(type);
if (it == _attributeTypeMap.end()) {
tgtAssert(false, "Could not find a VertexAttribute with the given type. Returning 0 as default value.");
LERROR("Could not find a VertexAttribute with the given type. Returning 0 as default value.");
return 0;
}
return it->second;
}
}
\ No newline at end of file
#ifndef VERTEXATTRIBUTE_H__
#define VERTEXATTRIBUTE_H__
#include "tgt/exception.h"
#include "tgt/tgt_gl.h"
#include <string>
#include <vector>
#include <map>
namespace tgt {
class BufferObject;
class Shader;
class VertexArrayObject;
/**
* Class encapsulating an OpenGL Vertex Attribute state.
* \see http://www.opengl.org/wiki/Vertex_Array_Object
*/
class VertexAttribute {
friend class VertexArrayObject;
public:
/**
* Destructor
*/
~VertexAttribute();
protected:
/**
* Creates an OpenGL Vertex Attribute for the data in \a BufferObject and binds it to the uniform
* named \a uniformName in the given shader.
*
* \note VertexAttributes shall only be created by VertexArrayObject's member functions, hence the
* constructor is protected.
*
* \param index Index of the generic vertex attribute to be modified.
* \param bufferObject BufferObject to bind
*/
VertexAttribute(size_t index, BufferObject* bufferObject, size_t stride, size_t offset);
size_t _index; ///< Index of the generic vertex attribute to be modified.
size_t _stride; ///< Specifies the byte offset between consecutive generic vertex attributes.
size_t _offset; ///< Offset in bytes to the first element in the buffer.
BufferObject* _bufferObject; ///< BufferObject that is bound to this VertexAttribute.
static const std::string loggerCat_;
};
// ================================================================================================
/**
* Wrapper class for OpenGL Vertex Array Objects.
*
* \note Because all member methods require a valid locked OpenGL context, we have
* implicit thread-safety.
*/
class VertexArrayObject {
public:
/**
* Enumeration of different VertexAttribute types.
* Every added VertexAttribute may have the UnspecifiedAttribute, then its index cannot be
* re-acquired by getVertexAttributeIndexByType(). In contrast, each other attribute types
* can only be assigned to one single VertexAttribute which then can be re-acquired by
* getVertexAttributeIndexByType().
*/
enum AttributeType {
UnspecifiedAttribute,
VerticesAttribute,
NormalsAttribute,
TextureCoordinatesAttribute,
ColorsAttribute
};
VertexArrayObject(bool autoBind = true) throw (tgt::Exception);
/**
* Destructor, deletes the whole VAO.
*/
~VertexArrayObject();
/**
* Binds this VertexArrayObject to the current OpenGL context.
*/
void bind();
/**
* Unbinds this VertexArrayObject from the current OpenGL context.
*/
void unbind();
/**
* Add a VertexAttribute to this VertexArrayObject.
* A VertexAttribute refers to a BufferObject and defines where to find the (geometry, normal, ...) data
* in it.
* \param attributeType
* \param bufferObject
* \param stride
* \param offset
* \return
*/
size_t addVertexAttribute(AttributeType attributeType, BufferObject* bufferObject, size_t stride = 0, size_t offset = 0, bool enable = true);
/**
*
* \param index
* \param bufferObject
* \param stride
* \param offset
*/
void updateVertexAttribute(size_t index, BufferObject* bufferObject, size_t stride = 0, size_t offset = 0);
/**
* Enables the VertexAttribute with the given index in the OpenGL client state.
* \param index Index of the VertexAttribute to enable.
*/
void enableVertexAttribute(size_t index);
/**
* Disables the VertexAttribute with the given index in the OpenGL client state.
* \param index Index of the VertexAttribute to disable.
*/
void disableVertexAttribute(size_t index);
/**
* Returns the index of the VertexAttribute which was previously created with the given type.
* \note A VertexAttribute of type \a type must have been created beforehand. Otherwise
* this method will raise an error and just return 0 (which is also a perfectly
* valid index).
* \param type Type of the VertexAttribute to search for. Must not be UnspecifiedAttribute, must have been created beforehand!
* \return The index of the VertexAttribute, which was created with the given type. If no such
* VA was created, this method raises an error and returns 0 as default value (which is
* also a perfect valid return value!).
*/
size_t getVertexAttributeIndexByType(AttributeType type) const;
protected:
/**
* Initializes all static members.
*/
void initStaticMembers();
size_t _id; ///< Id of the internal OpenGL handle to the VAO.
std::vector<VertexAttribute> _attributes; ///< List of all VertexAttributes of this VAO.
std::map<AttributeType, size_t> _attributeTypeMap; ///< Map of the AttributeTypes to their indices in the VertexAttributes list.
static bool _initialized; ///< Flag whether the static members are initialized;
static std::vector<bool> _enabledAttributes; ///< List of the enabled VertexAttributes. TODO: They are global in the OpenGL client side (hence, the static), right?
static size_t _currentlyBoundVertexArray; ///< Id of the VertexArrayObject which was bound most recently. 0 if the most recent bind call was unbind().
static const std::string loggerCat_;
};
}
#endif // VERTEXATTRIBUTE_H__
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment