/// Guards #ifndef GLTRAITS_HPP_ #define GLTRAITS_HPP_ /// Includes #include <cstddef> #include <glbase.hpp> /// GLTraits class GLTraits { public: //// Value template<typename> struct Value; template<GLenum id> struct ValueID; }; //// Helpers #define GLTRAITS_KEEP(...) __VA_ARGS__ #define GLTRAITS_OMIT(...) //// Value #define GLTRAITS_VALUE_SRED GL_SR8_EXT #define GLTRAITS_VALUE_SRG GL_SRG8_EXT #define GLTRAITS_VALUE_SRGB GL_SRGB8 #define GLTRAITS_VALUE_SRGBA GL_SRGB8_ALPHA8 #define GLTRAITS_VALUE_COMPRESSED_SRED GL_COMPRESSED_SRGB #define GLTRAITS_VALUE_COMPRESSED_SRG GL_COMPRESSED_SRGB #define GLTRAITS_VALUE_COMPRESSED_SRGB GL_COMPRESSED_SRGB #define GLTRAITS_VALUE_COMPRESSED_SRGBA GL_COMPRESSED_SRGB_ALPHA #define GLTRAITS_VALUE( \ VALUE, \ COLUMNS, ROWS, \ GLSL, FORMAT, TYPE, INTERNAL_FORMAT, \ OFFSET_ARGS, PTR, \ V, UNIFORM, SUFFIX, ATTRIB, \ INTEGER, \ NORMALIZE_ARGS, \ V1U, V2U, \ V1A, V2A, \ EXTU, EXTA, \ ... \ ) \ template<> \ struct GLTraits::Value<VALUE> \ { \ auto static constexpr name = #VALUE; \ auto static constexpr columns = GLint{COLUMNS}; \ auto static constexpr rows = GLint{ROWS}; \ auto static constexpr glsl = GLenum{GL_##GLSL}; \ auto static constexpr format = GLenum{GL_##FORMAT##INTEGER}; \ auto static constexpr type = GLenum{GL_##TYPE}; \ auto static constexpr internal_format = GLenum{GL_##INTERNAL_FORMAT}; \ auto static constexpr internal_format_srgb = GLenum{GLTRAITS_VALUE_S##FORMAT}; \ auto static constexpr internal_format_compressed = GLenum{GL_COMPRESSED_##FORMAT}; \ auto static constexpr internal_format_compressed_srgb = GLenum{GLTRAITS_VALUE_COMPRESSED_S##FORMAT}; \ auto static constexpr integer = bool(*#INTEGER); \ auto static constexpr id = \ (glsl == GL_INT || glsl == GL_UNSIGNED_INT) && \ sizeof(VALUE) < sizeof(GLint) \ ? type \ : glsl; \ void static uniform(GLint location, VALUE const & value) \ { \ if (GLBase::debug() >= 1) \ GLBase::check_supported({V1U, V2U}, EXTU); \ glUniform##UNIFORM##ROWS##SUFFIX##V( \ location, \ __VA_ARGS__ \ PTR(value) \ ); \ } \ void static vertex_attrib(GLint location, VALUE const & value) \ { \ if (GLBase::debug() >= 1) \ GLBase::check_supported({V1A, V2A}, EXTA); \ if (location == -1) \ return; \ for (auto column = GLuint{0}; column < columns; ++column) \ glVertexAttrib##ATTRIB##ROWS##SUFFIX##V( \ (GLuint)location + column, \ PTR(value) GLTRAITS_##OFFSET_ARGS(+ rows * column) \ ); \ } \ void static vertex_attrib_pointer( \ GLint location, \ std::size_t offset = 0, \ std::size_t stride = sizeof(VALUE) \ ) \ { \ if (GLBase::debug() >= 1) \ GLBase::check_supported({V1A, V2A}, EXTA); \ if (location == -1) \ return; \ auto constexpr sizeof_column = sizeof(VALUE) / columns; \ for (auto column = GLuint{0}; column < columns; ++column) \ glVertexAttrib##ATTRIB##Pointer( \ (GLuint)location + column, \ rows, \ type, \ GLTRAITS_##NORMALIZE_ARGS(GL_FALSE,) \ (GLsizei)stride, \ (void const *)(offset + sizeof_column * column) \ ); \ } \ }; \ template<> \ struct GLTraits::ValueID<GLTraits::Value<VALUE>::id> \ { \ using Value = VALUE; \ }; #define GLTRAITS_VALUE_SCALAR( VALUE, TYPE, GLSL, INTERNAL, ...) GLTRAITS_VALUE(VALUE, 1, 1, GLSL, RED, TYPE, R ##INTERNAL, OMIT, , , , __VA_ARGS__,) #define GLTRAITS_VALUE_VECTOR_N( N, FORMAT, VALUE, TYPE, PTR, INTERNAL, ...) GLTRAITS_VALUE(VALUE##N, 1, N, TYPE##_VEC##N, FORMAT, TYPE, FORMAT##INTERNAL, KEEP, PTR, v, , __VA_ARGS__, 1,) #define GLTRAITS_VALUE_MATRIX_N( N, FORMAT, VALUE, TYPE, PTR, T, INTERNAL, ...) GLTRAITS_VALUE(VALUE##N, N, N, TYPE##_MAT##N, FORMAT, TYPE, FORMAT##INTERNAL, KEEP, PTR, v, Matrix, __VA_ARGS__, 1, T,) #define GLTRAITS_VALUE_MATRIX_N_M(N, M, FORMAT, VALUE, TYPE, PTR, T, INTERNAL, ...) GLTRAITS_VALUE(VALUE##N##x##M, N, M, TYPE##_MAT##N##x##M, FORMAT, TYPE, FORMAT##INTERNAL, KEEP, PTR, v, Matrix##N##x, __VA_ARGS__, 1, T,) #define GLTRAITS_VALUE_VECTOR(...) \ GLTRAITS_VALUE_VECTOR_N( 2, RG, __VA_ARGS__) \ GLTRAITS_VALUE_VECTOR_N( 3, RGB, __VA_ARGS__) \ GLTRAITS_VALUE_VECTOR_N( 4, RGBA, __VA_ARGS__) #define GLTRAITS_VALUE_MATRIX_(SUPPORT_ARGS, ...) \ GLTRAITS_VALUE_MATRIX_N( 2, RG, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 0, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N_M(2, 3, RGB, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N_M(2, 4, RGBA, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N_M(3, 2, RG, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N( 3, RGB, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 0, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N_M(3, 4, RGBA, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N_M(4, 2, RG, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N_M(4, 3, RGB, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ GLTRAITS_VALUE_MATRIX_N( 4, RGBA, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 0, 2, 0, {}, {})) #define GLTRAITS_VALUE_MATRIXS(...) GLTRAITS_VALUE_MATRIX_(KEEP, __VA_ARGS__) #define GLTRAITS_VALUE_MATRIX(...) GLTRAITS_VALUE_MATRIX_(OMIT, __VA_ARGS__) GLTRAITS_VALUE_SCALAR( GLfloat, FLOAT, FLOAT, 32F, f, , , KEEP, 2, 0, 2, 0, {}, {}) GLTRAITS_VALUE_SCALAR( bool, BYTE, BOOL, 8I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLbyte, BYTE, INT, 8I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLshort, SHORT, INT, 16I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLint, INT, INT, 32I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLubyte, UNSIGNED_BYTE, UNSIGNED_INT, 8UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLushort, UNSIGNED_SHORT, UNSIGNED_INT, 16UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLuint, UNSIGNED_INT, UNSIGNED_INT, 32UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) GLTRAITS_VALUE_SCALAR( GLdouble, DOUBLE, DOUBLE, ED, d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") #ifdef GLM_VERSION #include <glm/gtc/type_ptr.hpp> GLTRAITS_VALUE_VECTOR( glm::vec, FLOAT, glm::value_ptr, 32F, f, , , KEEP, 2, 0, 2, 0, {}, {}) GLTRAITS_VALUE_MATRIXS(glm::mat, FLOAT, glm::value_ptr, GL_FALSE, 32F, f, , , KEEP) GLTRAITS_VALUE_VECTOR( glm::ivec, INT, glm::value_ptr, 32I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) GLTRAITS_VALUE_VECTOR( glm::uvec, UNSIGNED_INT, glm::value_ptr, 32UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) GLTRAITS_VALUE_VECTOR( glm::dvec, DOUBLE, glm::value_ptr, , d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") GLTRAITS_VALUE_MATRIX( glm::dmat, DOUBLE, glm::value_ptr, GL_FALSE, , d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") #endif /// Guards #endif