# LambdaCube 3D API 0.5

We gradually improve the documentation. If you have any question or something is confusing and needs to be clarified please ask us via email or irc on `#haskell-game`

(irc.freenode.net).

# Reduction phases

Reduction is done in three different phases:

- Compile time CPU
- Runtime CPU
- Runtime GPU

The runtime CPU and runtime GPU phases are interleaved.

Design principles:

- Every reduction step is done in the runtime CPU phase by default.
- As an optimization, some reductions are done at runtime GPU instead of runtime CPU. Of course, this optimization step is crucial: without this optimization LambdaCube 3D is useless.

GPU operations are very slow on CPU, but the CPU implementation of GPU primitives ensures that there is no cheating in the types of GPU primitives. - As an optimization, some reductions are done at compile time CPU instead of runtime CPU.
- The programmer can assert that a computation is done in a specific phase via the type system.

In this way, one can refactor LambdaCube 3D source code without fear of performance regressions.

Principle 1. is not yet implemented: some reductions are only possible to do at the runtime GPU phase.

Principle 4. is not implemented yet: phase information is provided in the comments, not in the types. The compiler code generator automagically determines the phases of expressions.

# Basic types

## Basic values

type | description | example values |
---|---|---|

`Bool` |
Boolean values | `True` , `False` |

`Int` |
signed integers | …, `-2` , `-1` , `0` , `1` , `2` , … |

`Word` |
unsigned integers | `0` , `1` , `2` , … |

`Nat` |
natural numbers | `0` , `1` , `2` , … |

or `Zero` , `Succ Zero` , `Succ (Succ Zero)` , … |
||

`Float` |
floating point numbers | `0` , `3.14` , … |

`Vec n t` |
vectors | `V3 0.1 0 0` , `V2 True False` |

`Mat i j t` |
matrices | `M23F (V2 0 0.1) (V2 1 1) (V3 0 0) :: Mat 2 3 Float` |

The difference between `Word`

and `Nat`

is that they have different representations. `Word`

values are atomic, whilst `Nat`

values have more structure: for example the pattern `Succ a`

matches all non-zero naturals. Usually `Nat`

is used in types, for example, the dimension of a `Vec`

is a `Nat`

instead of an `Int`

.

The vector constructors are `V2`

, `V3`

and `V4`

. It is only possible to construct vectors with 2, 3 or 4 dimensions.

For example,

` V3 0 1.1 2 :: Vec 3 Float`

The matrix constructors are `M22F`

, `M23F`

, `M24F`

, `M32F`

, `M33F`

, `M34F`

, `M42F`

, `M43F`

and `M44F`

. The matrix constructors needs the columns of the matrices.

For example,

` M23F (V2 0 0.1) (V2 1 1) (V3 0 0) :: Mat 2 3 Float`

It is only possible to construct matrices with dimensions i x j where i and j are 2, 3 or 4.

It is only possible to construct martices of float elements.

## Basic type families (type functions)

```
VecScalar :: Nat -> Type -> Type
MatVecScalarElem :: Type -> Type
```

If the first argument of `VecScalar`

is `1`

, then the result is the second argument, otherwise `VecScalar`

is the same as `Vec`

.

Examples:

```
VecScalar 1 Float = Float
VecScalar 2 Float = Vec 2 Float
```

`MatVecScalarElem`

gives back the type of elements of matrices and vectors; in case of scalars it is the identity function.

Examples:

```
MatVecScalarElem Float = Float
MatVecScalarElem (Vec 3 Bool) = Bool
MatVecScalarElem (Mat 3 3 Float) = Float
```

## Basic type classes

type class | instances | description |
---|---|---|

`Integral` |
`Int` , `Word` |
integral numbers |

`Signed` |
`Float` , `Int` |
signed numbers |

`Num` |
`Float` , `Int` , `Word` |
numbers |

`Floating` |
`Float` , `Float` vectors, `Float` matrices |
floating point numbers and containers |

`Component` |
`Bool` , `Int` , `Word` , `Float` and its vectors |
provides `zero` and `one` (see below) |

## Primitive operations

*Phase information*

Runtime CPU: None of the primitive oparations are accessible.

Runtime GPU: All of the primitive oparations are accessible.

Compile time CPU: Some of the primitive oparations are accessible.

### Values

