# [`gltraits`][]
A [C++11][]/[OpenGL][]>=[1.0][](/[GLM][]) [trait][]s library.
This library seeks to unify some parts of the OpenGL [API][] to ease [generic
programming][]. It also provides sensible default arguments, [optional][debug]
[check][]s for [version][]/[extension][] support, and optional support for
[OpenGL Mathematics (GLM)][GLM] (which provides [GLSL][]-like types).
A more philosophical description: it aims to make the implicit symmetries of
the OpenGL API explicit. In the process, some wrinkles in the symmetry are also
brought to light. Therefore, it may be useful for learning and understanding
the OpenGL API (although this use case may be limited due to the (ab)use of C++
language features).
This header-only library makes heavy use of macros. For easy inspection of the
results, a script that runs the preprocessor is available in
[`doc/preprocess`][] and its output in [`doc/preprocess.hpp`][].
A typical use case is demonstrated by this quote from [OGLDEV on YouTube][]:
> Notice, in order to make this an unsigned integer texture we use `GL_RGB32UI`
> as the `internal_format`, `GL_RGB_INTEGER` as the `format`, and
> `GL_UNSIGNED_INT` as the data `type`. Combining all these formats and types
> correctly in OpenGL can often be a pain, and I literally pulled the last few
> pieces of hair from my head trying to get this to work.
These constants are provided in `GLTraits::Value<glm::uvec3>`. Of course, this
becomes even more valuable when `glm::uvec3` is replaced by some unknown
template parameter.
[`gltraits`]: https://git.rcrnstn.net/rcrnstn/gltraits
[C++11]: https://en.wikipedia.org/wiki/C++11
[OpenGL]: https://en.wikipedia.org/wiki/OpenGL
[1.0]: https://en.wikipedia.org/wiki/OpenGL#Version_history
[GLM]: https://glm.g-truc.net
[trait]: https://en.wikipedia.org/wiki/Trait_(computer_programming)
[API]: https://en.wikipedia.org/wiki/API
[generic programming]: https://en.wikipedia.org/wiki/Generic_programming
[debug]: https://git.rcrnstn.net/rcrnstn/glbase#debug
[check]: https://git.rcrnstn.net/rcrnstn/glbase#check
[version]: https://en.wikipedia.org/wiki/OpenGL#Version_history
[extension]: https://www.khronos.org/opengl/wiki/OpenGL_Extension
[GLSL]: https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language
[`doc/preprocess`]: doc/preprocess
[`doc/preprocess.hpp`]: doc/preprocess.hpp
[OGLDEV on YouTube]: https://www.youtube.com/watch?v=71G-PVpaVk8&t=5m17s
## Usage
### Value
The [empty][] `struct GLTraits::Value<typename Value>` is template specialized
on the following types.
-   `GLfloat`
-   `bool`
-   `GL{,u}byte`
-   `GL{,u}short`
-   `GL{,u}int`
-   `GLdouble`
[GLM][] support is enabled if `glm/glm.hpp` is included (specifically, if
`GLM_VERSION` is defined) before inclusion of `gltraits.hpp`. In that case
`GLTraits::Value` is additionally template specialized on the following types.
-   `glm::{,i,u,d}vec{2,3,4}`
-   `glm::{,d}mat{2{,x3,x4},3{x2,,x4},4{x2,x3,}}`
`GLTraits::Value` contains the following `static constexpr` member variables.
-   `char   const name[]`
-   `GLint        columns`
-   `GLint        rows`
-   `GLenum       glsl`
-   `GLenum       format`
-   `GLenum       type`
-   `GLenum       internal_format`
-   `GLenum       internal_format_srgb`
-   `GLenum       internal_format_compressed`
-   `GLenum       internal_format_compressed_srgb`
-   `bool         integer`
-   `GLenum       id`
`id` is guaranteed to be unique to this `Value` and is equal to `glsl` for all
`Value`s except `GL{,u}{byte,short}`, for which it is equal to `type`.
`GLTraits::Value` contains the following `static` member functions.
-   ```cpp
    void uniform(GLint location, Value const & value)
    ```
    Generalization of `glUniform*`.
    Uploads `value` to the [uniform][] indicated by `location` of the current
    [shader][] program.
-   ```cpp
    void vertex_attrib(GLint location, Value const & value)
    ```
    Generalization of `glVertexAttrib*`.
    Uploads `value` to the [non-array attribute][] indicated by `location`.
    Note that [`glDisableVertexAttribArray`][] is not called (for performance).
-   ```cpp
    void vertex_attrib_pointer(
        GLint       location,
        std::size_t offset = 0,
        std::size_t stride = sizeof(Value)
    )
    ```
    Generalization of `glVertexAttrib*Pointer`.
    Sets the [format][] as well as the [offset and stride][] of the [array
    attribute][] indicated by `location`. Note that
    [`glEnableVertexAttribArray`][] is not called (for performance).
If `location` is `-1`, the above calls will do nothing. No error will be
generated in this case.
Note that matrix types (e.g. from [GLM][], if enabled), occupy several
consecutive attribute locations (one per column), which are all handled
automatically by `vertex_attrib{,_pointer}(...)` above.
`GLTRAITS_VALUE*` macros are defined to ease the definition of new template
specializations of `GLTraits::Value`. Consult the source for the definitions
and usage examples.
The [empty][] `struct GLTraits::ValueID<GLenum id>` is template specialized on
the different values of `GLTraits::Value<Value>::id`.
`GLTraits::ValueID` contains the following type definitions.
-   `Value`. An alias for the template type parameter for which
    `GLTraits::Value<Value>::id == id` holds.
`GLTraits::ValueID` provides a compile time mapping from `GLenum id` back to
the type `Value`. E.g. `GLTraits::ValueID<GL_FLOAT>::Value` is an alias for
`GLfloat`. This works for all supported types, including those provided by
[GLM][] if enabled, e.g. `GLTraits::ValueID<GL_FLOAT_VEC3>::Value` would be an
alias for `glm::vec3`.
[empty]: https://en.cppreference.com/w/cpp/types/is_empty
[uniform]: https://www.khronos.org/opengl/wiki/Uniform_(GLSL)
[shader]: https://www.khronos.org/opengl/wiki/Shader
[non-array attribute]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Non-array_attribute_values
[format]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_format
[offset and stride]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_buffer_offset_and_stride
[array attribute]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Buffer_Object
[`glDisableVertexAttribArray`]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glEnableVertexAttribArray.xhtml
[`glEnableVertexAttribArray`]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glEnableVertexAttribArray.xhtml
## Building
See [`BUILDING.md`][].
[`BUILDING.md`]: BUILDING.md
## License
Licensed under the [ISC License][] unless otherwise noted, see the
[`LICENSE`][] file.
[ISC License]: https://choosealicense.com/licenses/isc
[`LICENSE`]: LICENSE