CUGL 3.0
Cornell University Game Library
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Protected Attributes | List of all members
cugl::graphics::InstanceBuffer Class Reference

#include <CUInstanceBuffer.h>

Inheritance diagram for cugl::graphics::InstanceBuffer:
cugl::graphics::VertexBuffer

Public Member Functions

 InstanceBuffer ()
 
 ~InstanceBuffer ()
 
void dispose () override
 
bool init (GLsizei size, GLsizei stride) override
 
bool init (GLsizei tsize, GLsizei tstride, GLsizei isize, GLsizei istride)
 
void attach (const std::shared_ptr< Shader > &shader) override
 
GLsizei getInstanceCapacity () const
 
GLsizei getInstanceStride () const
 
void loadInstanceData (const void *data, GLsizei size, GLenum usage=GL_STREAM_DRAW)
 
void drawInstanced (GLenum mode, GLsizei count, GLsizei instances, GLint offset=0)
 
void drawInstancedDirect (GLenum mode, GLint first, GLsizei count, GLsizei instances)
 
void setupInstanceAttribute (const std::string name, GLint size, GLenum type, GLboolean norm, GLsizei offset)
 
- Public Member Functions inherited from cugl::graphics::VertexBuffer
 VertexBuffer ()
 
 ~VertexBuffer ()
 
virtual void dispose ()
 
virtual bool init (GLsizei size, GLsizei stride)
 
void bind ()
 
void unbind ()
 
virtual void attach (const std::shared_ptr< Shader > &shader)
 
std::shared_ptr< Shaderdetach ()
 
std::shared_ptr< ShadergetShader () const
 
bool isBound () const
 
GLsizei getCapacity () const
 
GLsizei getStride () const
 
void loadVertexData (const void *data, GLsizei size, GLenum usage=GL_STREAM_DRAW)
 
void loadIndexData (const void *data, GLsizei size, GLenum usage=GL_STREAM_DRAW)
 
void draw (GLenum mode, GLsizei count, GLint offset=0)
 
void drawDirect (GLenum mode, GLint first, GLsizei count)
 
virtual void setupAttribute (const std::string name, GLint size, GLenum type, GLboolean norm, GLsizei offset)
 
void enableAttribute (const std::string name)
 
void disableAttribute (const std::string name)
 

Static Public Member Functions

static std::shared_ptr< InstanceBufferalloc (GLsizei size, GLsizei stride)
 
static std::shared_ptr< InstanceBufferalloc (GLsizei tsize, GLsizei tstride, GLsizei isize, GLsizei istride)
 
- Static Public Member Functions inherited from cugl::graphics::VertexBuffer
static std::shared_ptr< VertexBufferalloc (GLsizei size, GLsizei stride)
 

Protected Attributes

GLsizei _instanceSize
 
GLsizei _instanceStride
 
GLuint _instanceBuffer
 
std::unordered_map< std::string, AttribData_instAttribs
 
- Protected Attributes inherited from cugl::graphics::VertexBuffer
GLsizei _size
 
GLsizei _stride
 
GLuint _vertArray
 
GLuint _vertBuffer
 
GLuint _indxBuffer
 
std::shared_ptr< Shader_shader
 
std::unordered_map< std::string, bool > _enabled
 
std::unordered_map< std::string, AttribData_attributes
 

Detailed Description

This class defines a vertex buffer for drawing instanced shapes.

This class is an alternative to VertexBuffer for those cases in which you need to instance a simple mesh (e.g. particle systems). It separates the buffer data into two groups: the template and the instance data. The template is the mesh data repeated every instance. The instance data is the unique data for each instance. By design, template data is designed to be static, while instance data is designed to be streamed.

The template mesh uses these methods inherited from VertexBuffer. Indeed, if you restrict yourself to only the inherited methods, this class behaves exactly like VertexBuffer. Instancing is provided by the new methods.

