158 lines
4.2 KiB
C++

/**
This file is a part of our_dick
Copyright (C) 2022 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 <http://www.gnu.org/licenses/>.
*/
#ifndef OUR_DICK_GRAPHICS_OGL_UBO_HPP
#define OUR_DICK_GRAPHICS_OGL_UBO_HPP
#include "gl_include.hpp"
#include <rml/mat.hpp>
#include <rml/vec.hpp>
#include <type_traits> //a lot of stuff
#include "buffer_map.hpp"
namespace gfx::ogl{
namespace detail{
template<class T>
struct is_bounded_array{
static constexpr bool value = false;
};
template<class T, size_t I>
struct is_bounded_array<T[I]>{
static constexpr bool value = true;
};
template<class T>
struct is_valid_uniform_scalar{
static constexpr bool value = std::is_same_v<T,GLint> ||
std::is_same_v<T,GLuint> ||
std::is_same_v<T,bool> ||
std::is_same_v<T,GLfloat> ||
std::is_same_v<T,GLdouble>;
};
template<class T>
struct is_valid_uniform_matrix{
template<class U, size_t R, size_t C>
static constexpr bool test(rml::matrix_base<U,R,C>*){
return is_valid_uniform_scalar<typename T::value_type>::value && T::Columns <= 4 && T::Rows <= 4;
}
static constexpr bool test(void*){
return false;
}
static constexpr bool value = test(static_cast<std::decay_t<T>*>(nullptr));
};
template<class T>
struct is_valid_uniform_type{
static constexpr bool value = is_valid_uniform_scalar<T>::value || is_valid_uniform_matrix<T>::value || is_bounded_array<T>::value;
};
template<size_t I, class Type, class... Types>
struct get_type{
using type = typename get_type<I-1, Types...>::type;
};
template<class Type, class... Types>
struct get_type<0, Type, Types...>{
using type = Type;
};
template<class... Types>
struct get_type<0,bool,Types...>{
using type = int;
};
template<size_t I, class... Types>
using get_type_t = typename get_type<I, Types...>::type;
template<class T>
constexpr size_t get_alignment_of_(void);
template<class T>
constexpr size_t get_alignment_multiple_(void);
template<class T>
constexpr size_t size_of_(void);
}
//Class for a uniform buffer object
//automatically sets alignments for std140 uniform blocks
template<class... Types>
class ubo
{
private:
static_assert((detail::is_valid_uniform_type<Types>::value && ...));
public:
static constexpr size_t num_elements = sizeof...(Types);
template<size_t I>
using type_of = detail::get_type_t<I, Types...>;
private:
GLuint m_buffer = 0;
public:
ubo(buffer::usage usage = buffer::usage::DYNAMIC_DRAW);
ubo(const ubo&);
ubo(ubo&&);
~ubo(void);
ubo& operator=(const ubo&);
ubo& operator=(ubo&&);
//raw modify the data (NOT A GOOD IDEA)
scoped_buffer_map<void> map(buffer::maptype m);
void buffer(const void* data, size_t datasize, size_t start);
void initialize(unsigned char value = 0);
//Safely modify the data to comply with GLSL std140 layout
template<size_t I>
auto get(void);
template<size_t I, class T>
void set(T&& t);
//Direct access to opengl handle
GLuint raw(void)const;
size_t get_size(void)const;
size_t get_cap(void)const;
buffer::usage get_usage(void)const;
//Bind to uniform block binding location
void bind(size_t index)const;
private:
template<size_t I>
static constexpr size_t get_offset_of_(void);
template<size_t I>
static constexpr size_t get_alignment_of_(void);
static constexpr size_t get_total_size_(void);
public:
template<size_t I>
static constexpr size_t offset_of = get_offset_of_<I>();
template<size_t I>
static constexpr size_t alignment_of = get_alignment_of_<I>();
};
}
#include "ubo.tpp"
#endif