`zero` |
`:: Component a => a` |
Generic zero value, for example `zero = V3 0.0 0.0 0.0 :: Vec 3 Float` |

`one` |
`:: Component a => a` |
Generic one value, for example `one = V3 1.0 1.0 1.0 :: Vec 3 Float` |

```
rgb :: Float -> Float -> Float -> Vec 4 Float
rgb r g b = V4 r g b 1.0
```

`black` |
`:: Vec 4 Float` |
same as `rgb 0.0 0.0 0.0` |

`gray` |
`:: Vec 4 Float` |
same as `rgb 0.5 0.5 0.5` |

`silver` |
`:: Vec 4 Float` |
same as `rgb 0.75 0.75 0.75` |

`white` |
`:: Vec 4 Float` |
same as `rgb 1.0 1.0 1.0` |

`maroon` |
`:: Vec 4 Float` |
same as `rgb 0.5 0.0 0.0` |

`red` |
`:: Vec 4 Float` |
same as `rgb 1.0 0.0 0.0` |

`olive` |
`:: Vec 4 Float` |
same as `rgb 0.5 0.5 0.0` |

`yellow` |
`:: Vec 4 Float` |
same as `rgb 1.0 1.0 0.0` |

`green` |
`:: Vec 4 Float` |
same as `rgb 0.0 0.5 0.0` |

`lime` |
`:: Vec 4 Float` |
same as `rgb 0.0 1.0 0.0` |

`teal` |
`:: Vec 4 Float` |
same as `rgb 0.0 0.5 0.5` |

`aqua` |
`:: Vec 4 Float` |
same as `rgb 0.0 1.0 1.0` |

`navy` |
`:: Vec 4 Float` |
same as `rgb 0.0 0.0 0.5` |

`blue` |
`:: Vec 4 Float` |
same as `rgb 0.0 0.0 1.0` |

`purple` |
`:: Vec 4 Float` |
same as `rgb 0.5 0.0 0.5` |

`fuchsia` |
`:: Vec 4 Float` |
same as `rgb 1.0 0.0 1.0` |

### Transformation Functions

`lookat` |
`:: Vec 3 Float -> Vec 3 Float -> Vec 3 Float -> Mat 4 4 Float` |
camera transformation with args: camera position, target position, upward direction |

`perspective` |
`:: Float -> Float -> Float -> Float -> Mat 4 4 Float` |
perspective transformation with args: near plane, far plane, field of view of the y axis (in radians), aspect ratio (i.e. screen’s width/height) |

`scale` |
`:: Float -> Vec 4 Float -> Vec 4 Float` |
scales a vector |

`rotMatrixX` |
`:: Float -> Mat 4 4 Float` |
rotation around X axis, takes the angle in radians |

`rotMatrixY` |
`:: Float -> Mat 4 4 Float` |
rotation around Y axis, takes the angle in radians |

`rotMatrixZ` |
`:: Float -> Mat 4 4 Float` |
rotation around Z axis, takes the angle in radians |

`rotationEuler` |
`:: Float -> Float -> Float -> Mat 4 4 Float` |
rotation using Euler angles |

`translateBefore4` |
`:: Vec 3 Float -> Mat 4 4 Float` |
translation matrix |

### Arithmetic Functions

The functions operate component-wise.

`(+)` |
`:: Num (MatVecElem a) => a -> a -> a` |
addition of two scalar, vector or matrix |

`(-)` |
`:: Num (MatVecElem a) => a -> a -> a` |
substraction of two scalar, vector or matrix |

`(*)` |
`:: Num (MatVecElem a) => a -> a -> a` |
multiplication of two scalar, vector or matrix |

`(/)` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
division of two scalar or vector |

`mod` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
modulus of two scalar or vector |

`neg` |
`:: Signed (MatVecScalarElem a) => a -> a` |
unary negation of a scalar, vector or matrix |

`(+!)` |
`:: (t ~ MatVecScalarElem a, Num t) => a -> t -> a` |
addition between (scalar, vector or matrix) and a scalar |

`(-!)` |
`:: (t ~ MatVecScalarElem a, Num t) => a -> t -> a` |
substraction between (scalar, vector or matrix) and a scalar |

`(*!)` |
`:: (t ~ MatVecScalarElem a, Num t) => a -> t -> a` |
multiplication between (scalar, vector or matrix) and a scalar |