For simplicity, we do not support instance depths (e.g glVertexAttribDivisor) greater than 1. If you need that level of control, you should create your own abstraction.

A instance buffer must be attached to a shader to be used. However, an instance buffer can swap shaders at any time, which is why this class is separated out. Unlike Texture and UniformBuffer, an instance buffer does not have a true many one relationship with a Shader object. An instance buffer can only be connected to one shader at a time and vice versa. So we model this as a direct connection. As instance buffers push data to a shader, the dependency requires that a shader be linked to an instance buffer object.

This class tries to remain loosely coupled with its shader. If the instance buffer has attributes lacking in the shader, they will be ignored. If it is missing attributes that the shader expects, the shader will use the default value for the type.

As with VertexBuffer, we allow the mesh data to be indexed, though that is not required. The index data is applied to the template, not the instance data.

Constructor & Destructor Documentation

◆ InstanceBuffer()

cugl::graphics::InstanceBuffer::InstanceBuffer ( )
inline

Creates an uninitialized instance buffer.

You must initialize the instance buffer to allocate buffer memory.

◆ ~InstanceBuffer()

cugl::graphics::InstanceBuffer::~InstanceBuffer ( )
inline

Deletes this instance buffer, disposing all resources.

Member Function Documentation

◆ alloc() [1/2]

static std::shared_ptr< InstanceBuffer > cugl::graphics::InstanceBuffer::alloc ( GLsizei  size,
GLsizei  stride 
)
inlinestatic

Returns a new instance buffer to support the given strides.

The stride is the size of a single piece of vertex data. The instance buffer needs this value to set attribute locations for both the template and the instance buffers. In this initializer, these are assumed to be the same value.

Since changing these values fundamentally changes the type of data that can be sent to this instance buffer, they are set at buffer creation and cannot be changed. It is possible for a stride to be 0, but only if that layer consists of a single attribute. Using stride 0 is not recommended.

For performance reasons, we also require that the instance buffer specify a maximum size. This size is applied to everything: vertex, index, and instance data. So it should be the maximum of all of them. Size is specified in terms of maximum elements, not bytes.

Parameters
sizeThe maximum number of elements in this buffer
strideThe size of a single piece of data (template or instance)
Returns
a new instance buffer to support the given strides.

◆ alloc() [2/2]

static std::shared_ptr< InstanceBuffer > cugl::graphics::InstanceBuffer::alloc ( GLsizei  tsize,
GLsizei  tstride,
GLsizei  isize,
GLsizei  istride 
)
inlinestatic

Returns a new instance buffer to support the given strides.

The stride is the size of a single piece of vertex data. The instance buffer needs this value to set attribute locations for both the template and the instance buffers. Note that these values do not have to be the same as these buffers are separate.

Since changing these values fundamentally changes the type of data that can be sent to this instance buffer, they are set at buffer creation and cannot be changed. It is possible for a stride to be 0, but only if that layer consists of a single attribute. Using stride 0 is not recommended.

For performance reasons, we also require that the instance buffer specify a maximum size. The template size is applied both the template vertices and the indices. So it should be the maximum of both. Size is specified in terms of maximum elements, not bytes.

Parameters
tsizeThe maximum number of elements in the template later
tstrideThe size of a single piece of data in the template layer
isizeThe maximum number of elements in the instance later
istrideThe size of a single piece of data in the instance layer
Returns
a new instance buffer to support the given strides.

◆ attach()

void cugl::graphics::InstanceBuffer::attach ( const std::shared_ptr< Shader > &  shader)
overridevirtual

Attaches the given shader to this instance buffer.

This method will link all enabled attributes in this instance buffer (warning about any attributes that are missing from the shader). It will also immediately bind both the instance buffer and the shader, making them ready to use.

Parameters
shaderThe shader to attach

Reimplemented from cugl::graphics::VertexBuffer.

◆ dispose()

void cugl::graphics::InstanceBuffer::dispose ( )
overridevirtual

Deletes the instance buffer, freeing all resources.

