#pragma once #include "collections.hpp" #include "gl_traits.hpp" #include #include template class VertexArrayObject { public: template static void configure(const GLuint arrayObject, const GLuint arrayBuffer, const GLuint indexBuffer, const SequentialCollection auto & vertices, const SequentialCollection auto & indices) { glBindVertexArray(arrayObject); configure_attribs(arrayBuffer); data(vertices, arrayBuffer, GL_ARRAY_BUFFER); data(indices, indexBuffer, GL_ELEMENT_ARRAY_BUFFER); glBindVertexArray(0); } template static void configure(const GLuint arrayObject, const GLuint arrayBuffer, const SequentialCollection auto & vertices) { glBindVertexArray(arrayObject); configure_attribs(arrayBuffer); data(vertices, arrayBuffer, GL_ARRAY_BUFFER); glBindVertexArray(0); } template static void configure(const GLuint arrayObject, const GLuint arrayBuffer) { glBindVertexArray(arrayObject); configure_attribs(arrayBuffer); glBufferData(GL_ARRAY_BUFFER, static_cast(sizeof(Vertex)), nullptr, GL_DYNAMIC_DRAW); glBindVertexArray(0); } private: template static void data(const Data & data, const GLuint arrayBuffer, GLenum target) { using Value = typename Data::element_type; glBindBuffer(target, arrayBuffer); glBufferData(target, static_cast(sizeof(Value) * data.size()), data.data(), GL_STATIC_DRAW); } template static void set_pointer(GLuint & vertexArrayId) { glEnableVertexAttribArray(vertexArrayId); using traits = gl_traits().*attrib)>>; glVertexAttribPointer(vertexArrayId++, traits::size, traits::type, GL_FALSE, sizeof(Vertex), &(static_cast(nullptr)->*attrib)); } template static void configure_attribs(const GLuint arrayBuffer) { glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); GLuint vertexArrayId {}; (set_pointer(vertexArrayId), ...); } };