Skip to content

Commit 299bd8b

Browse files
committed
tiling noise implementation for classic perlin noise
1 parent da1f424 commit 299bd8b

11 files changed

+164
-32
lines changed

sources/noise/gradient.swift

Lines changed: 89 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,26 @@ enum Const
66
STRETCH_2D:Double = 0.5 * (3.squareRoot() - 1)
77
}
88

9-
// UNDOCUMENTED
10-
public
11-
struct ClassicNoise3D:HashedNoise
9+
fileprivate
10+
protocol _ClassicNoise3D
1211
{
13-
let permutation_table:PermutationTable,
14-
amplitude:Double,
15-
frequency:Double
16-
17-
init(amplitude:Double, frequency:Double, permutation_table:PermutationTable)
18-
{
19-
self.amplitude = amplitude
20-
self.frequency = frequency
21-
self.permutation_table = permutation_table
22-
}
23-
24-
public
25-
init(amplitude:Double, frequency:Double, seed:Int = 0)
26-
{
27-
self.amplitude = 0.982 * amplitude
28-
self.frequency = frequency
29-
self.permutation_table = PermutationTable(seed: seed)
30-
}
31-
32-
private
12+
var frequency:Double { get }
13+
var amplitude:Double { get }
3314
func gradient(from point:Math.IntV3, at offset:Math.DoubleV3) -> Double
15+
}
16+
17+
extension _ClassicNoise3D
18+
{
19+
@inline(__always)
20+
fileprivate
21+
func _gradient(hash:Int, offset:Math.DoubleV3) -> Double
3422
{
3523
// use vectors to the edge of a cube
36-
let hash:Int = self.permutation_table.hash(point) & 15,
37-
u:Double = hash < 8 ? offset.x : offset.y,
38-
vt:Double = hash == 12 || hash == 14 ? offset.x : offset.z,
39-
v:Double = hash < 4 ? offset.y : vt
40-
return (hash & 1 != 0 ? -u : u) + (hash & 2 != 0 ? -v : v)
24+
let h:Int = hash & 15,
25+
u:Double = h < 8 ? offset.x : offset.y,
26+
vt:Double = h == 12 || h == 14 ? offset.x : offset.z,
27+
v:Double = h < 4 ? offset.y : vt
28+
return (h & 1 != 0 ? -u : u) + (h & 2 != 0 ? -v : v)
4129
}
4230

4331
public
@@ -83,6 +71,79 @@ struct ClassicNoise3D:HashedNoise
8371
}
8472
}
8573

74+
// UNDOCUMENTED
75+
public
76+
struct ClassicNoise3D:HashedNoise, _ClassicNoise3D
77+
{
78+
let permutation_table:PermutationTable,
79+
amplitude:Double,
80+
frequency:Double
81+
82+
init(amplitude:Double, frequency:Double, permutation_table:PermutationTable)
83+
{
84+
self.amplitude = amplitude
85+
self.frequency = frequency
86+
self.permutation_table = permutation_table
87+
}
88+
89+
public
90+
init(amplitude:Double, frequency:Double, seed:Int = 0)
91+
{
92+
self.amplitude = 0.982 * amplitude
93+
self.frequency = frequency
94+
self.permutation_table = PermutationTable(seed: seed)
95+
}
96+
97+
fileprivate
98+
func gradient(from point:Math.IntV3, at offset:Math.DoubleV3) -> Double
99+
{
100+
return self._gradient(hash: self.permutation_table.hash(point), offset: offset)
101+
}
102+
}
103+
104+
// UNDOCUMENTED
105+
public
106+
struct ClassicTilingNoise3D:HashedTilingNoise, _ClassicNoise3D
107+
{
108+
let permutation_table:PermutationTable,
109+
amplitude:Double,
110+
frequency:Double,
111+
wavelengths:Math.IntV3
112+
113+
init(amplitude:Double, frequency:Double, permutation_table:PermutationTable, wavelengths:Math.IntV3)
114+
{
115+
self.amplitude = amplitude
116+
self.frequency = frequency
117+
self.permutation_table = permutation_table
118+
self.wavelengths = wavelengths
119+
}
120+
121+
public
122+
init(amplitude:Double, frequency:Double, wavelengths:Int, seed:Int = 0)
123+
{
124+
self.init( amplitude: amplitude, frequency: frequency,
125+
wavelengths_x: wavelengths,
126+
wavelengths_y: wavelengths,
127+
wavelengths_z: wavelengths,
128+
seed: seed)
129+
}
130+
131+
public
132+
init(amplitude:Double, frequency:Double, wavelengths_x:Int, wavelengths_y:Int, wavelengths_z:Int, seed:Int = 0)
133+
{
134+
self.amplitude = 0.982 * amplitude
135+
self.frequency = frequency
136+
self.permutation_table = PermutationTable(seed: seed)
137+
self.wavelengths = (wavelengths_x, wavelengths_y, wavelengths_z)
138+
}
139+
140+
fileprivate
141+
func gradient(from point:Math.IntV3, at offset:Math.DoubleV3) -> Double
142+
{
143+
return self._gradient(hash: self.permutation_table.hash(Math.mod(point, self.wavelengths)), offset: offset)
144+
}
145+
}
146+
86147
@available(*, deprecated, message: "simplex noise nearly identical to and is an inferior implementation of super simplex noise")
87148
public
88149
struct SimplexNoise2D:HashedNoise

