Skip to content

Commit 10662d2

Browse files
committed
create dedicated pseudo random number generator
1 parent 361140f commit 10662d2

File tree

6 files changed

+113
-93
lines changed

6 files changed

+113
-93
lines changed

poisson.png

85 Bytes
Loading

sources/noise/cell.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct CellNoise2D:Noise
4343
func evaluate(_ x:Double, _ y:Double) -> Double
4444
{
4545
let sample:DoubleV2 = (x * self.frequency , y * self.frequency),
46-
bin:IntV2 = (floor(sample.x) , floor(sample.y)),
46+
bin:IntV2 = (Math.ifloor(sample.x) , Math.ifloor(sample.y)),
4747
sample_rel:DoubleV2 = (sample.x - Double(bin.a), sample.y - Double(bin.b))
4848

4949
// determine kernel
@@ -97,7 +97,7 @@ struct CellNoise2D:Noise
9797
}
9898
}
9999

100-
// Cell group:
100+
// Cell group I:
101101
// within r^2 = 0.25
102102
// cumulative sample coverage = 65.50%
103103

@@ -133,7 +133,7 @@ struct CellNoise2D:Noise
133133
// inner ----- B ------- C --------+ ← quadrant
134134
// ↓
135135

136-
// Cell group:
136+
// Cell group II:
137137
// within r^2 = 1.0
138138
// cumulative sample coverage = 99.96%
139139
let inner:IntV2 = (near.a + quadrant.a, near.b + quadrant.b)
@@ -152,7 +152,7 @@ struct CellNoise2D:Noise
152152
return self.amplitude * r2
153153
}
154154

155-
// Cell group:
155+
// Cell group III:
156156
// within r^2 = 2.0
157157
// cumulative sample coverage = 100%
158158
let outer:IntV2 = (far.a - quadrant.a, far.b - quadrant.b)
@@ -236,7 +236,7 @@ struct CellNoise3D:Noise
236236
func evaluate(_ x:Double, _ y:Double, _ z:Double) -> Double
237237
{
238238
let sample:DoubleV3 = (x * self.frequency , y * self.frequency , z * self.frequency),
239-
bin:IntV3 = (floor(sample.x) , floor(sample.y) , floor(sample.z)),
239+
bin:IntV3 = (Math.ifloor(sample.x) , Math.ifloor(sample.y) , Math.ifloor(sample.z)),
240240
sample_rel:DoubleV3 = (sample.x - Double(bin.a), sample.y - Double(bin.b), sample.z - Double(bin.c))
241241

242242
// determine kernel
@@ -301,7 +301,7 @@ struct CellNoise3D:Noise
301301
// check each cell group, exiting early if we are guaranteed to have found
302302
// the closest point
303303

304-
// Cell group:
304+
// Cell group I:
305305
// within r^2 = 0.25
306306
// cumulative sample coverage = 47.85%
307307
_inspect_cell(offset: (-1, 0, 0))
@@ -319,7 +319,7 @@ struct CellNoise3D:Noise
319319
return self.amplitude * r2
320320
}
321321

322-
// Cell group:
322+
// Cell group II:
323323
// within r^2 = 0.5
324324
// cumulative sample coverage = 88.60%
325325
for offset in [(1, 0, 0), ( 0, 1, 0), ( 0, 0, 1),
@@ -334,7 +334,7 @@ struct CellNoise3D:Noise
334334
return self.amplitude * r2
335335
}
336336

337-
// Cell group:
337+
// Cell group III:
338338
// within r^2 = 0.75
339339
// cumulative sample coverage = 98.26%
340340
for offset in [(0, 1, 1), (1, 0, 1), (1, 1, 0), (-1, 1, 1), (1, -1, 1), (1, 1, -1)]
@@ -347,7 +347,7 @@ struct CellNoise3D:Noise
347347
return self.amplitude * r2
348348
}
349349

350-
// Cell group:
350+
// Cell group IV:
351351
// within r^2 = 1.0
352352
// cumulative sample coverage = 99.94%
353353
_inspect_cell(offset: (1, 1, 1))
@@ -357,7 +357,7 @@ struct CellNoise3D:Noise
357357
return self.amplitude * r2
358358
}
359359

360-
// Cell group:
360+
// Cell group V:
361361
// within r^2 = 1.25
362362
// cumulative sample coverage > 99.99%
363363
for offset in [(-2, 0, 0), ( 0, -2, 0), ( 0, 0, -2),
@@ -372,7 +372,7 @@ struct CellNoise3D:Noise
372372
return self.amplitude * r2
373373
}
374374

