1- //! Two- and three-dimensional Perlin noise.
1+ //! Procedural noise generation .
22
33use super :: {
44 spline:: smoothstep,
55 vary:: lerp,
66 vec:: { splat, vec2, vec3, Vec2 , Vec3 , Vector } ,
77} ;
88
9- /// Gradient vectors for 2D noise.
10- static GRADS_2 : [ Vec2 ; 8 ] = [
11- vec2 ( 0.924 , 0.383 ) ,
12- vec2 ( 0.383 , 0.924 ) ,
13- vec2 ( -0.383 , 0.924 ) ,
14- vec2 ( -0.924 , 0.383 ) ,
15- vec2 ( -0.924 , -0.383 ) ,
16- vec2 ( -0.383 , -0.924 ) ,
17- vec2 ( 0.383 , -0.924 ) ,
18- vec2 ( 0.924 , -0.383 ) ,
19- ] ;
20-
21- /// Gradient vectors for 3D noise.
22- static GRADS_3 : [ Vec3 ; 16 ] = [
23- //
24- vec3 ( 0.0 , -1.0 , -1.0 ) ,
25- vec3 ( 0.0 , -1.0 , 1.0 ) ,
26- vec3 ( 0.0 , 1.0 , -1.0 ) ,
27- vec3 ( 0.0 , 1.0 , 1.0 ) ,
28- //
29- vec3 ( -1.0 , 0.0 , -1.0 ) ,
30- vec3 ( -1.0 , 0.0 , 1.0 ) ,
31- vec3 ( 1.0 , 0.0 , -1.0 ) ,
32- vec3 ( 1.0 , 0.0 , 1.0 ) ,
33- //
34- vec3 ( -1.0 , -1.0 , 0.0 ) ,
35- vec3 ( -1.0 , 1.0 , 0.0 ) ,
36- vec3 ( 1.0 , -1.0 , 0.0 ) ,
37- vec3 ( 1.0 , 1.0 , 0.0 ) ,
38- //
39- vec3 ( 1.0 , 1.0 , 0.0 ) ,
40- vec3 ( -1.0 , 1.0 , 0.0 ) ,
41- vec3 ( 0.0 , -1.0 , 1.0 ) ,
42- vec3 ( 0.0 , -1.0 , -1.0 ) ,
43- ] ;
44-
45- #[ rustfmt:: skip]
46- static PERM : [ u8 ; 256 ] = [
47- 156 , 2 , 157 , 90 , 75 , 199 , 55 , 167 , 62 , 92 , 101 , 253 , 66 , 134 , 113 , 83 ,
48- 1 , 136 , 78 , 106 , 254 , 105 , 248 , 176 , 234 , 5 , 195 , 226 , 49 , 71 , 87 , 44 ,
49- 122 , 94 , 219 , 140 , 72 , 159 , 237 , 212 , 8 , 162 , 200 , 124 , 125 , 69 , 165 , 74 ,
50- 245 , 42 , 89 , 216 , 158 , 108 , 238 , 184 , 217 , 73 , 126 , 210 , 14 , 111 , 19 , 188 ,
51- 186 , 45 , 38 , 223 , 35 , 112 , 214 , 26 , 145 , 95 , 99 , 193 , 250 , 189 , 152 , 182 ,
52- 166 , 247 , 148 , 213 , 168 , 70 , 96 , 249 , 127 , 132 , 4 , 137 , 41 , 60 , 102 , 28 ,
53- 27 , 240 , 227 , 155 , 211 , 230 , 9 , 80 , 178 , 3 , 68 , 153 , 143 , 84 , 179 , 181 ,
54- 12 , 97 , 103 , 16 , 225 , 146 , 63 , 82 , 203 , 175 , 163 , 147 , 11 , 116 , 185 , 215 ,
55- 57 , 120 , 208 , 129 , 115 , 198 , 37 , 201 , 39 , 98 , 20 , 183 , 56 , 118 , 109 , 142 ,
56- 138 , 65 , 117 , 114 , 160 , 25 , 43 , 191 , 204 , 161 , 22 , 251 , 139 , 79 , 131 , 231 ,
57- 76 , 0 , 205 , 206 , 244 , 51 , 174 , 13 , 110 , 85 , 209 , 77 , 64 , 53 , 48 , 221 ,
58- 133 , 93 , 224 , 24 , 33 , 164 , 23 , 47 , 171 , 128 , 243 , 18 , 52 , 119 , 149 , 100 ,
59- 246 , 233 , 31 , 192 , 252 , 190 , 15 , 172 , 91 , 229 , 144 , 54 , 61 , 58 , 220 , 36 ,
60- 222 , 29 , 50 , 88 , 121 , 173 , 232 , 194 , 239 , 197 , 32 , 180 , 107 , 46 , 7 , 130 ,
61- 169 , 81 , 218 , 67 , 21 , 170 , 187 , 59 , 86 , 235 , 154 , 123 , 150 , 177 , 135 , 228 ,
62- 104 , 242 , 6 , 151 , 255 , 34 , 30 , 141 , 202 , 196 , 236 , 207 , 241 , 40 , 17 , 10
63- ] ;
64-
65- fn perm ( x : i32 ) -> i32 {
66- PERM [ ( x & 0xFF ) as usize ] as i32
67- }
68-
69- fn grad2 ( x : f32 , y : f32 ) -> Vec2 {
70- let perm = perm ( x as i32 + perm ( y as i32 ) ) ;
71- GRADS_2 [ perm as usize & 0x7 ]
72- }
73-
74- fn grads2 ( pt : Vec2 ) -> [ Vec2 ; 4 ] {
75- use super :: float:: f32;
76- let [ x0, y0] = pt. map ( f32:: floor) . 0 ;
77-
78- let g00 = grad2 ( x0, y0) ;
79- let g01 = grad2 ( x0, y0 + 1.0 ) ;
80- let g10 = grad2 ( x0 + 1.0 , y0) ;
81- let g11 = grad2 ( x0 + 1.0 , y0 + 1.0 ) ;
82-
83- [ g00, g01, g10, g11]
84- }
85-
86- fn grad3 ( x : f32 , y : f32 , z : f32 ) -> Vec3 {
87- let perm = perm ( x as i32 + perm ( y as i32 + perm ( z as i32 ) ) ) ;
88- GRADS_3 [ perm as usize & 0xF ]
89- }
90-
91- fn grads3 ( pt0 : Vec3 ) -> [ Vec3 ; 8 ] {
92- use super :: float:: f32;
93- let pt1 = pt0 + splat ( 1.0 ) ;
94- let [ x0, y0, z0] = pt0. 0 ;
95- let [ x1, y1, z1] = pt1. 0 ;
96-
97- let g000 = grad3 ( x0, y0, z0) ;
98- let g001 = grad3 ( x0, y0, z1) ;
99- let g010 = grad3 ( x0, y1, z0) ;
100- let g011 = grad3 ( x0, y1, z1) ;
101- let g100 = grad3 ( x1, y0, z0) ;
102- let g101 = grad3 ( x1, y0, z1) ;
103- let g110 = grad3 ( x1, y1, z0) ;
104- let g111 = grad3 ( x1, y1, z1) ;
105-
106- [ g000, g001, g010, g011, g100, g101, g110, g111]
107- }
108-
9+ /// Returns the Perlin noise value corresponding to the 2D point.
10910pub fn perlin2 ( pt : Vec2 ) -> f32 {
11011 use super :: float:: f32;
11112 let f = pt - pt. map ( f32:: floor) ;
@@ -123,6 +24,10 @@ pub fn perlin2(pt: Vec2) -> f32 {
12324 lerp ( t. y ( ) , a, b)
12425}
12526
27+ /// Returns the Perlin gradient vector corresponding to the 2D point.
28+ ///
29+ /// The vector is computed by taking the gradient vectors of all four
30+ /// surrounding grid points and smoothly interpolating between them.
12631pub fn perlin2v ( pt : Vec2 ) -> Vec2 {
12732 use super :: float:: f32;
12833 let fract = pt - pt. map ( f32:: floor) ;
@@ -134,6 +39,7 @@ pub fn perlin2v(pt: Vec2) -> Vec2 {
13439 lerp ( t. y ( ) , a, b)
13540}
13641
42+ /// Returns the Perlin noise value corresponding to the 3D point.
13743pub fn perlin3 ( pt : Vec3 ) -> f32 {
13844 use super :: float:: f32;
13945 let pt0 = pt. map ( f32:: floor) ;
@@ -163,6 +69,10 @@ pub fn perlin3(pt: Vec3) -> f32 {
16369 lerp ( t. z ( ) , z0, z1)
16470}
16571
72+ /// Returns the Perlin gradient vector corresponding to the 3D point.
73+ ///
74+ /// The vector is computed by taking the gradient vectors of all four
75+ /// surrounding grid points and smoothly interpolating between them.
16676pub fn perlin3v ( pt : Vec3 ) -> Vec3 {
16777 use super :: float:: f32;
16878 let fract = pt - pt. map ( f32:: floor) ;
@@ -178,35 +88,124 @@ pub fn perlin3v(pt: Vec3) -> Vec3 {
17888 lerp ( t. z ( ) , z0, z1)
17989}
18090
91+ fn perm ( x : i32 ) -> i32 {
92+ PERM [ ( x & 0xFF ) as usize ] as i32
93+ }
94+
95+ fn grad2 ( x : f32 , y : f32 ) -> Vec2 {
96+ let perm = perm ( x as i32 + perm ( y as i32 ) ) ;
97+ GRADS_2 [ perm as usize & 0x7 ]
98+ }
99+
100+ fn grads2 ( pt : Vec2 ) -> [ Vec2 ; 4 ] {
101+ use super :: float:: f32;
102+ let [ x0, y0] = pt. map ( f32:: floor) . 0 ;
103+
104+ let g00 = grad2 ( x0, y0) ;
105+ let g01 = grad2 ( x0, y0 + 1.0 ) ;
106+ let g10 = grad2 ( x0 + 1.0 , y0) ;
107+ let g11 = grad2 ( x0 + 1.0 , y0 + 1.0 ) ;
108+
109+ [ g00, g01, g10, g11]
110+ }
111+
112+ fn grad3 ( x : f32 , y : f32 , z : f32 ) -> Vec3 {
113+ let perm = perm ( x as i32 + perm ( y as i32 + perm ( z as i32 ) ) ) ;
114+ GRADS_3 [ perm as usize & 0xF ]
115+ }
116+
117+ fn grads3 ( pt0 : Vec3 ) -> [ Vec3 ; 8 ] {
118+ let pt1 = pt0 + splat ( 1.0 ) ;
119+ let [ x0, y0, z0] = pt0. 0 ;
120+ let [ x1, y1, z1] = pt1. 0 ;
121+
122+ //
123+ // 011 +--------------+ 111
124+ // / | / |
125+ // / | / |
126+ // 010 +--------------+ 110 |
127+ // | | | |
128+ // | +--------|-----+ 101
129+ // | / | /
130+ // | / | /
131+ // 000 +--------------+ 100
132+ //
133+
134+ let g000 = grad3 ( x0, y0, z0) ;
135+ let g001 = grad3 ( x0, y0, z1) ;
136+ let g010 = grad3 ( x0, y1, z0) ;
137+ let g011 = grad3 ( x0, y1, z1) ;
138+ let g100 = grad3 ( x1, y0, z0) ;
139+ let g101 = grad3 ( x1, y0, z1) ;
140+ let g110 = grad3 ( x1, y1, z0) ;
141+ let g111 = grad3 ( x1, y1, z1) ;
142+
143+ [ g000, g001, g010, g011, g100, g101, g110, g111]
144+ }
145+
146+ const A : f32 = 1.237 ;
147+ const B : f32 = 0.513 ;
148+ /// Gradient vectors for 2D noise.
149+ static GRADS_2 : [ Vec2 ; 8 ] = [
150+ vec2 ( A , B ) ,
151+ vec2 ( B , A ) ,
152+ vec2 ( -B , A ) ,
153+ vec2 ( -A , B ) ,
154+ vec2 ( -A , -B ) ,
155+ vec2 ( -B , -A ) ,
156+ vec2 ( B , -A ) ,
157+ vec2 ( A , -B ) ,
158+ ] ;
159+
160+ /// Gradient vectors for 3D noise.
161+ static GRADS_3 : [ Vec3 ; 16 ] = [
162+ //
163+ vec3 ( 0.0 , -1.0 , -1.0 ) ,
164+ vec3 ( 0.0 , -1.0 , 1.0 ) ,
165+ vec3 ( 0.0 , 1.0 , -1.0 ) ,
166+ vec3 ( 0.0 , 1.0 , 1.0 ) ,
167+ //
168+ vec3 ( -1.0 , 0.0 , -1.0 ) ,
169+ vec3 ( -1.0 , 0.0 , 1.0 ) ,
170+ vec3 ( 1.0 , 0.0 , -1.0 ) ,
171+ vec3 ( 1.0 , 0.0 , 1.0 ) ,
172+ //
173+ vec3 ( -1.0 , -1.0 , 0.0 ) ,
174+ vec3 ( -1.0 , 1.0 , 0.0 ) ,
175+ vec3 ( 1.0 , -1.0 , 0.0 ) ,
176+ vec3 ( 1.0 , 1.0 , 0.0 ) ,
177+ //
178+ vec3 ( 1.0 , 1.0 , 0.0 ) ,
179+ vec3 ( -1.0 , 1.0 , 0.0 ) ,
180+ vec3 ( 0.0 , -1.0 , 1.0 ) ,
181+ vec3 ( 0.0 , -1.0 , -1.0 ) ,
182+ ] ;
183+
184+ /// Permutation table for calculating a pseudo-random index for each grid point.
185+ #[ rustfmt:: skip]
186+ static PERM : [ u8 ; 256 ] = [
187+ 156 , 2 , 157 , 90 , 75 , 199 , 55 , 167 , 62 , 92 , 101 , 253 , 66 , 134 , 113 , 83 ,
188+ 1 , 136 , 78 , 106 , 254 , 105 , 248 , 176 , 234 , 5 , 195 , 226 , 49 , 71 , 87 , 44 ,
189+ 122 , 94 , 219 , 140 , 72 , 159 , 237 , 212 , 8 , 162 , 200 , 124 , 125 , 69 , 165 , 74 ,
190+ 245 , 42 , 89 , 216 , 158 , 108 , 238 , 184 , 217 , 73 , 126 , 210 , 14 , 111 , 19 , 188 ,
191+ 186 , 45 , 38 , 223 , 35 , 112 , 214 , 26 , 145 , 95 , 99 , 193 , 250 , 189 , 152 , 182 ,
192+ 166 , 247 , 148 , 213 , 168 , 70 , 96 , 249 , 127 , 132 , 4 , 137 , 41 , 60 , 102 , 28 ,
193+ 27 , 240 , 227 , 155 , 211 , 230 , 9 , 80 , 178 , 3 , 68 , 153 , 143 , 84 , 179 , 181 ,
194+ 12 , 97 , 103 , 16 , 225 , 146 , 63 , 82 , 203 , 175 , 163 , 147 , 11 , 116 , 185 , 215 ,
195+ 57 , 120 , 208 , 129 , 115 , 198 , 37 , 201 , 39 , 98 , 20 , 183 , 56 , 118 , 109 , 142 ,
196+ 138 , 65 , 117 , 114 , 160 , 25 , 43 , 191 , 204 , 161 , 22 , 251 , 139 , 79 , 131 , 231 ,
197+ 76 , 0 , 205 , 206 , 244 , 51 , 174 , 13 , 110 , 85 , 209 , 77 , 64 , 53 , 48 , 221 ,
198+ 133 , 93 , 224 , 24 , 33 , 164 , 23 , 47 , 171 , 128 , 243 , 18 , 52 , 119 , 149 , 100 ,
199+ 246 , 233 , 31 , 192 , 252 , 190 , 15 , 172 , 91 , 229 , 144 , 54 , 61 , 58 , 220 , 36 ,
200+ 222 , 29 , 50 , 88 , 121 , 173 , 232 , 194 , 239 , 197 , 32 , 180 , 107 , 46 , 7 , 130 ,
201+ 169 , 81 , 218 , 67 , 21 , 170 , 187 , 59 , 86 , 235 , 154 , 123 , 150 , 177 , 135 , 228 ,
202+ 104 , 242 , 6 , 151 , 255 , 34 , 30 , 141 , 202 , 196 , 236 , 207 , 241 , 40 , 17 , 10
203+ ] ;
204+
181205#[ cfg( test) ]
182206mod tests {
183207 use super :: * ;
184- use std:: dbg;
185-
186- #[ test]
187- fn perlin2_theo ( ) {
188- let pt: Vec2 = vec2 ( 9.5 , 5.5 ) ;
189-
190- use super :: super :: float:: f32;
191- let f = pt - pt. map ( f32:: floor) ;
192- let [ fx, fy] = f. 0 ;
193-
194- let [ g00, g01, g10, g11] : [ Vec2 ; 4 ] = [
195- vec2 ( 0.924 , 0.383 ) ,
196- vec2 ( 0.383 , -0.924 ) ,
197- vec2 ( -0.383 , 0.924 ) ,
198- vec2 ( -0.924 , -0.383 ) ,
199- ] ;
200- let d00 = g00. dot ( & vec2 ( fx, fy) ) ;
201- let d01 = g01. dot ( & vec2 ( fx, fy - 1.0 ) ) ;
202- let d10 = g10. dot ( & vec2 ( fx - 1.0 , fy) ) ;
203- let d11 = g11. dot ( & vec2 ( fx - 1.0 , fy - 1.0 ) ) ;
204-
205- let t = f. map ( smoothstep) ;
206- let ( a, b) = lerp ( t. x ( ) , ( d00, d01) , ( d10, d11) ) ;
207-
208- dbg ! ( lerp( t. y( ) , a, b) ) ;
209- }
208+ use std:: eprintln;
210209
211210 #[ test]
212211 fn perlin2_statistics ( ) {
@@ -223,8 +222,8 @@ mod tests {
223222 }
224223 avg /= count. pow ( 2 ) as f32 ;
225224
226- assert_eq ! ( avg, -0.0004172578 ) ;
227- assert_eq ! ( min, -0.6612066 ) ;
225+ assert_eq ! ( avg, -0.0005586566 ) ;
226+ assert_eq ! ( min, -0.8853002 ) ;
228227 assert_eq ! ( max, 0.6612066 ) ;
229228 }
230229 #[ test]
@@ -246,8 +245,8 @@ mod tests {
246245 }
247246 avg /= count. pow ( 3 ) as f32 ;
248247
249- assert_eq ! ( avg, - 0.0003959533 ) ;
248+ assert_eq ! ( avg, 0.00039595732 ) ;
250249 assert_eq ! ( min, -0.8853568 ) ;
251- assert_eq ! ( max, 0.87813747 ) ;
250+ assert_eq ! ( max, 0.8853002 ) ;
252251 }
253252}
0 commit comments