diff --git a/include/graphics/vao.hpp b/include/graphics/vao.hpp
new file mode 100644
index 0000000..477991c
--- /dev/null
+++ b/include/graphics/vao.hpp
@@ -0,0 +1,131 @@
+/**
+ This file is a part of our_dick
+ Copyright (C) 2020 rexy712
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef OUR_DICK_GRAPHICS_VAO_HPP
+#define OUR_DICK_GRAPHICS_VAO_HPP
+
+#include "gl_include.hpp"
+#include "math/math.hpp"
+
+namespace graphics{
+ using namespace math;
+
+ class vertex_attribute;
+
+ //class representing a vertex array object
+ class vao
+ {
+ private:
+ GLuint m_buffer; //handle to the vertex array
+
+ public:
+ //create a default initialized opengl vao
+ vao();
+ vao(const vao&) = delete;
+ vao(vao&&);
+ ~vao();
+
+ vao& operator=(const vao&) = delete;
+ vao& operator=(vao&&);
+
+ //Get access to a generic vertex attribute within this vao
+ vertex_attribute get_attribute(int index);
+
+ //bind this vao for use with rendering program
+ void bind();
+ //unbind this vao and rebind state machine to 0
+ void unbind();
+ };
+
+ //class representing a generic vertex attribute in a vao
+ class vertex_attribute
+ {
+ private:
+ GLuint m_vao; //handle to vertex array object
+ int m_index; //index of this attribute
+ public:
+ constexpr vertex_attribute(GLuint vao, int index):
+ m_vao(vao),
+ m_index(index){}
+ constexpr vertex_attribute(const vertex_attribute&) = default;
+ constexpr vertex_attribute(vertex_attribute&&) = default;
+ ~vertex_attribute() = default;
+
+ constexpr vertex_attribute& operator=(const vertex_attribute&) = default;
+ constexpr vertex_attribute& operator=(vertex_attribute&&) = default;
+
+ //enable use as an array attribute (most likely what is desired)
+ void enable_array_mode();
+ //disable use as an array attribute. used for static data in attributes during rendering
+ void disable_array_mode();
+
+ //setters for use in array mode. Same arguments as glVertexAttribPointer but these take arguments
+ //as object counts rather than bytes. a valid vbo must be bound to buffers::array_buffer before these are called.
+ void set_float_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_double_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_byte_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_ubyte_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_short_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_ushort_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_int_pointer(GLint size, GLsizei stride, GLsizei offset);
+ void set_uint_pointer(GLint size, GLsizei stride, GLsizei offset);
+
+ //setters for use in non array mode
+ void set(GLfloat);
+ void set(GLshort);
+ void set(GLdouble);
+ void set(GLint);
+ void set(GLuint);
+ void set(GLfloat, GLfloat);
+ void set(GLshort, GLshort);
+ void set(GLdouble, GLdouble);
+ void set(GLint, GLint);
+ void set(GLuint, GLuint);
+ void set(GLfloat, GLfloat, GLfloat);
+ void set(GLshort, GLshort, GLshort);
+ void set(GLdouble, GLdouble, GLdouble);
+ void set(GLint, GLint, GLint);
+ void set(GLuint, GLuint, GLuint);
+ void set(GLfloat, GLfloat, GLfloat, GLfloat);
+ void set(GLshort, GLshort, GLshort, GLshort);
+ void set(GLdouble, GLdouble, GLdouble, GLdouble);
+ void set(GLint, GLint, GLint, GLint);
+ void set(GLuint, GLuint, GLuint, GLuint);
+ void set(const vec2&);
+ void set(const vec2&);
+ void set(const vec2&);
+ void set(const vec2&);
+ void set(const vec2&);
+ void set(const vec3&);
+ void set(const vec3&);
+ void set(const vec3&);
+ void set(const vec3&);
+ void set(const vec3&);
+ void set(const vec4&);
+ void set(const vec4&);
+ void set(const vec4&);
+ void set(const vec4&);
+ void set(const vec4&);
+ void set(const vec4&);
+ void set(const vec4&);
+ void set(const vec4&);
+ };
+
+}
+
+#endif
diff --git a/src/graphics/vao.cpp b/src/graphics/vao.cpp
new file mode 100644
index 0000000..31407d5
--- /dev/null
+++ b/src/graphics/vao.cpp
@@ -0,0 +1,242 @@
+/**
+ This file is a part of our_dick
+ Copyright (C) 2020 rexy712
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+#include "graphics/vao.hpp"
+#include //exchange, swap
+
+namespace graphics{
+
+ void vertex_attribute::enable_array_mode(){
+ glBindVertexArray(m_vao);
+ glEnableVertexAttribArray(m_index);
+ }
+ void vertex_attribute::disable_array_mode(){
+ glBindVertexArray(m_vao);
+ glEnableVertexAttribArray(m_index);
+ }
+ void vertex_attribute::set_float_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * stride, (void*)(sizeof(GLfloat) * offset));
+ }
+ void vertex_attribute::set_double_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_DOUBLE, GL_FALSE, sizeof(GLdouble) * stride, (void*)(sizeof(GLdouble) * offset));
+ }
+ void vertex_attribute::set_byte_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_BYTE, GL_FALSE, sizeof(GLbyte) * stride, (void*)(sizeof(GLbyte) * offset));
+ }
+ void vertex_attribute::set_ubyte_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(GLubyte) * stride, (void*)(sizeof(GLubyte) * offset));
+ }
+ void vertex_attribute::set_short_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_SHORT, GL_FALSE, sizeof(GLshort) * stride, (void*)(sizeof(GLshort) * offset));
+ }
+ void vertex_attribute::set_ushort_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(GLushort) * stride, (void*)(sizeof(GLushort) * offset));
+ }
+ void vertex_attribute::set_int_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_INT, GL_FALSE, sizeof(GLint) * stride, (void*)(sizeof(GLint) * offset));
+ }
+ void vertex_attribute::set_uint_pointer(GLint size, GLsizei stride, GLsizei offset){
+ glBindVertexArray(m_vao);
+ glVertexAttribPointer(m_index, size, GL_UNSIGNED_INT, GL_FALSE, sizeof(GLuint) * stride, (void*)(sizeof(GLuint) * offset));
+ }
+ void vertex_attribute::set(GLfloat x){
+ glBindVertexArray(m_vao);
+ glVertexAttrib1f(m_index, x);
+ }
+ void vertex_attribute::set(GLshort x){
+ glBindVertexArray(m_vao);
+ glVertexAttrib1s(m_index, x);
+ }
+ void vertex_attribute::set(GLdouble x){
+ glBindVertexArray(m_vao);
+ glVertexAttrib1d(m_index, x);
+ }
+ void vertex_attribute::set(GLint x){
+ glBindVertexArray(m_vao);
+ glVertexAttribI1i(m_index, x);
+ }
+ void vertex_attribute::set(GLuint x){
+ glBindVertexArray(m_vao);
+ glVertexAttribI1ui(m_index, x);
+ }
+ void vertex_attribute::set(GLfloat x, GLfloat y){
+ glBindVertexArray(m_vao);
+ glVertexAttrib2f(m_index, x, y);
+ }
+ void vertex_attribute::set(GLshort x, GLshort y){
+ glBindVertexArray(m_vao);
+ glVertexAttrib2s(m_index, x, y);
+ }
+ void vertex_attribute::set(GLdouble x, GLdouble y){
+ glBindVertexArray(m_vao);
+ glVertexAttrib2d(m_index, x, y);
+ }
+ void vertex_attribute::set(GLint x, GLint y){
+ glBindVertexArray(m_vao);
+ glVertexAttribI2i(m_index, x, y);
+ }
+ void vertex_attribute::set(GLuint x, GLuint y){
+ glBindVertexArray(m_vao);
+ glVertexAttribI2ui(m_index, x, y);
+ }
+ void vertex_attribute::set(GLfloat x, GLfloat y, GLfloat z){
+ glBindVertexArray(m_vao);
+ glVertexAttrib3f(m_index, x, y, z);
+ }
+ void vertex_attribute::set(GLshort x, GLshort y, GLshort z){
+ glBindVertexArray(m_vao);
+ glVertexAttrib3s(m_index, x, y, z);
+ }
+ void vertex_attribute::set(GLdouble x, GLdouble y, GLdouble z){
+ glBindVertexArray(m_vao);
+ glVertexAttrib3d(m_index, x, y, z);
+ }
+ void vertex_attribute::set(GLint x, GLint y, GLint z){
+ glBindVertexArray(m_vao);
+ glVertexAttribI3i(m_index, x, y, z);
+ }
+ void vertex_attribute::set(GLuint x, GLuint y, GLuint z){
+ glBindVertexArray(m_vao);
+ glVertexAttribI3ui(m_index, x, y, z);
+ }
+ void vertex_attribute::set(GLfloat x, GLfloat y, GLfloat z, GLfloat w){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4f(m_index, x, y, z, w);
+ }
+ void vertex_attribute::set(GLshort x, GLshort y, GLshort z, GLshort w){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4s(m_index, x, y, z, w);
+ }
+ void vertex_attribute::set(GLdouble x, GLdouble y, GLdouble z, GLdouble w){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4d(m_index, x, y, z, w);
+ }
+ void vertex_attribute::set(GLint x, GLint y, GLint z, GLint w){
+ glBindVertexArray(m_vao);
+ glVertexAttribI4i(m_index, x, y, z, w);
+ }
+ void vertex_attribute::set(GLuint x, GLuint y, GLuint z, GLuint w){
+ glBindVertexArray(m_vao);
+ glVertexAttribI4ui(m_index, x, y, z, w);
+ }
+ void vertex_attribute::set(const vec2& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib2fv(m_index, v);
+ }
+ void vertex_attribute::set(const vec2& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib2sv(m_index, v);
+ }
+ void vertex_attribute::set(const vec2& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib2dv(m_index, v);
+ }
+ void vertex_attribute::set(const vec2& v){
+ glBindVertexArray(m_vao);
+ glVertexAttribI2iv(m_index, v);
+ }
+ void vertex_attribute::set(const vec2& v){
+ glBindVertexArray(m_vao);
+ glVertexAttribI2uiv(m_index, v);
+ }
+ void vertex_attribute::set(const vec3& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib3fv(m_index, v);
+ }
+ void vertex_attribute::set(const vec3& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib3sv(m_index, v);
+ }
+ void vertex_attribute::set(const vec3& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib3dv(m_index, v);
+ }
+ void vertex_attribute::set(const vec3& v){
+ glBindVertexArray(m_vao);
+ glVertexAttribI3iv(m_index, v);
+ }
+ void vertex_attribute::set(const vec3& v){
+ glBindVertexArray(m_vao);
+ glVertexAttribI3uiv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4fv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4sv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4dv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4iv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4uiv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4bv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4ubv(m_index, v);
+ }
+ void vertex_attribute::set(const vec4& v){
+ glBindVertexArray(m_vao);
+ glVertexAttrib4usv(m_index, v);
+ }
+
+
+ vao::vao(){
+ glGenVertexArrays(1, &m_buffer);
+ }
+ vao::vao(vao&& v):
+ m_buffer(std::exchange(v.m_buffer, 0)){}
+ vao::~vao(){
+ if(m_buffer)
+ glDeleteVertexArrays(1, &m_buffer);
+ }
+ vao& vao::operator=(vao&& v){
+ std::swap(m_buffer, v.m_buffer);
+ return *this;
+ }
+ vertex_attribute vao::get_attribute(int index){
+ return vertex_attribute(m_buffer, index);
+ }
+ void vao::bind(){
+ glBindVertexArray(m_buffer);
+ }
+ void vao::unbind(){
+ glBindVertexArray(0);
+ }
+
+
+}