attribute index exception, overload attributes bind, model add and bind methods

This commit is contained in:
ohsqueezy 2023-07-18 23:19:57 -04:00
parent d1fe6b927c
commit cd66f70d0c
6 changed files with 243 additions and 67 deletions

View File

@ -10,32 +10,25 @@
#include "Attributes.hpp" #include "Attributes.hpp"
/* Set the generic vertex attribute index for the attributes. It must be the same index that is
* returned when glGetAttribLocation is given the shader program and variable name the attributes
* will be associated with. The bind class member functions can automatically do that, and they
* should be used instead of this function if possible.
*
* The index may be specified to GL in the shader source code using the location layout qualifier
* in GLSL 3.3 and above. It can also be set automatically by GL when a shader program is linked.
* In both cases, the return value of glGetAttribLocation should be passed to this function.
* Otherwise, this index can be an arbitrary choice that is not greater than GL_MAX_VERTEX_ATTRIBS,
* in which case it would be explicitly passed to glBindAttribLocation.
*
* Once assigned, the index can be passed to glVertexAttribPointer to set the properties of the
* attributes on the GPU, either manually or automatically through the add member function in the
* VBO class. */
void sb::Attributes::index(GLint index) void sb::Attributes::index(GLint index)
{ {
attribute_index = index; _index = index;
} }
/* Returns the generic vertex attribute index for the attributes. This index can be passed to
* glBindAttribLocation to assign the index to a shader input variable if the index isn't already
* assigned by a layout qualifier in the GLSL source code. The index should be passed to
* glVertexAttribPointer to specify the location to use when rendering. */
GLint sb::Attributes::index() const GLint sb::Attributes::index() const
{ {
return attribute_index; try
{
return std::get<GLint>(_index);
}
catch (const std::bad_variant_access&)
{
std::ostringstream message;
message << "Trying to get index for " << dimensions() << "D " << size() << "b attributes, but no index has been set yet. Assign an"
<< " index with glBindAttribLocation and copy it to Attributes::index(GLint) or look up the index automatically at bind time by"
<< " passing the location name and linked shader program index to Attributes::bind(const std::string&, GLuint).";
throw std::runtime_error(message.str());
}
} }
void sb::Attributes::offset(GLintptr offset) void sb::Attributes::offset(GLintptr offset)
@ -43,7 +36,6 @@ void sb::Attributes::offset(GLintptr offset)
_offset = offset; _offset = offset;
} }
/* Returns the count of attributes */
std::size_t sb::Attributes::count() const std::size_t sb::Attributes::count() const
{ {
return std::visit([] (const auto& vector) -> std::size_t { return std::visit([] (const auto& vector) -> std::size_t {
@ -59,8 +51,6 @@ std::size_t sb::Attributes::count() const
}, vertices); }, vertices);
} }
/* Returns the size in bytes of the object's underlying vector of vertices. This can be passed to OpenGL
* along with the memory pointer when copying vertices to the GPU. */
std::size_t sb::Attributes::size() const std::size_t sb::Attributes::size() const
{ {
return std::visit([] (const auto& vector) -> std::size_t { return std::visit([] (const auto& vector) -> std::size_t {
@ -76,6 +66,17 @@ std::size_t sb::Attributes::size() const
}, vertices); }, vertices);
} }
void sb::Attributes::bind() const
{
/* Define an array of vertex attributes that have data stored at the specified offset. */
glVertexAttribPointer(index(), dimensions(), type(), normalized(), 0, reinterpret_cast<GLvoid*>(_offset));
/* Debug */
std::ostringstream message;
message << "After binding " << *this;
sb::Log::gl_errors(message.str());
}
void sb::Attributes::bind(const std::string& name, GLuint program) void sb::Attributes::bind(const std::string& name, GLuint program)
{ {
GLint index = glGetAttribLocation(program, name.c_str()); GLint index = glGetAttribLocation(program, name.c_str());
@ -96,13 +97,8 @@ void sb::Attributes::bind(const std::string& name, GLuint program)
message << "After getting attribute location of " << name; message << "After getting attribute location of " << name;
sb::Log::gl_errors(message.str()); sb::Log::gl_errors(message.str());
/* Define an array of vertex attributes that have data stored at the specified offset. */ /* Call glVertexAttribPointer with the index */
glVertexAttribPointer(this->index(), dimensions(), type(), normalized(), 0, reinterpret_cast<GLvoid*>(_offset)); bind();
/* Debug */
message = std::ostringstream();
message << "After binding " << *this << " to " << name;
sb::Log::gl_errors(message.str());
} }
void sb::Attributes::enable() const void sb::Attributes::enable() const
@ -115,10 +111,6 @@ void sb::Attributes::disable() const
glDisableVertexAttribArray(*this); glDisableVertexAttribArray(*this);
} }
/* Return the GLenum that corresponds to the type of scalar being held in the vertices. This
* will return either GL_FLOAT, GL_INT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE, GL_BOOL, or
* GL_INVALID_ENUM. A return value of GL_INVALID_ENUM indicates an error meaning there are no
* attributes and no type exists yet. */
GLenum sb::Attributes::type() const GLenum sb::Attributes::type() const
{ {
return std::visit([] (const auto& vector) -> GLenum { return std::visit([] (const auto& vector) -> GLenum {
@ -159,7 +151,6 @@ GLenum sb::Attributes::type() const
}, vertices); }, vertices);
} }
/* Return the number of dimensions in the vertices. If there are no vertices, return 0. */
std::size_t sb::Attributes::dimensions() const std::size_t sb::Attributes::dimensions() const
{ {
return std::visit([] (const auto& vector) -> std::size_t { return std::visit([] (const auto& vector) -> std::size_t {
@ -183,14 +174,11 @@ std::size_t sb::Attributes::dimensions() const
}, vertices); }, vertices);
} }
/* Normalization isn't supported, so this always returns false */
bool sb::Attributes::normalized() const bool sb::Attributes::normalized() const
{ {
return false; return false;
} }
/* Returns a pointer to the first vertex in the object's underlying vector of vertices. This can be used
* along with the size function to pass the raw bytes of the vertices to the GPU. */
sb::Attributes::operator const void*() const sb::Attributes::operator const void*() const
{ {
return std::visit([] (const auto& vector) -> const void* { return std::visit([] (const auto& vector) -> const void* {
@ -206,7 +194,6 @@ sb::Attributes::operator const void*() const
}, vertices); }, vertices);
} }
/* Attributes can be represented by their GL index when an int is requested. */
sb::Attributes::operator int() const sb::Attributes::operator int() const
{ {
return index(); return index();
@ -248,7 +235,7 @@ void sb::Attributes::add(const Attributes& other)
if (!found) if (!found)
{ {
std::ostringstream message; std::ostringstream message;
message << "warning: " << other << " was not added to the attributes because its type is incompatible"; message << "warning: " << other << " was not added to " << *this << " because types are incompatible";
sb::Log::log(message); sb::Log::log(message);
} }
} }
@ -262,13 +249,9 @@ void sb::Attributes::extend(const Attributes& other, std::size_t count)
} }
} }
/* Overload the stream operator to support attributes. Add a string representation of the vertices to
* the output stream. Since this is defined as a friend function and isn't in the global scope, it should
* prevent it being looked up with arguments other than attributes. */
std::ostream& sb::operator<<(std::ostream& out, const Attributes& attributes) std::ostream& sb::operator<<(std::ostream& out, const Attributes& attributes)
{ {
out << "<Attributes #" << attributes.index() << ", " << attributes.dimensions() << "D, " << out << "<Attributes " << attributes.dimensions() << "D, " << attributes.size() << " bytes, ";
attributes.size() << " bytes, ";
std::visit([&] (const auto& vector) { std::visit([&] (const auto& vector) {
if constexpr (!std::is_same_v<std::decay_t<decltype(vector)>, std::monostate>) if constexpr (!std::is_same_v<std::decay_t<decltype(vector)>, std::monostate>)
{ {

View File

@ -1,4 +1,4 @@
/*!<pre> /*!
* /\ +------------------------------------------------------+ * /\ +------------------------------------------------------+
* ____/ \____ /| - Open source game framework licensed to freely use, | * ____/ \____ /| - Open source game framework licensed to freely use, |
* \ / / | copy, modify and sell without restriction | * \ / / | copy, modify and sell without restriction |
@ -7,7 +7,7 @@
* | ~~~~~~~~~~~~ | +------------------------------------------------------+ * | ~~~~~~~~~~~~ | +------------------------------------------------------+
* | SPACE ~~~~~ | / * | SPACE ~~~~~ | /
* | ~~~~~~~ BOX |/ * | ~~~~~~~ BOX |/
* +--------------+ </pre> * +--------------+
* *
* Attributes * Attributes
* ========== * ==========
@ -102,10 +102,11 @@
#include <initializer_list> #include <initializer_list>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <exception>
#include "glm/glm.hpp" #include "glm/glm.hpp"
#include "Log.hpp" #include "Log.hpp"
#include "extension.hpp" #include "extension.hpp"
namespace sb namespace sb
{ {
@ -118,6 +119,9 @@ namespace sb
private: private:
/* Memory offset in the VBO */
GLintptr _offset = 0;
/* Every type of vertex in the glm vertex types (bool, unsigned int, int, float) from 1D to 4D is included in this variant. /* Every type of vertex in the glm vertex types (bool, unsigned int, int, float) from 1D to 4D is included in this variant.
* Each variant alternative is a vector of vertex type, so only homogenous vectors can be used. Index 0 is the std::monostate * Each variant alternative is a vector of vertex type, so only homogenous vectors can be used. Index 0 is the std::monostate
* alternative, which is used here for default initialization to indicate Attributes are in an empty state where no variant * alternative, which is used here for default initialization to indicate Attributes are in an empty state where no variant
@ -130,8 +134,9 @@ namespace sb
std::vector<glm::bvec3>, std::vector<glm::uvec3>, std::vector<glm::ivec3>, std::vector<glm::vec3>, std::vector<glm::bvec3>, std::vector<glm::uvec3>, std::vector<glm::ivec3>, std::vector<glm::vec3>,
std::vector<glm::bvec4>, std::vector<glm::uvec4>, std::vector<glm::ivec4>, std::vector<glm::vec4>>; std::vector<glm::bvec4>, std::vector<glm::uvec4>, std::vector<glm::ivec4>, std::vector<glm::vec4>>;
Vertices vertices; Vertices vertices;
GLint attribute_index = 0;
GLintptr _offset = 0; /* Index is stored as a variant because it needs to be checked whether it is uninitialized (std::monostate) or not. */
std::variant<std::monostate, GLint> _index;
public: public:
@ -142,19 +147,26 @@ namespace sb
Attributes() {}; Attributes() {};
/*! /*!
* Construct a new Attributes object with vertices set to the vertices contained in this vector * Construct a new Attributes object with vertices set to the vertices contained in this vector.
*
* @param vertices vector of vertices
*/ */
template<typename Type> template<typename Type>
Attributes(const std::vector<Type>& vertices) : vertices(vertices) {} Attributes(const std::vector<Type>& vertices) : vertices(vertices) {}
/*! /*!
* Add a vertex. The vertex can be any of the variant types. * Add a vertex. The vertex can be any of the variant types.
*
* @param vertex vertex of 1 to 4 dimensions
*/ */
template<typename Type> template<typename Type>
Attributes(const Type& vertex) : Attributes({vertex}) {} Attributes(const Type& vertex) : Attributes({vertex}) {}
/*! /*!
* Add a vertex by specifying each coordinate as a separate argument. All arguments must have idential type. * Add a vertex by specifying each coordinate as a separate argument. All arguments must have identical type.
*
* @param coordinate_0 x coordinate
* @param coordinates y, z, and w coordinates can be specified as well, each as their own argument, using a parameter pack
*/ */
template<typename XType, typename... CoordinateTypes, template<typename XType, typename... CoordinateTypes,
std::enable_if_t<(... && std::is_same_v<CoordinateTypes, XType>), std::nullptr_t> = nullptr> std::enable_if_t<(... && std::is_same_v<CoordinateTypes, XType>), std::nullptr_t> = nullptr>
@ -165,6 +177,8 @@ namespace sb
* Add vertices by passing an uninitialized list of vertices. This template applies to a list of * Add vertices by passing an uninitialized list of vertices. This template applies to a list of
* vertices where the list type is undeclared but the containing vertices have been initialized * vertices where the list type is undeclared but the containing vertices have been initialized
* or the type can be inferred because the vertices are 1D scalars. * or the type can be inferred because the vertices are 1D scalars.
*
* @param vertices uninitialized list of initialized multidimensional vertices or uninitialized scalars
*/ */
template<typename VertexType> template<typename VertexType>
Attributes(const std::initializer_list<VertexType>& vertices) : Attributes(const std::initializer_list<VertexType>& vertices) :
@ -174,6 +188,8 @@ namespace sb
* Add vertices by passing a two-dimensional initializer list, a list of uninitialized vertices. * Add vertices by passing a two-dimensional initializer list, a list of uninitialized vertices.
* The appropriate glm vertex size is applied by looking at the length of the first uninitialized * The appropriate glm vertex size is applied by looking at the length of the first uninitialized
* vertex in the initializer list. * vertex in the initializer list.
*
* @param vertices uninitialized list of uninitialized vertices
*/ */
template<typename CoordinateType> template<typename CoordinateType>
Attributes(const std::initializer_list<std::initializer_list<CoordinateType>>& vertices) Attributes(const std::initializer_list<std::initializer_list<CoordinateType>>& vertices)
@ -277,7 +293,35 @@ namespace sb
*/ */
void extend(const Attributes& other, std::size_t count = 1); void extend(const Attributes& other, std::size_t count = 1);
void index(GLint); /*!
* Set the generic vertex attribute index for the attributes.
*
* This must be the same index that is returned when `glGetAttribLocation` is given the shader program and associated
* variable name for the attributes in the shader program.
*
* To make sure those align, either assign an arbitray index with `glBindAttribLocation` and pass it to this function, or
* skip this function and look up the index automatically at bind time by passing the location name and linked shader program
* index to sb::Attributes::bind(const std::string&, GLuint).
*
* The index may also be specified to GL in the shader source code using the location layout qualifier in GLSL 3.3 and above.
*
* If assigning an arbitrary index, this can be any integer not greater than `GL_MAX_VERTEX_ATTRIBS`, and it must also be
* passed to `glBindAttribLocation`.
*
* Once assigned, the index can be passed to `glVertexAttribPointer` to set the properties of the attributes on the GPU, either
* manually or automatically through sb::VBO::add(sb::Attributes&).
*
* @param index index the attributes bind to in the shader program
*/
void index(GLint index);
/*!
* Get the generic vertex attribute index for the attributes. This index can be passed to `glBindAttribLocation` to assign the
* index to a shader input variable if the index isn't already assigned by a layout qualifier in the GLSL source code. The
* index should be passed to `glVertexAttribPointer` to specify the location to use when rendering.
*
* @return index the attributes bind to in the shader program
*/
GLint index() const; GLint index() const;
/*! /*!
@ -288,12 +332,21 @@ namespace sb
*/ */
void offset(GLintptr offset); void offset(GLintptr offset);
/*!
* Create a pointer to these attributes in the VAO using this object's index and offset values by calling `glVertexAttribPointer`.
*
* The offset should have been previously set by a call to VBO::add(sb::Attributes&) or some equivalent in manual GL calls.
* The index should have been previously set to the index of the location in the shader program associated with the attributes
* using sb::Attributes::index(GLint) or some equivalent in manual GL calls.
*/
void bind() const;
/*! /*!
* Get the index of the uniform with the given name, store it as this object's index, and create a pointer to these * Get the index of the uniform with the given name, store it as this object's index, and create a pointer to these
* attributes in the VAO using this object's offset value. * attributes in the VAO using this object's offset value.
* *
* The offset should have been previously set by a call to `VBO::add` or some equivalent in manual GL calls. The program * The offset should have been previously set by a call to VBO::add(sb::Attributes&) or some equivalent in manual GL calls.
* must already be linked to get the location. * The program must already be linked to get the location.
* *
* @param name uniform name * @param name uniform name
* @param program GLSL program, created with glCreateProgram * @param program GLSL program, created with glCreateProgram
@ -313,13 +366,66 @@ namespace sb
*/ */
void disable() const; void disable() const;
/*!
* Get the size in bytes of the object's underlying vector of vertices. This can be passed to OpenGL along with the memory
* pointer when copying vertices to the GPU. It can also be used with sb::VBO::allocate(GLsizeiptr, GLenum).
*
* @return size in bytes of the attributes
*/
std::size_t size() const; std::size_t size() const;
/*!
* @return the number of attributes in the object
*/
std::size_t count() const; std::size_t count() const;
/*!
* Get the `GLenum` that corresponds to the type of scalar being held in the vertices. This will return either `GL_FLOAT`,
* `GL_INT`, `GL_UNSIGNED_INT`, `GL_UNSIGNED_BYTE`, `GL_BOOL`, or `GL_INVALID_ENUM`. A return value of `GL_INVALID_ENUM`
* indicates an error meaning there are no attributes and no type exists yet.
*
* @return the attributes type
*/
GLenum type() const; GLenum type() const;
/*!
* Get the number of dimensions in the vertices. If there are no vertices, return 0.
*
* @return number of dimensions in the vertices
*/
std::size_t dimensions() const; std::size_t dimensions() const;
/*!
* Normalization isn't supported, so this always returns `false`
*
* @return false
*/
bool normalized() const; bool normalized() const;
friend std::ostream& operator<<(std::ostream&, const Attributes&);
/*!
* Overload the stream operator to support attributes. Add a string representation of the vertices to the output stream. Since
* this is defined as a friend function and isn't in the global scope, it should prevent it being looked up with arguments other
* than attributes.
*
* @param out output stream
* @param attributes attributes object to print
* @return edited output stream
*/
friend std::ostream& operator<<(std::ostream& out, const Attributes& attributes);
/*!
* Get a pointer to the first vertex in the object's underlying vector of vertices. This can be used along with the size
* function to pass the raw bytes of the vertices to the GPU.
*
* @return pointer to the first vertex in the object's underlying vector of vertices
*/
operator const void*() const; operator const void*() const;
/*!
* Attributes can be represented by their GL index when an int is requested.
*
* @return index the attributes bind to in the shader program
*/
operator int() const; operator int() const;
}; };

View File

@ -77,8 +77,17 @@ std::shared_ptr<sb::Attributes>& sb::Model::operator[](const std::string& name)
void sb::Model::enable() const void sb::Model::enable() const
{ {
for (const auto& attributes : this->attributes()) for (const auto& attributes : this->attributes())
{ {
attributes.second->enable(); try
{
attributes.second->enable();
}
catch (const std::runtime_error& error)
{
std::ostringstream message;
message << "Error enabling " << attributes.first << " attributes on model";
throw std::runtime_error(message.str());
}
} }
} }
@ -136,7 +145,30 @@ void sb::Model::load()
texture.load(); texture.load();
} }
} }
void sb::Model::add(sb::VBO& vbo)
{
for (auto& [name, attributes] : attributes())
{
vbo.add(*attributes);
}
}
void sb::Model::bind()
{
/* Bind textures */
for (sb::Texture& texture : textures())
{
texture.bind();
}
/* Bind attributes */
for (auto& [name, attributes] : attributes())
{
attributes->bind();
}
}
const glm::mat4& sb::Model::transformation() const const glm::mat4& sb::Model::transformation() const
{ {
return _transformation; return _transformation;

View File

@ -30,6 +30,7 @@
#include "Attributes.hpp" #include "Attributes.hpp"
#include "Texture.hpp" #include "Texture.hpp"
#include "Carousel.hpp" #include "Carousel.hpp"
#include "VBO.hpp"
namespace sb namespace sb
{ {
@ -113,6 +114,8 @@ namespace sb
* Assign name to attributes, copy and wrap in a shared pointer. The model can share ownership of the created attribute * Assign name to attributes, copy and wrap in a shared pointer. The model can share ownership of the created attribute
* memory with callers that request it. * memory with callers that request it.
* *
* Any existing attributes with the same name will be replaced with the given attributes.
*
* @param attributes attributes object to copy and wrap * @param attributes attributes object to copy and wrap
* @param name name the model will associate with the attributes * @param name name the model will associate with the attributes
*/ */
@ -121,6 +124,8 @@ namespace sb
/*! /*!
* Assign name to attributes (for example, "position" or "uv") and share ownership. * Assign name to attributes (for example, "position" or "uv") and share ownership.
* *
* Any existing attributes with the same name will be replaced with the given attributes.
*
* @param attributes attributes object to share with this model * @param attributes attributes object to share with this model
* @param name name the model will associate with the attributes * @param name name the model will associate with the attributes
*/ */
@ -130,7 +135,15 @@ namespace sb
* Get the attributes under name, wrapped in the shared pointer held by this object. * Get the attributes under name, wrapped in the shared pointer held by this object.
* *
* This function uses operator[] or std::map, so this can be used to add new attributes to the object if they are * This function uses operator[] or std::map, so this can be used to add new attributes to the object if they are
* wrapped in a shared pointer. * wrapped in a shared pointer or the return value is deferenced.
*
* sb::Plane plane;
* sb::Attributes color_attributes;
* color_attributes.extend({255.0f, 0.0f, 0.0f, 255.0f}, plane["position"]->count());
* plane["color"] = std::make_shared<sb::Attributes>(color_attributes);
* // *plane["color"] = color_attributes; // same effect
* // plane.attributes(color_attributes, "color"); // same effect
* sprite = sb::Sprite(plane);
* *
* @param name name of the attributes to get * @param name name of the attributes to get
* @return writable reference to the attributes at name * @return writable reference to the attributes at name
@ -188,6 +201,22 @@ namespace sb
*/ */
void load(); void load();
/*!
* Add all attributes to the given vertex buffer object. The buffer object should have been previously allocated to at least the
* size of this model by passing Model::size() to VBO::allocate(GLsizeiptr, GLenum).
*
* The VBO must currently be bound.
*
* @param vbo vertex buffer object that the model's attribute vertices will be added to
*/
void add(sb::VBO& vbo);
/*!
* Bind all of this model's attributes and textures by calling each of their bind methods. Textures and attributes all must already
* have GL indices set, for example by calling Texture::generate() and Attributes::index(GLint) on each.
*/
void bind();
/*! /*!
* @return a constanst reference to the model's transformation matrix * @return a constanst reference to the model's transformation matrix
*/ */

View File

@ -164,6 +164,28 @@ namespace sb
plane.load(); plane.load();
} }
/*!
* Add all attributes to the given vertex buffer object. The buffer object should have been previously allocated to at least the
* size of this sprite by passing Sprite::size() to VBO::allocate(GLsizeiptr, GLenum).
*
* The VBO must currently be bound.
*
* @param vbo vertex buffer object that the sprite's attribute vertices will be added to
*/
void add(sb::VBO& vbo)
{
plane.add(vbo);
}
/*!
* Bind all of this sprite's attributes and textures by calling each of their bind methods. Textures and attributes all must already
* have GL indices set, for example by calling Texture::generate() and Attributes::index(GLint) on each.
*/
void bind()
{
plane.bind();
}
/*! /*!
* Get a reference to the plane object's shared pointer to the attributes with the given name. The underlying attributes * Get a reference to the plane object's shared pointer to the attributes with the given name. The underlying attributes
* object is fully exposed, meaning it can be edited, and both its const and non-const methods can be used. * object is fully exposed, meaning it can be edited, and both its const and non-const methods can be used.
@ -258,6 +280,8 @@ namespace sb
* this sprite, and false if not. The currently bound shader should be written to use that flag. For example, it could use the * this sprite, and false if not. The currently bound shader should be written to use that flag. For example, it could use the
* flag to choose whether to use the UV or the color attributes. * flag to choose whether to use the UV or the color attributes.
* *
* The vertex data is expected to be bound before this function is called.
*
* @param transformation_uniform transformation uniform ID * @param transformation_uniform transformation uniform ID
* @param view the view matrix for transforming from world space to camera space * @param view the view matrix for transforming from world space to camera space
* @param projection projection matrix for transforming from camera space to clip space * @param projection projection matrix for transforming from camera space to clip space

View File

@ -67,20 +67,22 @@ namespace sb
* GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. If using `glBufferSubData` directly to change the VBO's data frequently, a value other than the * GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. If using `glBufferSubData` directly to change the VBO's data frequently, a value other than the
* default GL_STATIC_DRAW can be used. * default GL_STATIC_DRAW can be used.
* *
* The VBO must currently be bound.
*
* @param size number of bytes of GPU memory to allocate to the buffer * @param size number of bytes of GPU memory to allocate to the buffer
* @param usage indicator to the GL implementation of how the data will be used, see `glBufferData` for info * @param usage indicator to the GL implementation of how the data will be used, see `glBufferData` for info
*/ */
void allocate(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW); void allocate(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW);
/*! /*!
* Set memory in the GPU buffer to the values of the attribute data using `glBufferSubData`. The memory * Set memory in the GPU buffer to the values of the attribute data using `glBufferSubData`. The memory is a contiguous area from the
* is a contiguous area from the object's current byte offset value to the offset plus the size in * object's current byte offset value to the offset plus the size in bytes of the attributes. After the memory is set, the offset is
* bytes of the attributes. After the memory is set, the offset is updated to point to the end of the * updated to point to the end of the area.
* area.
* *
* The offset is stored in the sb::Attributes object, so the object can associate the vertex data with * The offset replaces the currently set offset in the sb::Attributes object, so the attributes object can associate its vertex data with
* the VAO by passing the offset along when it calls glVertexAttribPointer in its sb::Attributes::bind * the VAO by passing the offset along when it calls `glVertexAttribPointer` in its sb::Attributes::bind() method.
* method. *
* The VBO must currently be bound.
* *
* @warning This function is expected to change in the future to allow more control over the offset so * @warning This function is expected to change in the future to allow more control over the offset so
* the VBO can be refilled using this class. * the VBO can be refilled using this class.