# noise

## 0.1.0-SNAPSHOT

Naive Perlin noise implementation

### dependencies

 org.clojure/clojure 1.7.0 org.clojure/clojurescript 1.7.122 org.clojure/core.async 0.1.346.0-17112a-alpha

(this space intentionally left almost blank)

```(ns ^:figwheel-always noise.core
(:require))```
`(enable-console-print!)`

# Perlin Noise (naive & slow implementation)

See http://flafla2.github.io/2014/08/09/perlinnoise.html

Perlin noise is "pseudo-random" noise, which gives it a more organic look than truly random noise, because the noise function will be similar for two nearby points. This is accomplished by placing a grid on a coordinate plane and associating random vectors with each intersection point on the grid. For each point in the plane, its value is a function of the dot product between a set of vectors from the points to each corner of its bounding box, and the pseudorandom gradients associated with those corners.

generate 8 random gradients

```(def gradients
(vec (take 8 (repeatedly (fn []
(let [x (rand)
y (rand)
mult (if (> (rand) (rand)) 1.0 -1.0)
mult2 (if (> (rand) (rand)) 1.0 -1.0)]
[(* x mult) (* y mult2)]))))))```

find the gradient associated with a corner of a grid cell. This stands in for the hash function in the real implementation, and the purpose is to map data of arbitrary size to data of fixed size (our 8 random gradients). I think this, along with the dot function, account for the slowness. The theoretical explanations all involve the dot product but I don't understand how it's implemented in most real implentations, including Ken Perlin's Java reference implementation.

```(defn get-gradient
[[a b]]
(let [ndx (int (mod (+ a b) 7))]
(get gradients ndx)))```

for a given point, find the corners of the bounding box (grid cell) it is contained within

```(defn get-corners
[x y]
(let [nw [(- x (mod x 100)) (- y (mod y 100))]
[x y] nw
ne [(+ 100 x) y]
sw [x (+ 100 y)]
se [(+ 100 x) (+ 100 y)]]
[nw ne sw se]))```

vector dot product

```(defn dot
[X Y]
(reduce + (map * X Y)))```

linear interpolation function

```(defn lerp
[t a b]
(+ a (* t (- b a))))```
```(defn ease
[t]
(- (* 3 (.pow js/Math t 2))
(* 2 (.pow js/Math t 3))))```

find the gradients of each corner of the bounding box

```(defn corner-gradients
[x y]
(map get-gradient (get-corners x y)))```

find the vectors from the point to the bounding box corners

```(defn corner-to-point-vectors
[x y]
(map (fn [[cx cy]] [(- x cx) (- y cy)])
(get-corners x y)))```

compute the 'influences' of the corner gradients, by taking the dot product of the corner gradient and the vector from the point to that corner

```(defn influences
[x y]
(let [gs (corner-gradients x y)
vs (corner-to-point-vectors x y)]
(map dot gs vs)))```

compute the noise function value for a given pixel

```(defn noise
[x y]
(let [
;;situate the point within a unit square
rel-x (/ x 100)
rel-y (/ y 100)
;;find the coordinates within the unit square
frac-x (mod rel-x 1)
frac-y (mod rel-y 1)
;;exaggerate proximity to corner
Sx (ease frac-x)
Sy (ease frac-y)
;;compute influences of corner gradients
[nw ne sw se] ((fn []
(influences x y)))
;;linearly interpolate between the exaggerated point the "influenced" point
a (lerp Sx nw ne)
b (lerp Sx sw se)
z (lerp Sy a b)]
;;I forgot why this was needed :(
(.abs js/Math (/ z 10))))```

# drawing related stuff

multiplication by 40 is just so the gradients are visible on the drawn grid

```(defn xPlusGrad [x y]
(+ x (* 40 (first (get-gradient [x y])))))```
```(defn yPlusGrad [x y]
(+ y (* 40 (second  (get-gradient [x y])))))```

helper function to draw a stroke on the canvas

```(defn stroke
[ctx {:keys [startx starty endx endy]}]
(.beginPath ctx)
(.moveTo ctx startx starty)
(.lineTo ctx endx endy)
(.stroke ctx))```

draw the grid which shows the corner vectors and vectors to corners for an example point

```(defn drawGrid
[]
(let [canvas (.getElementById js/document "surface")
ctx (.getContext canvas "2d")]
(set! (.-strokeStyle ctx) "blue")
;; crisper lines on the canvas
(.translate ctx 0.5 0.5)
(doseq [n (range 100 500 100)]
(stroke ctx
{ :startx 100 :starty n
:endx 400 :endy n })
(stroke ctx
{ :startx n :starty 100
:endx n :endy 400 }))))```

draw the corner gradients on the example grid

```(defn drawGradients
[]
(let [canvas (.getElementById js/document "surface")
ctx (.getContext canvas "2d")]
(set! (.-strokeStyle ctx) "red")
(doseq [x (range 100 500 100)]
(doseq [y (range 100 500 100)]
(stroke ctx
{:startx x :starty y
:endx (xPlusGrad x y) :endy (yPlusGrad x y) })))))```

draw the example point on the grid

```(defn drawPoint
[]
(let [canvas (.getElementById js/document "surface")
ctx (.getContext canvas "2d")]
(set! (.-strokeStyle ctx) "green")
(.fillRect ctx 221 139 3 3)))```

draw the vectors from the point to the corners of its bounding box

```(defn drawPointVectors
[]
(let [canvas (.getElementById js/document "surface")
ctx (.getContext canvas "2d")
x 221
y 139]
(set! (.-strokeStyle ctx) "pink")
(doseq [[cx cy] (get-corners x y)]
(stroke ctx
{:startx cx :starty cy
:endx x :endy y }))))```

draw a canvas with the noise function computed for each pixel

```(defn drawNoiseCanvas
[]
(let [canvas (.getElementById js/document "noise")
ctx (.getContext canvas "2d")]
(doseq [x (range 100 400)
y (range 100 400)
:let [n  (int (* 256 (noise x y)))
color (str "rgb(" n "," n "," n ")")]]
(set! (.-fillStyle ctx) color)
(.fillRect ctx x y 1 1))))```
```(drawGrid)
(drawGradients)
(drawPointVectors)
(drawPoint)
(drawNoiseCanvas)```