# [`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`

`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.

[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