sources/noise/hash.swift

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,50 @@ extension HashedNoise
2323
public
2424
func reseeded() -> Self
2525
{
26-
return Self(amplitude: self.amplitude, frequency: self.frequency, permutation_table: PermutationTable(reseeding: self.permutation_table))
26+
let new_table:PermutationTable = PermutationTable(reseeding: self.permutation_table)
27+
return Self(amplitude: self.amplitude, frequency: self.frequency, permutation_table: new_table)
28+
}
29+
}
30+
31+
protocol HashedTilingNoise:Noise
32+
{
33+
var permutation_table:PermutationTable { get }
34+
var amplitude:Double { get }
35+
var frequency:Double { get }
36+
var wavelengths:Math.IntV3 { get }
37+
38+
init(amplitude:Double, frequency:Double, permutation_table:PermutationTable, wavelengths:Math.IntV3)
39+
}
40+
41+
extension HashedTilingNoise
42+
{
43+
public
44+
func amplitude_scaled(by factor:Double) -> Self
45+
{
46+
return Self(amplitude: self.amplitude * factor, frequency: self.frequency,
47+
permutation_table: self.permutation_table, wavelengths: self.wavelengths)
48+
}
49+
public
50+
func frequency_scaled(by factor:Double) -> Self
51+
{
52+
return Self(amplitude: self.amplitude, frequency: self.frequency * factor,
53+
permutation_table: self.permutation_table, wavelengths: self.wavelengths)
54+
}
55+
public
56+
func reseeded() -> Self
57+
{
58+
let new_table:PermutationTable = PermutationTable(reseeding: self.permutation_table)
59+
return Self(amplitude: self.amplitude, frequency: self.frequency,
60+
permutation_table: new_table, wavelengths: self.wavelengths)
61+
}
62+
63+
public
64+
func transposed(octaves:Int) -> Self
65+
{
66+
let frequency_factor:Double = octaves >= 0 ? Double(1 << octaves) : 1 / Double(1 << -octaves)
67+
return Self(amplitude: self.amplitude, frequency: self.frequency * frequency_factor,
68+
permutation_table: self.permutation_table,
69+
wavelengths: (self.wavelengths.a << octaves, self.wavelengths.b << octaves, self.wavelengths.c << octaves))
2770
}
2871
}
2972

sources/noise/noise.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,28 @@ enum Math
170170
return (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z)
171171
}
172172

173+
@inline(__always)
174+
private static
175+
func mod(_ x:Int, _ n:Int) -> Int
176+
{
177+
let remainder = x % n
178+
return remainder >= 0 ? remainder : remainder + n
179+
}
180+
181+
@inline(__always)
182+
static
183+
func mod(_ v1:IntV2, _ v2:IntV2) -> IntV2
184+
{
185+
return (Math.mod(v1.a, v2.a), Math.mod(v1.b, v2.b))
186+
}
187+
188+
@inline(__always)
189+
static
190+
func mod(_ v1:IntV3, _ v2:IntV3) -> IntV3
191+
{
192+
return (Math.mod(v1.a, v2.a), Math.mod(v1.b, v2.b), Math.mod(v1.c, v2.c))
193+
}
194+
173195
@inline(__always)
174196
static
175197
func dot(_ v1:DoubleV2, _ v2:DoubleV2) -> Double

tests/calibrate_cell2d.png

3.02 KB
Loading

tests/calibrate_cell3d.png

4.84 KB
Loading
30.8 KB
Loading

tests/calibrate_gradient2d.png

13.1 KB
Loading

tests/calibrate_gradient3d.png

11.9 KB
Loading

tests/noise/calibrate.blend

4.42 KB
Binary file not shown.

tests/noise/calibrate.blend1

571 KB
Binary file not shown.

0 commit comments

Comments
 (0)