# Warp the coordinate space

## A bit of theory about the OpenGL graphic pipeline

In the OpenGL graphics pipeline, the **fragment processor** is
the programmable unit that operates on fragment values. Shaders that
are intended to run in this processor are called
**fragment shaders**.
Refer to the book *OpenGL Shading Language* by R.J. Rost
and B. Licea-Jane for a deep understanding of the OpenGL graphics
pipeline.

The fragment values are computed between the vertex processor and
the fragment processor, and they are made available to the fragment
shader through **special input variables**. The primary inputs to
the fragment shader are the interpolated *varying* variables.

The window coordinate position of the fragment is communicated
through the special input varying variable
`vec4 gl_FragCoord`

. This window position value is the
result of the fixed functionality that interpolates primitives after
vertex processing to generate fragments.

## A simple exercise: warp an image by transforming the space coordinates

The fragment shader is executed on the fragment processor and
produces output values based on the input values that are provided.
One of the user-defined **output variables** is the
`vec4 gl_FragColor`

variable, which assigns the RGB
colour to the fragment.
There is a notebook of this exercise, have look at
https://observablehq.com/@riccardoscalco/warp-glsl-coordinate-space.

A fragment shader cannot change the fragment position
`gl_FragCoord`

, its task is to define the
`gl_FragColor`

variable as a function of
`gl_FragCoord`

.

In the next examples, the fragment position is expressed by a
variable `vec2 p`

with values in `[0, 1]`

. The
exercise we are going to follow is based on two functions. The first
function defines the fragment colour taking the fragment position as
the argument: `vec4 colour = f(p)`

. The second function
`vec2 g(p)`

warps the coordinate space defined by the
values of `p`

.

The composition of `f`

and `g`

will output a
distorted version of the original drawing:
`vec4 warpedColor = f(g(p))`

.

## Draw a lattice on the canvas

To better visualize the space transformation, the function
`f`

above implements a lattice.

Listing 1 shows the implementation of the
`smoothSquare`

function, which produces a smooth square
function along a given direction, with peaks nearly
`2 * delta`

wide. The `lattice`

function is
defined as the sum of two `smoothSquare`

drawn at two
perpendicular directions: `p.x`

and `p.y`

.

## Warp the coordinate space with a rotation around a point

For the sake of convenience, we are going to implement the space
transformation `g`

as a rotation around the canvas
centre.

Function `translateAndScale`

in
listing 2 scales the vector
`p`

of a factor `s`

and translates
`p`

so that the point `p = vec2(0., 0.)`

would
be at the centre of the canvas.

Function `rotate2D`

in
listing 3 implements a two-dimensional
rotation of an angle `alpha`

.

Function `warp`

applies the rotation to the point
`p`

, with an angle `alpha`

that is
proportional to the distance of `p`

from the canvas
centre.

## Distort the lattice with function composition

Eventually, we make use of function composition to warp the lattice
drawn in listing 1. The function
`lattice(warp(p))`

results from the composition of
functions `warp`

and `lattice`

.