`(/!)` |
`:: (Num t, a ~ VecScalar d t) => a -> t -> a` |
division between (scalar, vector or matrix) and a scalar |

`(%!)` |
`:: (Num t, a ~ VecScalar d t) => a -> t -> a` |
modulus between (scalar, vector or matrix) and a scalar |

### Geometric Functions

`length` |
`:: (a ~ VecScalar d Float) => a -> Float` |
length of a vector |

`distance` |
`:: (a ~ VecScalar d Float) => a -> a -> Float` |
distance of two vectors |

`dot` |
`:: (a ~ VecScalar d Float) => a -> a -> Float` |
dot product |

`cross` |
`:: (a ~ VecScalar 3 Float) => a -> a -> a` |
cross product |

`normalize` |
`:: (a ~ VecScalar d Float) => a -> a` |
normalize a vector to have length equals to 1 |

`faceforward` |
`:: (a ~ VecScalar d Float) => a -> a -> a -> a` |
same as faceforward in GLSL e.g. `faceForward n i nRef = if dot nRef i < 0 then n else -n` |

`refract` |
`:: (a ~ VecScalar d Float) => a -> a -> a -> a` |
same as refract in GLSL |

`reflect` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
same as reflect in GLSL |

### Matrix Functions

`transpose` |
`:: Mat i j a -> Mat j i a` |
transposed matrix |

`det` |
`:: Mat i i a -> Float` |
determinant |

`inv` |
`:: Mat i i a -> Mat i i a` |
inverse matrix |

`(.*.)` |
`:: Mat i j a -> Mat j k a -> Mat i k a` |
matrix * matrix (multiplication in matrix algebra) |

`(*.)` |
`:: Mat i j a -> Vec j a -> Vec i a` |
matrix * column vector (multiplication in matrix algebra) |

`(.*)` |
`:: Vec i a -> Mat i j a -> Vec j a` |
row vector * matrix (multiplication in matrix algebra) |

`outer` |
`:: Vec j a -> Vec i a -> Mat i j a` |
column vector * row vector (multiplication in matrix algebra) |

### Vector and Scalar Relational Functions (component-wise)

`(<)` |
`:: (Num t, a ~ VecScalar d t, b ~ VecScalar d Bool) => a -> a -> b` |
component-wise compare of x < y |

`(<=)` |
`:: (Num t, a ~ VecScalar d t, b ~ VecScalar d Bool) => a -> a -> b` |
component-wise compare of x <= y |

`(>)` |
`:: (Num t, a ~ VecScalar d t, b ~ VecScalar d Bool) => a -> a -> b` |
component-wise compare of x > y |

`(>=)` |
`:: (Num t, a ~ VecScalar d t, b ~ VecScalar d Bool) => a -> a -> b` |
component-wise compare of x >= y |

`(==)` |
`:: (t ~ MatVecScalarElem a) => a -> a -> Bool` |
x == y |

`(/=)` |
`:: (t ~ MatVecScalarElem a) => a -> a -> Bool` |
x /= y |

`PrimEqualV` |
`:: (Num t, a ~ VecScalar d t, b ~ VecScalar d Bool) => a -> a -> b` |
x == y (component-wise) |

`PrimNotEqualV` |
`:: (Num t, a ~ VecScalar d t, b ~ VecScalar d Bool) => a -> a -> b` |
x /= y (component-wise) |

### Logic Functions

`(&&)` |
`:: Bool -> Bool -> Bool` |
logical and |

`(||)` |
`:: Bool -> Bool -> Bool` |
logical or |

`xor` |
`:: Bool -> Bool -> Bool` |
logical exclusive or |

`not` |
`:: (a ~ VecScalar d Bool) => a -> a` |
logical negation (component-wise) |

`any` |
`:: VecScalar d Bool -> Bool` |
logical or between vector components |

`all` |
`:: VecScalar d Bool -> Bool` |
logical and between vector components |

### Angle and Trigonometry Functions

The functions operate component-wise.

`degrees` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
converts radians to degrees |

`radians` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
converts degrees to radians |

`acos` |
`:: (a ~ VecScalar d Float) => a -> a` |
arc cosine |

