# [`glconventions`][]

An [OpenGL][] conventions document.

In order to promote modularity, interoperability and consistency, this document
tries to lay forward a set of conventions, mostly surrounding naming. This is
important when moving from a monolithic copy-and-paste regime, especially for
shaders, to one based on re-usable libraries. Historical (often deprecated)
OpenGL, other graphics APIs, uniformity and brevity are the main points of
reference and driving forces.

[`glconventions`]: https://git.rcrnstn.net/rcrnstn/glconventions
[OpenGL]: https://en.wikipedia.org/wiki/OpenGL

## Spaces and matrices

```
mat4 world;
mat4 view;
mat4 projection;
```

Note that `world` is what is sometimes known as `model`. OpenGL historically
had a combined `modelview` matrix which transformed *from* model space all the
way (through world space) *to* view space. Since having to name each matrix
with both the "from" space *and* "to" space results in overly long names, the
convention chosen here is to only use the "to" space name. This is consistent
with Direct3D. When we combine space names in a matrix name we use several "to"
space names, e.g. `view_world` or `projection_view_world`. Note the order! It
is the same as order of multiplication: `projection_view = projection * view`.
The "from" space is implicitly the space before the (last) named "to" space;
model->world->view->projection.

To enable instancing, `world` is (always) specified as a vertex attribute.
`view` and `projection` are uniforms (optionally a uniform block).

[`glVertexAttrib`]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttrib.xhtml

## Shaders

### Variable naming

-   [Uniforms][]
    -   `*`
-   Vertex shader [inputs][] (attributes)
    -   `vert_*` (both per-vertex and per-instance data)
        uniforms
-   Geometry shader [inputs][]
    -   `geom_*`
-   Fragment shader [inputs][] (vertex or geometry shader [outputs][])
    -   `*`
-   Fragment shader [outputs][] (data)
    -   `frag_*`

Note that the prefixes correspond to the file extensions used by the [GLSL
reference compiler][].

Every name that is general enough that a collision might occur, even in
principle, must be suffixed with an `0`-based index (without any separating
`_`). Examples include `in vec4 color0`, `uniform sampler2D texture0`, `out
vec4 frag_data0`.

[uniforms]: #uniforms
[inputs]: #inputs
[outputs]: #outputs
[GLSL reference compiler]: https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/

### Uniforms

#### Geometric

```glsl
uniform mat4 view;
uniform mat4 projection;
```

If the GLSL code is distributed with corresponding CPU code to set its
uniforms, the following is also acceptable, since the names and their scope is
the same:

```glsl
uniform camera
{
    mat4 view;
    mat projection;
}
```

Note that this is a [uniform block][] and requires [uniform buffer][] support,
i.e. OpenGL [\>=3.1][] or the [`ARB_uniform_buffer_object`][] extension.
Further more, it requires some more work on the CPU. The advantage is that the
uniforms do not have to be set for every used shader program and can be set
"globally" e.g. once per frame.

[uniform block]: https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)
[uniform buffer]: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object
[\>=3.1]: https://en.wikipedia.org/wiki/OpenGL#Version_history
[`ARB_uniform_buffer_object`]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt

### Inputs

#### Geometric

```glsl
in mat4 {prefix_}world;
in vec3 {prefix_}position;
in vec3 {prefix_}normal;
in vec2 {prefix_}tex_coord;
```

In order of likelihood to be needed.

#### Common

```glsl
in vec4 {prefix_}color0;
```

### Outputs

As a general rule, all inputs should be forwarded to outputs because, in a
modular world, it may not be known what input the next shader stage requires.

All geometric quantities should be outputted in the [standard space][] of the
next shader stage *and* in any spaces between the standard space of the current
shader stage (exclusive) and the next. Specifically, this means the vertex
shader should output e.g. both `vec3 normal` and `vec3 world_normal`.

Unused outputs will be optimized out in the link stage.

The overwhelmingly most common fragment shader output is `vec4
frag_color`, and it is acceptable if data that might not quite be color
is written to this output, provided that it is the only output and that
the data can be held in `GL_RGBA8` (i.e. only 8 bits per channel).

[standard space]: #standard-spaces

### Standard spaces

Each shader stage has a standard space in which input geometric quantities are
expressed:

-   vertex: `model`
-   geometry: `view`
-   fragment: `view`

Quantities that is not expressed in the standard space has the space prefixed,
e.g. `world_normal`.

## License

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

[CC BY 4.0 License]: https://choosealicense.com/licenses/cc-by-4.0/
