-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
simplex.go
148 lines (127 loc) · 4.54 KB
/
simplex.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package simplex
import (
"unsafe"
)
const (
f2 = 0.36602542 // float32(0.5 * (math.Sqrt(3) - 1))
g2 = 0.21132487 // float32((3 - math.Sqrt(3)) / 6)
)
var (
perm [512]uint8
grad [512]uint16
pPerm unsafe.Pointer
pGrad unsafe.Pointer
)
var table = []uint8{151, 160, 137, 91, 90, 15,
131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180}
func init() {
var g2d = [12]uint16{
0x0101, // [+1, +1]
0xff01, // [-1, +1]
0x01ff, // [+1, -1]
0xffff, // [-1, -1]
0x0100, // [+1, +0]
0xff00, // [-1, +0]
0x0100, // [+1, +0]
0xff00, // [-1, +0]
0x0001, // [+0, +1]
0x00ff, // [+0, -1]
0x0001, // [+0, +1]
0x00ff, // [+0, -1]
}
for i := 0; i < 512; i++ {
perm[i] = table[i&255]
grad[i] = g2d[perm[i]%12]
}
pPerm = unsafe.Pointer(&perm[0])
pGrad = unsafe.Pointer(&grad[0])
}
// permutationsAt loads the three permutation locations for the gradients
func permutationsAt(idx, center uint16) (uint16, uint16, uint16) {
return uint16(*(*uint8)((unsafe.Pointer)(uintptr(pPerm) + uintptr(idx)))),
uint16(*(*uint8)((unsafe.Pointer)(uintptr(pPerm) + uintptr(idx+center)))),
uint16(*(*uint8)((unsafe.Pointer)(uintptr(pPerm) + uintptr(idx+1))))
}
// gradientAt loads the pre-calculated 2D gradient from the lookup table
func gradientAt(idx uint16) uint16 {
return *(*uint16)((unsafe.Pointer)(uintptr(pGrad) + 2*uintptr(idx)))
}
// Noise2 computes a two dimensional simplex noise
// Public Domain: https://weber.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
// Reference: https://mrl.cs.nyu.edu/~perlin/noise/
func Noise2(x, y float32) float32 {
// Skew the input space to determine which simplex cell we're in
s := (x + y) * f2
i := floor(x + s)
j := floor(y + s)
// Unskew the cell origin back to (x,y) space
t := float32(i+j) * g2
x0 := x - (float32(i) - t)
y0 := y - (float32(j) - t)
// For the 2D case, the simplex shape is an equilateral triangle.
// Determine which simplex we are in
i1, j1 := uint16(0), uint16(1) // upper triangle
if x0 > y0 { // lower triangle
i1 = 1
j1 = 0
}
// Offsets for middle corner in (x,y) unskewed coords
x1 := x0 - float32(i1) + g2
y1 := y0 - float32(j1) + g2
// Offsets for middle corner in (x,y) unskewed coords
const g = 2 * g2
x2 := x0 - 1 + g
y2 := y0 - 1 + g
// Work out the hashed gradient indices of the three simplex corners
ii := uint16(i & 255)
jj := uint16(j & 255)
p0, p1, p2 := permutationsAt(jj, j1)
g0 := gradientAt(ii + p0)
g1 := gradientAt(ii + i1 + p1)
g2 := gradientAt(ii + 1 + p2)
// Calculate the contribution from the three corners
n := float32(0.0)
if t := 0.5 - x0*x0 - y0*y0; t > 0 {
n += pow4(t) * dot2D(g0, x0, y0)
}
if t := 0.5 - x1*x1 - y1*y1; t > 0 {
n += pow4(t) * dot2D(g1, x1, y1)
}
if t := 0.5 - x2*x2 - y2*y2; t > 0 {
n += pow4(t) * dot2D(g2, x2, y2)
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to return values in the interval [-1,1].
return 70.0 * n
}
// pow4 lifts the value to the power of 4
func pow4(v float32) float32 {
v *= v
v *= v
return v
}
// dot2D computes dot product with the gradient
func dot2D(g uint16, x, y float32) float32 {
gx := float32(int8(g >> 8))
gy := float32(int8(g))
return gx*x + gy*y
}
// floor floors the floating-point value to an integer
func floor(x float32) int {
v := int(x)
if x < float32(v) {
return v - 1
}
return v
}