easy-gl › VertexArray

VertexArray

Manages an OpenGL Vertex Array Object (VAO). Captures vertex attribute format, buffer bindings and the element array buffer binding.

VertexAttribute struct

struct VertexAttribute {
    unsigned int index           = 0;
    int          components      = 0;         // 1–4
    DataType     type            = DataType::Float;
    bool         normalized      = false;
    std::size_t  stride_in_bytes = 0;
    std::size_t  offset_in_bytes = 0;
    bool         enabled         = true;
};

Basic usage — interleaved attributes

struct Vertex {
    float pos[3];
    float normal[3];
    float uv[2];
};

easygl::VertexArray vao;
easygl::Buffer      vbo;
vao.create();
vbo.create();

vao.bind();
vbo.bind(easygl::BufferTarget::Array);
vbo.set_data(easygl::BufferTarget::Array, meshVertices, vertexCount * sizeof(Vertex));

constexpr std::size_t stride = sizeof(Vertex);

vao.set_attribute(easygl::VertexAttribute{
    .index = 0, .components = 3, .type = easygl::DataType::Float,
    .normalized = false, .stride_in_bytes = stride,
    .offset_in_bytes = offsetof(Vertex, pos), .enabled = true});

vao.set_attribute(easygl::VertexAttribute{
    .index = 1, .components = 3, .type = easygl::DataType::Float,
    .normalized = false, .stride_in_bytes = stride,
    .offset_in_bytes = offsetof(Vertex, normal), .enabled = true});

vao.set_attribute(easygl::VertexAttribute{
    .index = 2, .components = 2, .type = easygl::DataType::Float,
    .normalized = false, .stride_in_bytes = stride,
    .offset_in_bytes = offsetof(Vertex, uv), .enabled = true});

Integer attributes (flat inputs in shaders)

// Use set_attribute_i_pointer for int/uint attributes
vao.set_attribute_i_pointer(
    3,                                   // index
    4,                                   // components
    easygl::DataType::UnsignedByte,
    sizeof(Vertex),
    reinterpret_cast<const void*>(offsetof(Vertex, boneIds)));

Instancing — per-instance attributes

// modelMatrices buffer is bound separately
instanceVbo.bind(easygl::BufferTarget::Array);

// mat4 takes 4 attribute slots (one per row)
for (unsigned int i = 0; i < 4; ++i) {
    vao.set_attribute_pointer(
        4 + i, 4, easygl::DataType::Float, false,
        64,   // stride = sizeof(mat4)
        reinterpret_cast<const void*>(i * 16));
    vao.enable_attribute(4 + i);
    vao.set_attribute_divisor(4 + i, 1); // advance once per instance
}

With an index buffer

vao.bind();
vbo.bind(easygl::BufferTarget::Array);
ibo.bind(easygl::BufferTarget::ElementArray); // captured by the VAO
// ... set attributes ...

// Render:
vao.bind();
device.draw_elements(easygl::PrimitiveType::Triangles,
                       indexCount, easygl::DataType::UnsignedInt, nullptr);

Method reference

MethodDescription
create()Allocate GL VAO handle.
destroy()Free handle. Noexcept.
bind()Bind this VAO.
unbind()Bind VAO 0 (unbind).
set_attribute(VertexAttribute)Configure and optionally enable a vertex attribute.
set_attribute_pointer(idx, size, type, norm, stride, ptr)Low-level attribute pointer setup.
set_attribute_i_pointer(idx, size, type, stride, ptr)Integer attribute pointer (no float conversion).
enable_attribute(idx)Enable vertex attribute at index.
disable_attribute(idx)Disable vertex attribute at index.
set_attribute_divisor(idx, divisor)Set instancing divisor (0 = per-vertex, 1 = per-instance).
is_created()True if GL handle allocated.
native_handle()Raw GL integer ID.
reset_handle_no_gl()Context-loss recovery.