`acosh` |
`:: (a ~ VecScalar d Float) => a -> a` |
arc hyperbolic cosine |

`asin` |
`:: (a ~ VecScalar d Float) => a -> a` |
arc sine |

`asinh` |
`:: (a ~ VecScalar d Float) => a -> a` |
arc hyperbolic sine |

`atan` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
arc tangent |

`atan2` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
arc tangent |

`atanh` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
arc hyperbolic tangent |

`cos` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
cosine |

`cosh` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
hyperbolic cosine |

`sin` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
sine |

`sinh` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
hyperbolic sine |

`tan` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
tangent |

`tanh` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
hyperbolic tangent |

### Exponential Functions

The functions operate component-wise.

`exp` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
natural exponentiation |

`log` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
natural logarithm |

`exp2` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
computes 2 raised to the given power |

`log2` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
2 base logarithm |

`sqrt` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
square root |

`inversesqrt` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
1 / square root |

`pow` |
`:: (a ~ VecScalar d Float) => a -> a -> a` |
x raised to the y power |

### Common Functions

`floor` |
`:: (a ~ VecScalar d Float) => a -> a` |
the largest integer not larger than the value (component-wise) |

`trunc` |
`:: (a ~ VecScalar d Float) => a -> a` |
the integer whose absolute value is largest but not larger than the absolute value of the value (component-wise) |

`round` |
`:: (a ~ VecScalar d Float) => a -> a` |
the nearest integer to the value (component-wise) |

`roundEven` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
the nearest even integer to the value (component-wise) |

`ceil` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
the smallest integer not less than the value (component-wise) |

`fract` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
the fractional part of the value (component-wise) |

`modF` |
`:: (a ~ VecScalar d Float) => a -> (a, a)` |
integer and fractional components (component-wise) |

`min` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
component-wise minimum |

