From 5a0b3927a33807cca4c77c40eb873f8a3b51b0b0 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 29 Apr 2023 19:07:11 +0100 Subject: Drop .hpp for header only things Half of them acquired a .cpp part anyway --- gfx/gl/vertexArrayObject.h | 109 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 gfx/gl/vertexArrayObject.h (limited to 'gfx/gl/vertexArrayObject.h') diff --git a/gfx/gl/vertexArrayObject.h b/gfx/gl/vertexArrayObject.h new file mode 100644 index 0000000..085cba6 --- /dev/null +++ b/gfx/gl/vertexArrayObject.h @@ -0,0 +1,109 @@ +#pragma once + +#include "collections.h" +#include "gl_traits.h" +#include "special_members.h" +#include + +class VertexArrayObject { +public: + template [[nodiscard]] VertexArrayObject(const T & arrayObject) + { + glBindVertexArray(arrayObject); + } + ~VertexArrayObject() + { + glBindVertexArray(0); + } + NO_MOVE(VertexArrayObject); + NO_COPY(VertexArrayObject); + + template struct MP { + constexpr MP(m T::*p) : P {p} { } + operator void *() const + { + return &(static_cast(nullptr)->*P); + } + m T::*P; + using value_type = m; + }; + template MP(m T::*) -> MP; + + template + VertexArrayObject & + addAttribs(const GLuint arrayBuffer, const SequentialCollection auto & vertices, const GLuint divisor = 0) + { + addAttribs(arrayBuffer, divisor); + data(vertices, arrayBuffer, GL_ARRAY_BUFFER); + return *this; + } + + template + VertexArrayObject & + addAttribs(const GLuint arrayBuffer, const GLuint divisor = 0) + { + configure_attribs(arrayBuffer, divisor); + return *this; + } + + template + VertexArrayObject & + addIndices(const GLuint arrayBuffer, const Indices & indices) + { + data(indices, arrayBuffer, GL_ELEMENT_ARRAY_BUFFER); + return *this; + } + + VertexArrayObject & + addIndices(const GLuint arrayBuffer) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrayBuffer); + return *this; + } + + template + static void + data(const Data & data, const GLuint arrayBuffer, GLenum target) + { + using Value = typename Data::value_type; + glBindBuffer(target, arrayBuffer); + glBufferData(target, static_cast(sizeof(Value) * data.size()), data.data(), GL_STATIC_DRAW); + } + +private: + template + static auto + set_pointer(const GLuint vertexArrayId, const void * ptr, const GLuint divisor) + { + using traits = gl_traits; + const auto usedAttribs + = traits::vertexAttribFunc(vertexArrayId, traits::size, traits::type, sizeof(VertexT), ptr); + for (GLuint i {}; i < usedAttribs; i++) { + glEnableVertexAttribArray(vertexArrayId + i); + glVertexAttribDivisor(vertexArrayId + i, divisor); + } + return usedAttribs; + } + + template + static auto + set_pointer(const GLuint vertexArrayId, const GLuint divisor) + { + return set_pointer(vertexArrayId, attrib, divisor); + } + + template + void + configure_attribs(const GLuint arrayBuffer, const GLuint divisor) + { + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + if constexpr (sizeof...(attribs) == 0) { + vertexArrayId += set_pointer(vertexArrayId, nullptr, divisor); + } + else { + ((vertexArrayId += set_pointer(vertexArrayId, divisor)), ...); + } + } + + GLuint vertexArrayId {}; +}; -- cgit v1.2.3