375-
// Cell group:
375+
// Cell group VI:
376376
// within r^2 = 1.5
377377
// cumulative sample coverage > 99.99%
378378
for offset in [( 0, 1, -2), ( 0, -2, 1), (1, 0, -2), (-2, 0, 1), (1, -2, 0), (-2, 1, 0),
@@ -386,7 +386,7 @@ struct CellNoise3D:Noise
386386
return self.amplitude * r2
387387
}
388388

389-
// Cell group:
389+
// Cell group VII:
390390
// within r^2 = 2.0
391391
// cumulative sample coverage > 99.99%
392392
_inspect_cell(offset: (-2, 1, 1))
@@ -398,7 +398,7 @@ struct CellNoise3D:Noise
398398
return self.amplitude * r2
399399
}
400400

401-
// Cell group:
401+
// Cell group VIII:
402402
// within r^2 = 2.25
403403
// cumulative sample coverage > 99.99%
404404
for offset in [(0, -2, -2), (-2, 0, -2), (-2, -2, 0), (-1, -2, -2), (-2, -1, -2), (-2, -2, -1)]
@@ -411,7 +411,7 @@ struct CellNoise3D:Noise
411411
return self.amplitude * r2
412412
}
413413

414-
// Cell group:
414+
// Cell group IX:
415415
// within r^2 = 2.5
416416
// cumulative sample coverage > 99.99%
417417
for offset in [(2, 0, 0), (0, 2, 0), (0, 0, 2),
@@ -426,7 +426,7 @@ struct CellNoise3D:Noise
426426
return self.amplitude * r2
427427
}
428428

429-
// Cell group:
429+
// Cell group X:
430430
// within r^2 = 2.75
431431
// cumulative sample coverage > 99.99%
432432
for offset in [(0, 1, 2), (0, 2, 1), (1, 0, 2), ( 2, 0, 1), (1, 2, 0), ( 2, 1, 0),
@@ -440,7 +440,7 @@ struct CellNoise3D:Noise
440440
return self.amplitude * r2
441441
}
442442

443-
// Cell group:
443+
// Cell group XI:
444444
// within r^2 = 3.0
445445
// cumulative sample coverage = 100%
446446
for offset in [(2, 1, 1), (1, 2, 1), (1, 1, 2)]

sources/noise/gradient.swift

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import func Glibc.sin
22
import func Glibc.cos
33

4+
fileprivate let SQUISH_2D :Double = 0.5 * (1 / 3.squareRoot() - 1)
5+
fileprivate let STRETCH_2D:Double = 0.5 * (3.squareRoot() - 1)
6+
47
fileprivate
58
protocol GradientNoise2D:Noise
69
{
@@ -71,8 +74,8 @@ struct SimplexNoise2D:GradientNoise2D
7174
v:Double = y + squish_offset
7275

7376
// get integral (u, v) coordinates of the rhombus
74-
let ub:Int = floor(u),
75-
vb:Int = floor(v)
77+
let ub:Int = Math.ifloor(u),
78+
vb:Int = Math.ifloor(v)
7679

7780
// (0, 0) ----- (1, 0)
7881
// \ A / \
@@ -354,8 +357,8 @@ struct SuperSimplexNoise2D:GradientNoise2D
354357
// (1, 2)
355358

356359
// use the (u, v) coordinates to bin the triangle
357-
let ub:Int = floor(u),
358-
vb:Int = floor(v)
360+
let ub:Int = Math.ifloor(u),
361+
vb:Int = Math.ifloor(v)
359362

360363
// get relative offsets from the top-left corner of the square (in (u, v) space)
361364
let du0:Double = u - Double(ub),
@@ -618,12 +621,12 @@ struct SuperSimplexNoise3D:Noise
618621
w2:Double = w1 + 512.5
619622

620623
// get integral (u, v, w) cube coordinates (can Swift vectorize this??)
621-
let ub1:Int = floor(u1),
622-
vb1:Int = floor(v1),
623-
wb1:Int = floor(w1),
624-
ub2:Int = floor(u2),
625-
vb2:Int = floor(v2),
626-
wb2:Int = floor(w2)
624+
let ub1:Int = Math.ifloor(u1),
625+
vb1:Int = Math.ifloor(v1),
626+
wb1:Int = Math.ifloor(w1),
627+
ub2:Int = Math.ifloor(u2),
628+
vb2:Int = Math.ifloor(v2),
629+
wb2:Int = Math.ifloor(w2)
627630

628631
// get offsets inside the cubes from the cube origins
629632
let du1:Double = u1 - Double(ub1),

sources/noise/noise.swift

Lines changed: 77 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
func floor(_ x:Double) -> Int
2-
{
3-
return x > 0 ? Int(x) : Int(x) - 1
4-
}
5-
6-
let SQUISH_2D :Double = 0.5 * (1 / 3.squareRoot() - 1)
7-
let STRETCH_2D:Double = 0.5 * (3.squareRoot() - 1)
8-
91
public
102
protocol Noise
113
{
@@ -52,40 +44,13 @@ extension Noise
5244
}
5345
}
5446

