# SDF-2D - v0.7.6

# Documentation

The motivation behind this library and more in-depth information about the rendering techniques utilised can be found in my thesis.

## Links

- Repository
- Demo
- Minimal example
- More complex example
- Source code of the demo

## Usage (1st option)

- To start using cutting-edge 2D graphics, first you have get a renderer instance. This is possible by calling the compile function.
  - For this, some DrawableDescriptors has to be provided.
  - Optionally, default compile settings can overridden using StartupSettings.
- After acquiring a renderer, the drawing of objects can be started through the Renderer interface.

## Usage (2nd option)

If you're planning on creating animated content, use the runAnimation function to spare yourself from writing boilerplate code. Further documentation on its usage is available in its documentation.

## Extending drawables

> Iñigo Quilez has some great 2D SDF-s

- Subclass Drawable
- Implement its abstract methods
- Add a static property to your class called `descriptor` of type DrawableDescriptors
- Follow the instructions given in Usage

## Useful to know

### Math

The `vec2`, `vec3`, and `vec4` types seen in the documentation come from the glMatrix library and are equivalent to regular JS Arrays or Float32Arrays. So, feel free to give `[x, y]` as an input for functions requiring `vec2`.

### Coordinates

Anywhere, where positions need to be specified, the `y` values grow upwards. That means, when setting the view area, the origin is at the bottom left corner of the display.

### Tile-based rendering

For optimising the evaluation of the distance field, the display is divided up into a grid of tiles. The shaders for each tile are compiled to support a fix maximum number of objects on it. When using the built-in drawables it is possible that after a certain number of on-screen objects new ones won't be visible.

Mitigating this issue is quite easy. Instead of the following code:

    this.renderer = await compile(canvas, [Circle.descriptor, CircleLight.descriptor]);

Modify it to something similar:

    this.renderer = await compile(canvas, [
      {
        ...Circle.descriptor,
        shaderCombinationSteps: [0, 1, 2, 24, 64],
      },
      {
        ...CircleLight.descriptor,
        shaderCombinationSteps: [0, 1, 2, 4],
      },
    ]);

The usage of too large numbers is not advised for compatibility and performance reasons alike.

> Steps are very useful for tile-based rendering, because it is possible for one tile (at a given moment) to be empty or contain just a few objects, while others have a large cluster of objects. The compiled shaders only take into account the necessary number of objects on each tile.