`max` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a` |
component-wise maximum |

`PrimMinS` |
`:: (Num t, a ~ VecScalar d t) => a -> t -> a` |
minimum between (scalar, vector or matrix) and a scalar |

`PrimMaxS` |
`:: (Num t, a ~ VecScalar d t) => a -> t -> a` |
maximum between (scalar, vector or matrix) and a scalar |

`isNan` |
`:: (a ~ VecScalar d Float, b ~ VecScalar d Bool) => a -> b` |
`True` if the value is a number (component-wise) |

`isInf` |
`:: (a ~ VecScalar d Float, b ~ VecScalar d Bool) => a -> b` |
`True` if the value is positive or negative infinity (component-wise) |

`abs` |
`:: (Signed t, a ~ VecScalar d t) => a -> a` |
component-wise absolute value |

`sign` |
`:: (Signed t, a ~ VecScalar d t) => a -> a` |
component-wise sign |

`clamp` |
`:: (Num t, a ~ VecScalar d t) => a -> a -> a -> a` |
constrain a value to lie between two further values (component-wise) |

`clampS` |
`:: (Num t, a ~ VecScalar d t) => a -> t -> t -> a` |
`clamp` with scalars |

`mix` |
`:: (a ~ VecScalar d Float) => a -> a -> a -> a` |
linear interpolation between two values (component-wise) |

`mixS` |
`:: (a ~ VecScalar d Float) => a -> a -> Float -> a` |
interpolate one scalar between (scalar, vector or matrix) values |

`mixB` |
`:: (a ~ VecScalar d Float) => a -> a -> VecScalar d Bool -> a` |
`True` : select first value; `False` : select second value (component-wise) |

`step` |
`:: (a ~ Vec d Float) => a -> a -> a` |
step function: 0.0 if the second value is less then the first; 1.0 otherwise (component-wise) |

`stepS` |
`:: (a ~ VecScalar d Float) => Float -> a -> a` |
`step` with scalar |

`smoothstep` |
`:: (a ~ Vec d Float) => a -> a -> a -> a` |
Hermite interpolation (component-wise) |

`smoothstepS` |
`:: (a ~ VecScalar d Float) => Float -> Float -> a -> a` |
`smoothstep` with scalar |

### Fragment Processing Functions

`dFdx` |
`(a ~ VecScalar d Float) => a -> a` |
partial derivate |

`dFdy` |
`(a ~ VecScalar d Float) => a -> a` |
partial derivate |

`fWidth` |
`(a ~ VecScalar d Float) => a -> a` |
the sum of the absolute value of derivatives in x and y |

### Noise Functions

`noise1` |
`:: VecScalar d Float -> Float` |
pseudo-random noise |

`noise2` |
`:: VecScalar d Float -> Vec 2 Float` |
pseudo-random noise |

`noise3` |
`:: VecScalar d Float -> Vec 3 Float` |
pseudo-random noise |

`noise4` |
`:: VecScalar d Float -> Vec 4 Float` |
pseudo-random noise |

### Bit-wise Functions

The functions operate component-wise and bit-wise.

`bAnd` |
`:: (Integral t, a ~ VecScalar d t) => a -> a -> a` |
logical AND |

`bOr` |
`:: (Integral t, a ~ VecScalar d t) => a -> a -> a` |
logical OR |

`bXor` |
`:: (Integral t, a ~ VecScalar d t) => a -> a -> a` |
logical XOR |

`bNot` |
`:: (Integral t, a ~ VecScalar d t) => a -> a` |
logical NOT |

`bAndS` |
`:: (Integral t, a ~ VecScalar d t) => a -> t -> a` |
`bAnd` with scalar |

`bOrS` |
`:: (Integral t, a ~ VecScalar d t) => a -> t -> a` |
`bOr` with scalar |

`bXorS` |
`:: (Integral t, a ~ VecScalar d t) => a -> t -> a` |
`bXor` with scalar |

The functions operate component-wise.

`shiftL` |
`:: (Integral t, a ~ VecScalar d t, b ~ VecScalar d Word) => a -> b -> a` |
shift left |

`shiftR` |
`:: (Integral t, a ~ VecScalar d t, b ~ VecScalar d Word) => a -> b -> a` |
shift right |

`shiftLS` |
`:: (Integral t, a ~ VecScalar d t) => a -> Word -> a` |
`shiftL` with scalar |

`shiftRS` |
`:: (Integral t, a ~ VecScalar d t) => a -> Word -> a` |
`shiftR` with scalar |

### Integer/Float Conversion Functions

The functions operate component-wise.

`floatBitsToInt` |
`:: VecScalar d Float -> VecScalar d Int` |
the encoding of a floating point value as an integer |

`floatBitsToWord` |
`:: VecScalar d Float -> VecScalar d Word` |
the encoding of a floating point value as a word |

`intBitsToFloat` |
`:: VecScalar d Int -> VecScalar d Float` |
inverse of `floatBitsToInt` |

`wordBitsToFloat` |
`:: VecScalar d Word -> VecScalar d Float` |
inverse of `floatBitsToWord` |

# Common data structures

### Homogeneous and heterogeneous lists (lists and tuples)

See the language specification

`Maybe`

data type

`Maybe`

has the standard definition:

`data Maybe a = Nothing | Just a`

`Vector`

data type

`data Vector (n :: Nat) t`

A `Vector n t`

is an vector with length `n`

.

The difference between `Vector`

and `Vec`

is that there is no restriction on the length of a `Vector`

.

*Phase information*

Currently `Vector`

is an auxiliary phantom type used in the description of `Fragment`

.

# Special data structures

### Geometric primitives

There are three type of primitives: triangles, lines and points.

```
data PrimitiveType
= Triangle
| Line
| Point
```

A `Primitive`

value is a container of 1, 2 or 3 values tagged with a `PrimitiveType`

.

```
data Primitive a :: PrimitiveType -> Type where
PrimPoint :: a -> Primitive a Point
PrimLine :: a -> a -> Primitive a Line
PrimTriangle :: a -> a -> a -> Primitive a Triangle
```

In LambdaCube3D, `Primitive`

is always paramterized by a heterogeneous list whose elements are called *attributes*.

### Primitive streams

`PrimitiveStream`

is a central data type of GPUs:

`type PrimitiveStream a p = [Primitive p a]`

#### Mapping `PrimitiveStream`

s

```
mapPrimitives :: (a -> b) -> PrimitiveStream p a -> PrimitiveStream p b
mapPrimitives f = map (mapPrimitive f)
mapPrimitive :: (a -> b) -> Primitive a p -> Primitive b p
```

You never need to call `mapPrimitive`

directly; use `mapPrimitives`

instead, which is compiled to runtime GPU code. (The compiled code will be part of the so-called *vertex shader*.)

#### Construction of `PrimitiveStream`

s

There are two ways to construct a `PrimitiveStream`

. The direct way is documented here, the other way is documented in Interface for inputs.

`fetchArrays`

gets a heterogenous list of attribute lists. The atribute lists should have the same length.

```
fetchArrays :: HList x -> PrimitiveStream p (HList (map ListElem x))
type family ListElem a where ListElem [a] = a
```

Example usage:

```
fetchArrays ([1.0, 2.0, 3.0], [True, False, True])
:: PrimitiveStream Triangle (Float, Bool)
```

Restriction: If the primitive type is `Triangle`

then the length of the lists should be divisible by 3; if the primitive type is `Line`

then the length of the lists should be divisible by 2.

(The higher level API will detect misuse of `fetchArrays`

statically.)

### Fragments

A `Fragment n t`

value is an `n`

-vector of `Maybe (SimpleFragment t)`

values. `Maybe`

is used because simple fragments may be filtered out with the `filterFragments`

function (see later).

`type Fragment n t = Vector n (Maybe (SimpleFragment t))`

A `SimpleFragment`

value is an attribute tuple plus a viewport coordinate with depth value:

```
data SimpleFragment t = SimpleFragment
{ sFragmentCoords :: Vec 3 Float -- x, y, depth
, sFragmentValue :: t
}
```

Basic functions on fragments:

```
customizeDepth :: (a -> Float) -> Fragment n a -> Fragment n a
filterFragment :: (a -> Bool) -> Fragment n a -> Fragment n a
mapFragment :: (a -> b) -> Fragment n a -> Fragment n b
```

### Fragment streams

`FragmentStream`

is a list of fragments:

`type FragmentStream n t = [Fragment n t]`

Operations on `FragmentStream`

s:

```
customizeDepths :: (a -> Float) -> FragmentStream n a -> FragmentStream n a
customizeDepths f = map (customizeDepth f)
filterFragments :: (a -> Bool) -> (FragmentStream n a) -> (FragmentStream n a)
filterFragments p = map (filterFragment p)
mapFragments :: (a -> b) -> FragmentStream n a -> FragmentStream n b
mapFragments f = map (mapFragment f)
```

*Phase information*

`customizeDepths`

, `filterFragments`

and `mapFragments`

are compiled to runtime GPU code.

The other operations are not accessible in any phase.

### Images

#### Image kinds

There are different kind of images depending on the role the image plays:

```
data ImageKind
= Color (c :: Type) -- the image stores `c`-values
| Depth -- the image stores depth values (`Float`s)
| Stencil -- the image stores stencil values (`Int`s)
```

The type of the stored values is calculated by `imageType`

:

```
imageType :: ImageKind -> Type
imageType (Color c) = c
imageType Depth = 'Float
imageType Stencil = 'Int
```

`Image`

type

An `Image n t`

is `n`

times a rectangle of `imageType t`

-pixels:

`type Image (n :: Nat) (t :: ImageKind) = Vector n [[imageType t]]`

The `n`

parameter is the so called *layer count*, which count the number of layers. Usually it is 1.

The layer count of an image:

`type family ImageLC a :: Nat where ImageLC (Image n t) = n`

Functions which construct clear images:

```
ColorImage :: (Num t, color ~ VecScalar d t) => color -> Image a (Color color)
DepthImage :: Float -> Image n Depth
StencilImage :: Int -> Image n Stencil
```

Some wrapper functions for creating 1-layered clear images:

```
emptyDepthImage = DepthImage @1
emptyColorImage = ColorImage @1
```

Other image construction functions (texture support):

```
PrjImage :: FrameBuffer 1 a -> Image 1 a
PrjImageColor :: FrameBuffer 1 (Depth Float, Color (Vec 4 Float)) -> Image 1 (Color (Vec 4 Float))
```

*Phase information*

`ColorImage`

, `DepthImage`

, `StencilImage`

, `PrjImage`

and `PrjImageColor`

are compiled to runtime GPU code.

The other operations are not accessible in any phase.

### Framebuffers

A `FrameBuffer n t`

is a tuple of images:

`type FrameBuffer (n :: Nat) (t :: [ImageKind]) = HList (map (Image n) t)`

#### Construction of framebuffers

One can construct a framebuffer from images if all have the same layer count:

```
imageFrame :: forall (a :: [Type]) . (sameLayerCounts a) => HList a -> FrameBuffer (ImageLC (head a)) (map GetImageKind a)
sameLayerCounts a = allSame (map 'ImageLC a)
allSame :: [a] -> Type
allSame [] = 'Unit
allSame [x] = 'Unit
allSame (x: y: xs) = 'T2 (x ~ y) (allSame (y:xs))
```

# Rasterization

Rasterization turns a `Primitive`

value into a list of `Fragment`

values.

For this, a rasterization context is needed, and also information how interpolation should be done.

### Rasterization contexts

There are different rasterization contexts for each primitive types:

```
data RasterContext a :: PrimitiveType -> Type where
TriangleCtx :: CullMode -> PolygonMode a -> PolygonOffset -> ProvokingVertex -> RasterContext a Triangle
LineCtx :: Float -> ProvokingVertex -> RasterContext a Line
PointCtx :: PointSize a -> Float -> PointSpriteCoordOrigin -> RasterContext a Point
```

Triangles can be discarded based on their apparent facing, a process known as Face Culling:

```
data CullMode
= CullFront -- triangle faces whose vertices appear counter-clockwise are culled
| CullBack -- triangle faces whose vertices appear clockwise are culled
| CullNone -- no culling
```

Triangles can be rendered in three ways according to `PolygonMode`

values. Note that in WebGL triangles are allways filled regardless of `PolygonMode`

values.

```
data PolygonMode a
= PolygonFill -- filled triangles (mostly used)
| PolygonPoint (PointSize a) -- only triangle vertices are rendered as squares with the given size
| PolygonLine Float -- only triangle edges are rendered with the given width
```

`PolygonOffset`

is used to eliminate the visual unpleasantness when you want to highlight the edges of a solid object. See glPolygonOffset.

```
data PolygonOffset
= NoOffset -- no offset
| Offset Float Float -- how to tweak depth values: *factor* and *units*
```

`ProvokingVertex`

values are used only in case of `Flat`

interpolation (see later).

```
data ProvokingVertex
= LastVertex -- the value of the last vertex is used in flat interpolation
| FirstVertex -- the value of the first vertex is used in flat interpolation
```

Points will be rendered as squares.

The square sides’ size is can given in two ways with `PointSize`

data:

```
data PointSize a
= PointSize Float -- static point size
| ProgramPointSize (a -> Float) -- dynamic point size which depends on attributes
```

Point are rendered as squares which can be texured. `PointSpriteCoordOrigin`

tells where is the origin for the texure.

```
data PointSpriteCoordOrigin
= LowerLeft -- texture origin is lower left corner
| UpperLeft -- texture origin is lower left corner
```

### Interpolation types

During rasterization, attribute values are interpolated between the vertices of triangles and lines.

OpenGL supports three types of interpolation:

```
data Interpolated t where
Flat :: Interpolated t -- no interpolation
Smooth :: (Floating t) => Interpolated t -- smooth interpolation
NoPerspective :: (Floating t) => Interpolated t -- no perspective correction
```

In case of `Flat`

interpolation, either the value of the first vertex or the value of the last vertex is chosen. The `ProvokingVertex`

value of the rasterization context tells which one to choose (see above).

### The `rasterizePrimitive`

function

`rasterize`

turns a `Primitive`

into a `FragmentStream`

, given a rasterization contex and info for interpolation:

```
rasterizePrimitive
:: a ~ Vec 4 Float: b
=> HList (map Interpolated b) -- tuple of Smooth & Flat
-> RasterContext (HList a) pr
-> Primitive (HList a) pr
-> FragmentStream 1 (HList b)
```

Notes:

- The first attribute of the primitive stream should have type
`Vec 4 Float`

.

This attribute is omitted in the result fragment stream. - One
`Interpolated`

value is needed for each fragment attribute for rasterization.

#### Rasterization of primitive streams

Always use `rasterizePrimitives`

instead of `rasterize`

becase the former is compiled to runtime GPU code:

```
rasterizePrimitives
:: a ~ Vec 4 Float: b
=> HList (map Interpolated b) -- tuple of Smooth & Flat
-> RasterContext (HList a) pr
-> PrimitiveStream pr (HList a)
-> FragmentStream 1 (HList b)
rasterizePrimitives ctx is s = concat (map (rasterize is ctx) s)
```

# Accumulation

Accumulation combines overlaying fragments. How to combine two overlaying fragments is described by an accumulation context.

The result of the accumulation is a framebuffer (a tuple of images).

### Accumulation contexts

An accumulation context is a tuple which contains one fragment operation for each fragment attribute.

There are three kind of fragment operations depending of the image kind:

```
data FragmentOperation :: ImageKind -> Type where
ColorOp :: Num c
=> Blending c -- blending function
-> VecScalar d Bool -- blending filter
-> FragmentOperation (Color (VecScalar d c))
DepthOp :: ComparisonFunction
-> Bool
-> FragmentOperation Depth
StencilOp :: StencilTests
-> StencilOps
-> StencilOps
-> FragmentOperation Stencil
```

The `ImageKind`

of a fragment operation:

```
type family FragmentOperationKind a :: ImageKind where
FragmentOperationKind (FragmentOperation x) = x
```

Blending is combination of color values.

```
data Blending :: Type -> Type where
NoBlending :: Blending t
BlendLogicOp :: (Integral t) => LogicOperation -> Blending t
Blend :: (BlendEquation, BlendEquation)
-> ((BlendingFactor, BlendingFactor), (BlendingFactor, BlendingFactor))
-> Vec 4 Float
-> Blending Float
```

```
data LogicOperation
= Clear
| And
| AndReverse
| Copy
| AndInverted
| Noop
| Xor
| Or
| Nor
| Equiv
| Invert
| OrReverse
| CopyInverted
| OrInverted
| Nand
| Set
```

```
data BlendingFactor
= ZeroBF
| OneBF
| SrcColor
| OneMinusSrcColor
| DstColor
| OneMinusDstColor
| SrcAlpha
| OneMinusSrcAlpha
| DstAlpha
| OneMinusDstAlpha
| ConstantColor
| OneMinusConstantColor
| ConstantAlpha
| OneMinusConstantAlpha
| SrcAlphaSaturate
```

```
data BlendEquation
= FuncAdd
| FuncSubtract
| FuncReverseSubtract
| Min
| Max
```

Comparison functions for depth values.

```
data ComparisonFunction
= Never
| Less
| Equal
| Lequal
| Greater
| Notequal
| Gequal
| Always
```

Stencil operations.

```
data StencilOperation
= OpZero
| OpKeep
| OpReplace
| OpIncr
| OpIncrWrap
| OpDecr
| OpDecrWrap
| OpInvert
```

### Accumulation function

The `overlay`

function overlays the fragments of a fragment streams on the given background images:

```
overlay
:: forall (n :: Nat) (c :: [Type])
. b ~ map FragmentOperationKind c
=> FrameBuffer n b -- backround images
-> ( HList c -- fragment operations (accumulation context)
, FragmentStream n (HList (imageType' b)) -- fragment steam
)
-> FrameBuffer n b -- result images
imageType' :: [ImageKind] -> [Type]
imageType' (Depth: x) = map imageType x
imageType' x = map imageType x
```

Notes:

- No fragment attribute is needed for overlaying depth images: the depth value is taken from the fragment viewport coordinates.

`accumulateWith`

just pairs an accumulation context with a fragment stream:

`accumulateWith ctx x = (ctx, x)`

# Getting inputs

The input of a pipeline consists of primitive streams, uniforms and textures.

### Uniforms and textures

Uniforms can be imported by their name:

`Uniform :: String -> t`

Note that currently the type of the uniform is not statically checked.

A texture is a uniform with type `Texture`

. Currently textures are treated specially in LambdaCube 3D but this is planned to be changed.

### Primitive streams

A primitive stream can be imported by `fetch`

:

```
fetch
:: forall a t
. String -- name of the primitive stream
-> HList t -- tuple of attribute names, given by `Attribute`
-> PrimitiveStream a (HList t)
```

Attribute names can be given by `Attribute`

:

`Attribute :: String -> t`

Note that currently the type of the attributes are not statically checked.

# Interface for outputs

`Output`

is an existential type which wraps a framebuffer.

```
data Output where
ScreenOut :: FrameBuffer a b -> Output
```

`renderFrame = ScreenOut`