# [`glquad`][]

A [GLSL][]/[OpenGL][] [\>=3.2][] [quad][] library.

The main functionality is [generation][] of (2D or 3D) quads with the provided
[vertex shader][] and [geometry shader][], expected to be used with a custom
[fragment shader][].

Mostly as a convenience, [fragment shader][]s are provided for [drawing][] (2D
or 3D) textures.

Other libraries, interoperating well with this one, that may be of interest:

-   [`glshader`][], easing the use of [shader][]s.
-   [`glframebuffer`][], easing the use of [framebuffer object][]s.
-   [`glconventions`][], documenting the conventions used.

[`glquad`]: https://git.rcrnstn.net/rcrnstn/glquad
[GLSL]: https://en.wikipedia.org/wiki/OpenGL_Shading_Language
[OpenGL]: https://en.wikipedia.org/wiki/OpenGL
[\>=3.2]: https://en.wikipedia.org/wiki/OpenGL#Version_history
[quad]: https://en.wikipedia.org/wiki/Quadrilateral
[generation]: #generation
[vertex shader]: https://www.khronos.org/opengl/wiki/Vertex_Shader
[geometry shader]: https://www.khronos.org/opengl/wiki/Geometry_Shader
[fragment shader]: https://www.khronos.org/opengl/wiki/Fragment_Shader
[drawing]: #drawing
[`glshader`]: https://git.rcrnstn.net/rcrnstn/glshader
[shader]: https://www.khronos.org/opengl/wiki/Shader
[`glframebuffer`]: https://git.rcrnstn.net/rcrnstn/glframebuffer
[framebuffer object]: https://www.khronos.org/opengl/wiki/Framebuffer_Object
[`glconventions`]: https://git.rcrnstn.net/rcrnstn/glconventions

## Requirements

[Geometry shader][]s require OpenGL [\>=3.2][] or the
[`ARB_geometry_shader4`][] extension.

[`ARB_geometry_shader4`]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_geometry_shader4.txt

## Usage

Link the shader program with:

-   `quad.vert`
-   `quad.geom`

The following uniforms need to be set:

-   `int instance_count`

The following outputs are written by the [geometry shader][]:

-   `vec3 position`, in the range `-1` to `+1`
-   `vec2 tex_coord`, in the range `0` to `1`

When issuing the draw call, use the following for 2D:

```
glDrawArrays(GL_POINTS, 0, 1);
```

and the following for 3D:

```
glDrawArraysInstanced(GL_POINTS, 0, 1 instance_count);
```

Here, `instance_count` is the number of [layer][]s in the [framebuffer][]; `1`
for 2D, texture depth for 3D.

[layer]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Layered_rendering
[framebuffer]: https://www.khronos.org/opengl/wiki/Framebuffer

### Generation

Vertices are generated entirely within a [geometry shader][], so no vertex
state (except for the obligatory [vertex array object][] for OpenGL [\>=3.3][])
has to be set up on the CPU (no data is even read by the [vertex shader][]),
potentially making operation transparent to other code, which can leave their
state bound.

[Instanced rendering][], with each instance rendering to a separate [layer][],
is used since it enables a large, dynamic, number of layers. [Geometry shader
instancing][] is more self-contained and requires less work by the CPU (simply
`glDrawArrays`), but is limited to a fixed, small, number of layers, and
requires OpenGL [\>=4.0][] or the [`ARB_gpu_shader5`][] extension.

[vertex array object]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object
[\>=3.3]: https://en.wikipedia.org/wiki/OpenGL#Version_history
[instanced rendering]: https://www.khronos.org/opengl/wiki/Vertex_Rendering#Instancing
[geometry shader instancing]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Instancing
[\>=4.0]: https://en.wikipedia.org/wiki/OpenGL#Version_history
[`ARB_gpu_shader5`]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_gpu_shader5.txt

### Drawing

The following outputs are written by these fragment shaders:

-   ` vec4 frag_color`

#### 2D

Link the shader program with:

-   `quad2d.frag`

The following uniforms need to be set:

-   `sampler2D texture0`

#### 3D

Link the shader program with:

-   `quad3d.frag`

The following uniforms need to be set:

-   `sampler3D texture0`
-   `float tex_coord_z`, `z` coordinate with which to sample `texture0`

## Build system

This project has support for [CMake][], and uses [`cmake-cxx`][].

There are several ways to use this project in another CMake-based project:

-   Use [`FetchContent`][] to download it and import the targets automatically
    as part of the configure step:

    ```cmake
    include(FetchContent)
    FetchContent_Declare(project-name
        GIT_REPOSITORY https://example.com/user/project-name
    )
    FetchContent_MakeAvailable(
        project-name
    )
    ```

-   Bundle it and import the targets with [`add_subdirectory`][].

-   Use [`find_package`][] (requires that the project is [packaged](#packaging)
    or [installed](#installing)).

As usual, use [`add_dependencies`][]/[`target_link_libraries`][] to declare the
dependency.

[CMake]: https://cmake.org
[`cmake-cxx`]: https://git.rcrnstn.net/rcrnstn/cmake-cxx
[`FetchContent`]: https://cmake.org/cmake/help/v3.14/module/FetchContent.html
[`add_subdirectory`]: https://cmake.org/cmake/help/v3.14/command/add_subdirectory.html
[`find_package`]: https://cmake.org/cmake/help/v3.14/command/find_package.html
[`add_dependencies`]: https://cmake.org/cmake/help/v3.14/command/add_dependencies.html
[`target_link_libraries`]: https://cmake.org/cmake/help/v3.14/command/target_link_libraries.html

### Configure and generate

To configure and generate a build tree, use `cmake`:

```sh
cmake -B build
```

To set the [`CMAKE_BUILD_TYPE`][], pass e.g. `-DCMAKE_BUILD_TYPE=Release`.

[`cmake`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#generate-a-project-buildsystem
[`CMAKE_BUILD_TYPE`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_BUILD_TYPE.html

### Build

To build, use [`cmake --build`][]:

```sh
cmake --build build
```

[`cmake --build`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#build-a-project

### Test

To run tests, use [`ctest`][]:

```sh
(cd build && ctest --output-on-failure)
```

[`ctest`]: https://cmake.org/cmake/help/v3.14/manual/ctest.1.html

### Package

To package, use [`cpack`][]:

```sh
(cd build && cpack)
```

[`cpack`]: https://cmake.org/cmake/help/v3.14/manual/cpack.1.html

### Install

To install onto the current system, use [`cmake --install`][]:

```sh
cmake --install build
```

[`cmake --install`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#install-a-project

## License

Licensed under the [ISC License][] unless otherwise noted, see the
[`LICENSE`](LICENSE) file.

[ISC License]: https://choosealicense.com/licenses/isc/