55-
struct PermutationTable
47+
enum Math
5648
{
57-
private
58-
let permut:[UInt8] // keep these small to minimize cache misses
59-
60-
init(seed:Int)
49+
@inline(__always)
50+
static
51+
func ifloor(_ x:Double) -> Int
6152
{
62-
var permutations:[UInt8] = [UInt8](0 ... 255),
63-
state128:(UInt32, UInt32, UInt32, UInt32) = (1, 0, UInt32(extendingOrTruncating: seed >> 32), UInt32(extendingOrTruncating: seed))
64-
for i in 0 ..< 255 - 1
65-
{
66-
var t:UInt32 = state128.3
67-
t ^= t &<< 11
68-
t ^= t &>> 8
69-
state128.3 = state128.2
70-
state128.2 = state128.1
71-
state128.1 = state128.0
72-
t ^= state128.0
73-
t ^= state128.0 &>> 19
74-
state128.0 = t
75-
permutations.swapAt(i, Int(t) & 255)
76-
}
77-
78-
self.permut = permutations
79-
}
80-
81-
func hash(_ n1:Int, _ n2:Int) -> Int
82-
{
83-
return Int(self.permut[Int(self.permut[n1 & 255]) ^ (n2 & 255)])
84-
}
85-
86-
func hash(_ n1:Int, _ n2:Int, _ n3:Int) -> Int
87-
{
88-
return Int(self.permut[self.hash(n1, n2) ^ (n3 & 255)])
53+
return x > 0 ? Int(x) : Int(x) - 1
8954
}
9055
}
9156

@@ -151,3 +116,75 @@ struct fBm<Generator:Noise>:Noise
151116
return u
152117
}
153118
}
119+
120+
struct RandomXORShift
121+
{
122+
private
123+
var state128:(UInt32, UInt32, UInt32, UInt32)
124+
125+
var max:UInt32
126+
{
127+
return UInt32.max
128+
}
129+
130+
init(seed:Int)
131+
{
132+
self.state128 = (1, 0, UInt32(extendingOrTruncating: seed >> 32), UInt32(extendingOrTruncating: seed))
133+
}
134+
135+
mutating
136+
func generate() -> UInt32
137+
{
138+
var t:UInt32 = self.state128.3
139+
t ^= t &<< 11
140+
t ^= t &>> 8
141+
self.state128.3 = self.state128.2
142+
self.state128.2 = self.state128.1
143+
self.state128.1 = self.state128.0
144+
t ^= self.state128.0
145+
t ^= self.state128.0 &>> 19
146+
self.state128.0 = t
147+
return t
148+
}
149+
150+
mutating
151+
func generate(less_than maximum:UInt32) -> UInt32
152+
{
153+
let upper_bound:UInt32 = UInt32.max - UInt32.max % maximum
154+
var x:UInt32 = 0
155+
repeat
156+
{
157+
x = self.generate()
158+
} while x >= upper_bound
159+
160+
return x % maximum
161+
}
162+
}
163+
164+
struct PermutationTable
165+
{
166+
private
167+
let permut:[UInt8] // keep these small to minimize cache misses
168+
169+
init(seed:Int)
170+
{
171+
var permutations:[UInt8] = [UInt8](0 ... 255),
172+
rng:RandomXORShift = RandomXORShift(seed: seed)
173+
for i in 0 ..< 255 - 1
174+
{
175+
permutations.swapAt(i, Int(rng.generate()) & 255)
176+
}
177+
178+
self.permut = permutations
179+
}
180+
181+
func hash(_ n1:Int, _ n2:Int) -> Int
182+
{
183+
return Int(self.permut[Int(self.permut[n1 & 255]) ^ (n2 & 255)])
184+
}
185+
186+
func hash(_ n1:Int, _ n2:Int, _ n3:Int) -> Int
187+
{
188+
return Int(self.permut[self.hash(n1, n2) ^ (n3 & 255)])
189+
}
190+
}

0 commit comments

Comments
 (0)