You must reinitialize the instance buffer to use it.

Reimplemented from cugl::graphics::VertexBuffer.

◆ drawInstanced()

void cugl::graphics::InstanceBuffer::drawInstanced ( GLenum  mode,
GLsizei  count,
GLsizei  instances,
GLint  offset = 0 
)

Draws to the active framebuffer using this instance buffer

This draw command will instance the mesh defined by both the vertex and index data. The count parameter determines the number of indices to use in the base mesh, while the instances parameter determines the number of indices. The optional paramter offset is for the offset into the indices, not the instances.

Any call to this command will use the current texture and uniforms. If the texture and/or uniforms need to be changed, then this draw command will need to be broken up into chunks. Use the optional parameter offset to chunk up the draw calls without having to reload data.

The drawing mode can be any of GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN or GL_TRIANGLES. These are the only modes accepted by both OpenGL and OpenGLES. See the OpenGL documentation for the number of indices required for each type. In practice the Poly2 class is designed to support GL_POINTS, GL_LINES, and GL_TRIANGLES only.

This method will only succeed if this buffer is actively bound.

Parameters
modeThe OpenGLES drawing mode
countThe number of vertices in the base mesh
instancesThe number of mesh instances
offsetThe initial index to start the mesh

◆ drawInstancedDirect()

void cugl::graphics::InstanceBuffer::drawInstancedDirect ( GLenum  mode,
GLint  first,
GLsizei  count,
GLsizei  instances 
)

Draws to the active framebuffer using this instance buffer

This draw command will instance the mesh defined in the vertex buffer the given number of times. In defining the mesh, it will bypass the index buffer, and draw the vertices in order starting from the first specified vertex.

Any call to this command will use the current texture and uniforms. If the texture and/or uniforms need to be changed, then this draw command will need to be broken up into chunks. Use the initial offset parameter to chunk up the draw calls without having to reload data.

The drawing mode can be any of GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN or GL_TRIANGLES. These are the only modes accepted by both OpenGL and OpenGLES. See the OpenGL documentation for the number of indices required for each type. In practice the Poly2 class is designed to support GL_POINTS, GL_LINES, and GL_TRIANGLES only.

This method will only succeed if this buffer is actively bound.

Parameters
modeThe OpenGLES drawing mode
firstThe initial vertex in the base mesh
countThe number of vertices in the base mesh
instancesThe number of mesh instances

◆ getInstanceCapacity()

GLsizei cugl::graphics::InstanceBuffer::getInstanceCapacity ( ) const
inline

Returns the maximum capacity of the instance layer.

The size determines the number of elements that can be loaded with loadInstanceData.

Returns
the maximum capacity of the instance layer.

◆ getInstanceStride()

GLsizei cugl::graphics::InstanceBuffer::getInstanceStride ( ) const
inline

Returns the stride of the instance layer.

The data loaded into the instance layer is expected to have the size of this stride. If it does not, strange things will happen.

Returns
the stride of of the instance layer.

◆ init() [1/2]

bool cugl::graphics::InstanceBuffer::init ( GLsizei  size,
GLsizei  stride 
)
inlineoverridevirtual

Initializes this instance buffer to support the given stride

The stride is the size of a single piece of vertex data. The instance buffer needs this value to set attribute locations for both the template and the instance buffers. In this initializer, these are assumed to be the same value.

Since changing these values fundamentally changes the type of data that can be sent to this instance buffer, they are set at buffer creation and cannot be changed. It is possible for a stride to be 0, but only if that layer consists of a single attribute. Using stride 0 is not recommended.

For performance reasons, we also require that the instance buffer specify a maximum size. This size is applied to everything: vertex, index, and instance data. So it should be the maximum of all of them. Size is specified in terms of maximum elements, not bytes.

Parameters
sizeThe maximum number of elements in this buffer
strideThe size of a single piece of data (template or instance)
Returns
true if initialization was successful.

Reimplemented from cugl::graphics::VertexBuffer.

◆ init() [2/2]

bool cugl::graphics::InstanceBuffer::init ( GLsizei  tsize,
GLsizei  tstride,
GLsizei  isize,
GLsizei  istride 
)

Initializes this instance buffer to support the given strides

The stride is the size of a single piece of vertex data. The instance buffer needs this value to set attribute locations for both the template and the instance buffers. Note that these values do not have to be the same as these buffers are separate.

Since changing these values fundamentally changes the type of data that can be sent to this instance buffer, they are set at buffer creation and cannot be changed. It is possible for a stride to be 0, but only if that layer consists of a single attribute. Using stride 0 is not recommended.

For performance reasons, we also require that the instance buffer specify a maximum size. The template size is applied both the template vertices and the indices. So it should be the maximum of both. Size is specified in terms of maximum elements, not bytes.

Parameters
tsizeThe maximum number of elements in the template later
tstrideThe size of a single piece of data in the template layer
isizeThe maximum number of elements in the instance later
istrideThe size of a single piece of data in the instance layer
Returns
true if initialization was successful.

◆ loadInstanceData()

void cugl::graphics::InstanceBuffer::loadInstanceData ( const void *  data,
GLsizei  size,
GLenum  usage = GL_STREAM_DRAW 
)

Loads the given instance buffer with data.

The data loaded is the data that will be used at the next call to either drawInstanced or drawInstancedDirect. It will be combined with the vertex/index data the render the final image.

The data loaded is expected to have the size of the instance buffer stride. If it does not, strange things will happen.

The usage is one of GL_STATIC_DRAW, GL_STREAM_DRAW, or GL_DYNAMIC_DRAW. Static drawing should be reserved for vertices and/or indices that do not change (so all animation happens in uniforms). Instance data is typically streaming (as is with the case of particle systems), so it is generally best to choose GL_STREAM_DRAW.

This method will only succeed if this buffer is actively bound.

Parameters
dataThe data to load
sizeThe number of instances to load
usageThe type of data load

◆ setupInstanceAttribute()

void cugl::graphics::InstanceBuffer::setupInstanceAttribute ( const std::string  name,
GLint  size,
GLenum  type,
GLboolean  norm,
GLsizei  offset 
)

Initializes an instance attribute, assigning is a size, type and offset.

This method is necessary for the instance buffer to convey data to the shader. Without it, the shader will used default values for the attribute rather than data from the instance buffer.

It is safe to call this method even when the shader is not attached. The values will be cached and will be used to link this buffer to the shader when the shader is attached. This also means that a instance buffer can swap shaders without having to reinitialize attributes. If a shader is attached, the attribute will be enabled immediately.

If the attribute does not refer to one supported by the active shader, then it will be ignored (e.g. the effect is the same as disabling the attribute).

The attribute type can be one of GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_HALF_FLOAT, GL_FLOAT, GL_FIXED, or GL_INT_2_10_10_10_REV. Doubles are not supported by OpenGLES.

The attribute offset is measured in bytes from the start of the instance data structure (for a single instance).

Parameters
nameThe attribute name
sizeThe attribute size in byte.
typeThe attribute type
normWhether to normalize the value (floating point only)
offsetThe attribute offset in the vertex data structure

Member Data Documentation

◆ _instanceBuffer

GLuint cugl::graphics::InstanceBuffer::_instanceBuffer
protected

The buffer for the instance data

◆ _instanceSize

GLsizei cugl::graphics::InstanceBuffer::_instanceSize
protected

The maximums size of the instance layer

◆ _instanceStride

GLsizei cugl::graphics::InstanceBuffer::_instanceStride
protected

The data stride of the instance layer (0 if there is only one attribute)

◆ _instAttribs

std::unordered_map<std::string, AttribData> cugl::graphics::InstanceBuffer::_instAttribs
protected

The instance attributes


The documentation for this class was generated from the following file: