Perlin noise: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Raku}}: minor simplification)
m (→‎{{header|Wren}}: Changed to Wren S/H)
(11 intermediate revisions by 4 users not shown)
Line 1:
{{task}}
 
The   '''[[wp:Perlin noise|Perlin noise]]'''   is a kind of   [[wp:gradient noise|gradient noise]]   invented by   [[wp:Ken Perlin|Ken Perlin]]   around the end of the twentieth century and still currently heavily used in   [[wp:computer graphics|computer graphics]],   most notably to procedurally generate textures or heightmaps.
 
The Perlin noise is basically a &nbsp; [[random numbers|pseudo-random]] &nbsp; mapping of &nbsp; <big><big><math>\R^d</math></big></big> &nbsp; into &nbsp; <big><big><math>\R</math></big></big> &nbsp; with an integer &nbsp; <big><math>d</math></big> &nbsp; which can be arbitrarily large but which is usually &nbsp; 2, &nbsp; 3, &nbsp; or &nbsp; 4.
 
Either by using a dedicated library or by implementing the algorithm, show that the Perlin noise &nbsp; (as defined in 2002 in the Java implementation below) &nbsp; of the point in 3D-space with coordinates &nbsp; &nbsp; 3.14, &nbsp; 42, &nbsp; 7 &nbsp; &nbsp; is &nbsp; &nbsp; 0.13691995878400012.
 
Either by using a dedicated library or by implementing the algorithm, show that the Perlin noise (as defined in 2002 in the Java implementation below) of the point in 3D-space with coordinates 3.14, 42, 7 is 0.13691995878400012.
 
''Note: this result assumes 64 bit IEEE-754 floating point calculations. If your language uses a different floating point representation, make a note of it and calculate the value accurate to 15 decimal places, or your languages accuracy threshold if it is less. Trailing zeros need not be displayed.''
Line 214 ⟶ 213:
C:\rosettaCode>perlin.exe perlinData.txt 3.14 42 7
Perlin Noise for (3.14,42,7) is 0.13691995878400012
</pre>
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cmath>
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
 
std::vector<int32_t> p(512, 0);
 
double fade(const double& t) {
return t * t * t * ( t * ( t * 6 - 15 ) + 10 );
}
 
double lerp(const double& t, const double& a, const double& b) {
return a + t * ( b - a );
}
 
double grad(const int32_t& hash, const double& x, const double& y, const double& z) {
const int32_t h = hash & 15; // CONVERT LOW 4 BITS OF HASH CODE
const double u = h < 8 ? x : y; // INTO 12 GRADIENT DIRECTIONS.
const double v = h < 4 ? y : ( h == 12 || h == 14 ) ? x : z;
return ( ( h & 1 ) == 0 ? u : -u ) + ( ( h & 2 ) == 0 ? v : -v );
}
 
double perlin_noise(double x, double y, double z) {
int32_t X = static_cast<int32_t>(floor(x)) & 0xff; // FIND UNIT CUBE THAT
int32_t Y = static_cast<int32_t>(floor(y)) & 0xff; // CONTAINS POINT.
int32_t Z = static_cast<int32_t>(floor(z)) & 0xff;
x -= floor(x); // FIND RELATIVE X,Y,Z
y -= floor(y); // OF POINT IN CUBE.
z -= floor(z);
 
const double u = fade(x); // COMPUTE FADE CURVES
const double v = fade(y); // FOR EACH OF X,Y,Z.
const double w = fade(z);
 
const int32_t A = p[X ] + Y;
const int32_t AA = p[A ] + Z;
const int32_t AB = p[A + 1] + Z; // HASH COORDINATES OF
const int32_t B = p[X + 1] + Y;
const int32_t BA = p[B ] + Z;
const int32_t BB = p[B + 1] + Z; // THE 8 CUBE CORNERS,
 
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD
grad(p[BA ], x - 1, y , z )), // BLENDED
lerp(u, grad(p[AB ], x , y - 1, z ), // RESULTS
grad(p[BB ], x - 1, y - 1, z ))), // FROM 8
lerp(v, lerp(u, grad(p[AA + 1], x , y , z - 1), // CORNERS
grad(p[BA + 1], x - 1, y , z - 1)), // OF CUBE
lerp(u, grad(p[AB + 1], x , y - 1, z - 1),
grad(p[BB + 1], x - 1, y - 1, z - 1))));
}
 
void read_file(const std::string& file_name) {
std::ifstream file("../" + file_name);
if ( file.is_open() ) {
int32_t index = 0;
std::string line;
while( std::getline(file, line) ) {
std::istringstream stream(line);
std::string word;
while ( std::getline(stream, word, ',') ) {
const int32_t number = std::stoi(word);
p[index] = number;
p[256 + index] = number;
index++;
}
}
} else {
std::cout << "Cannot open file" << std::endl;
}
}
 
int main() {
read_file("permutation.txt");
 
std::cout << "Perlin noise applied to (3.14, 42.0, 7.0) gives " << std::setprecision(16)
<<perlin_noise(3.14, 42.0, 7.0) << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
Perlin noise applied to (3.14, 42.0, 7.0) gives 0.1369199587840001
</pre>
 
Line 415 ⟶ 502:
=={{header|Delphi}}==
See [https://rosettacode.org/wiki/Perlin_noise#Pascal Pascal].
 
 
=={{header|EasyLang}}==
{{trans|Lua}}
{{trans|D}}
 
[https://easylang.dev/show/#cod=bZbdctpIEIXveYqu2qot2C0TzYxmJF3kSVK+AGxiyjZQBBykp893hBBIxLHRzOnuM6d/NGT/49m+2w9z0ZlLmblQWOWsYhXZAAbzGUC0KlkM5qrcfAhWmPd45JmFZC4LFjJLFYC30qrK4PEYPQx8Kg475hK4MOcF5lZEYwFeFZa8iTt6gioOJcYVFjjEWfAWiSrYByvhgN7llcVkpXDiUCxBUlMol9L4dRyA0SUeyoVlqEwiiErJCtEQEUXprNSZjsxIxHtL0q8wakB6XmdkFMJb7ixGI9LnPDDlMGcesmAxN45DS4ItEQ4JMjMrVMrKCs4jH4dwn5VWchZCk1KGv5JVebAmzJGsi5WVLJPOkAQiKuUGP3gwDG3V1BMkRZUCX6qODlQFnFV0ndM6RCtpE0ZHWCYd9BYBVEV+bEQPu2SCl0ZbvbqoChUqiyqFJZc8bKYCRFWa0VCpyFvTkulJOglmhdJjNOgooxG+HShTMlTCMSkFZo2c15RxegFcagRYZ2BO85OsUqosmVp66lHnKjUJCBInMYI4XIRMlqdjJU0DoWOeCvtc08qSByXQrlIRc9PU4+sqWTQcqkRupYYMYvVPLwcpUulcK8JxI21VQCKYQq9JUSYIgZQCKG1GXmJIG0GOFBxvFkkyix5SjUtU1zN7nqx3B9vYcQdtmpjZnnf13+88Ns+T+WR92q5svXh5taPNZT68Hk+HLbv/+r9p/5HsCeaZ/U9Ks2v0x+thj9/ClgOGBV5t4JKgRe/987B4sbfFrzc7W23NJeSN26PFPncvFFrQZt2imSFfC+eF3ujP0NeCXj86V9e75kPXGgHngesD19OIKwwdnh498kc5zcAhDh2aBxHpUcSQofiLiKFHOU50LKLqaxIe5YzKlz1WrSW7b+rTBe16ud1tfr3e93EBz/pjx5nntpXdyC17uL6HVz3c3MPnM/gl3mlf1+zr275p2De3/Uk0muBzW9+v67Zu8/t93TZtMovMNPsaTvfMx7IF3QXMruiqRf0N9T26vBH4nmB5IVgOCZb+ht4I3uXbvgWwuEsAKZPlReG7v9mXnX16Vu/d7M4r3LH4nmVa1xfHziu/4/IjrrFvHOnyV13TpmkdW680UueH6ga+xUijH2oc+JYjpf5vSu8juolsb5/fNm2fX93zpCq/+9ltG6jFbPboFsnozq1AyEx31fb0uf486usrm+wPm+2xG/Yw5xbmi6KY/GPt1arhzHS9ctFL1rod/iHGzx7owjA92zf+m6OsukU2d53X5+5L79M3vgllvF5Tq93H7hDg4F//kq6OBCb9XV7S+eQP Run it]
 
<syntaxhighlight>
p[] = [ 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 ]
for i to 256
p[] &= p[i]
.
func fade t .
return t * t * t * (t * (t * 6 - 15) + 10)
.
func lerp t a b .
return a + t * (b - a)
.
func grad hash x y z .
h = hash mod 16
if h = 0 or h = 12
return x + y
elif h = 1 or h = 14
return y - x
elif h = 2
return x - y
elif h = 3
return -x - y
elif h = 4
return x + z
elif h = 5
return z - x
elif h = 6
return x - z
elif h = 7
return -x - z
elif h = 8
return y + z
elif h = 9 or h = 13
return z - y
elif h = 10
return y - z
.
return -y - z
.
func noise x y z .
a = floor x mod 256
b = floor y mod 256
c = floor z mod 256
xx = x mod 1
yy = y mod 1
zz = z mod 1
u = fade xx
v = fade yy
w = fade zz
a0 = p[a + 1] + b
a1 = p[a0 + 1] + c
a2 = p[a0 + 2] + c
b0 = p[a + 2] + b
b1 = p[b0 + 1] + c
b2 = p[b0 + 2] + c
k1 = grad p[a1 + 1] xx yy zz
k2 = grad p[b1 + 1] (xx - 1) yy zz
k3 = grad p[a2 + 1] xx (yy - 1) zz
k4 = grad p[b2 + 1] (xx - 1) (yy - 1) zz
k5 = grad p[a1 + 2] xx yy (zz - 1)
k6 = grad p[b1 + 2] (xx - 1) yy (zz - 1)
k7 = grad p[a2 + 2] xx (yy - 1) (zz - 1)
k8 = grad p[b2 + 2] (xx - 1) (yy - 1) (zz - 1)
return lerp w (lerp v (lerp u k1 k2) (lerp u k3 k4)) (lerp v (lerp u k5 k6) (lerp u k7 k8))
.
numfmt 17 0
print noise 3.14 42 7
#
# demo
for y = 0 to 199
for x = 0 to 199
p = noise (x / 30) (y / 30) 0.1
move x / 2 y / 2
color3 p p p
rect 0.6 0.6
.
.
</syntaxhighlight>
 
=={{header|Evaldraw}}==
{{trans|C}}
 
This is a translation of the C version, with the gradient function borrowed from the Go version.
This evaldraw version computes the correct output. The array doesnt have to be 512 elements, we can rely on the wrap around when
accessing indices out of bounds since power of 2 arrays are anded with their size on access. Evaldraw has a built-in noise(x,y,z) function
that behaves like perlin noise, but does not give the exact same result as the original implementation in Java by Ken Perlin. There
is a comparison, so we can see the similarity in output visually.
 
[[File:Evaldrawperlinnoise.png|thumb|alt=builtin noise function is faster|Perlin noise function vs builtin noise]]
 
<syntaxhighlight lang="c">
static p[256] = {
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
};
 
()
{
cls(0);
x=3.14; y=42; z=7;
val = perlin_noise(x,y,z);
// expect val=0.13691995878400012
moveto(0,256);
setcol(255,255,255);
printf("Perlin Noise for (%g,%g,%g) is %.17lf\n",x,y,z,val);
val = noise(x,y,z);
printf("Evaldraw builtin noise for (%g,%g,%g) is %.17lf",x,y,z,val);
t = 2*klock(0);
freq = 8;
scale = freq/255;
for(y=0; y<256; y++)
for(x=0; x<256; x++)
{
val = 128+128 * perlin_noise(x * scale,y * scale,t);
setcol(48+.25*val,64+1*val,200+1.5*val);
setpix(x,y);
val = 128+128 * noise(x * scale,y * scale,t);
setcol(48+.25*val,64+1*val,200+1.5*val);
setpix(x+256,y);
}
}
 
fade(t) { t * t * t * (t * (t * 6 - 15) + 10); }
 
lerp(t,a,b) { a + t * (b - a); }
 
grad(hash, double x, double y, double z) {
// convert 4 bits of hash into 12 gradient vectors
h = int(hash % 15);
// Evaldraw rscript compiler doesnt handle
// chained terniary statements gracefully, use if-else instead.
if (h==0 || h==12)
return x + y;
else if (h==1 || h==14)
return y - x;
else if (h==2)
return x - y;
else if (h==3)
return -x - y;
else if (h==4)
return x + z;
else if (h==5)
return z - x;
else if (h==6)
return x - z;
else if (h==7)
return -x - z;
else if (h==8)
return y + z;
else if (h==9 || h==13)
return z - y;
else if (h==10)
return y - z;
// case 11, 16:
return -y - z;
}
perlin_noise(x,y,z) {
// Find cube corner from xyz
cubx = floor(x);
cuby = floor(y);
cubz = floor(z);
x -= floor(x);
y -= floor(y);
z -= floor(z);
// Curves for x,y,z
u = fade(x);
v = fade(y);
w = fade(z);
// Hash coords of 8 cube corners
A = p[cubx]+cuby; AA = p[A]+cubz; AB = p[A+1]+cubz,
B = p[cubx+1]+cuby; BA = p[B]+cubz; BB = p[B+1]+cubz;
// Blended results from 8 corners in cube
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ),
grad(p[BA ], x-1, y , z )),
lerp(u, grad(p[AB ], x , y-1, z ),
grad(p[BB ], x-1, y-1, z ))),
lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ),
grad(p[BA+1], x-1, y , z-1 )),
lerp(u, grad(p[AB+1], x , y-1, z-1 ),
grad(p[BB+1], x-1, y-1, z-1 ))));
}
</syntaxhighlight>
 
=={{header|Factor}}==
Line 936 ⟶ 1,229:
 
=={{header|Java}}==
The original code from Perlin was originally published in java. Note that this does not have a main method so there will be no output. To test, add a main method, call noise() with 3.14,42,7, save the file as ImprovedNoise.java and compile.
<syntaxhighlight lang="java">// JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN.
 
Line 1,916 ⟶ 2,209:
 
sub noise($x is copy, $y is copy, $z is copy) {
my ($u, $v, $w) = map &fade, ($x, $y, $z) »-=«
my ($X, $Y, $Z) = ($x, $y, $z)».floor »+&» 255;
my ($u, $v, $w) = map &fade, $x -= $X, $y -= $Y, $z -= $Z;
my ($AA, $AB) = @p[$_] + $Z, @p[$_ + 1] + $Z given @p[$X] + $Y;
my ($BA, $BB) = @p[$_] + $Z, @p[$_ + 1] + $Z given @p[$X + 1] + $Y;
Line 1,930 ⟶ 2,223:
}
 
say noise 3.14, 42, 7;</syntaxhighlight>
</syntaxhighlight>
{{out}}
<pre>0.13691995878</pre>
Line 1,937 ⟶ 2,229:
=={{header|REXX}}==
{{trans|Go}}
Programming note: &nbsp; the REXX operator &nbsp; <big><b> '''//''' </b></big> &nbsp; is the remainder for division &nbsp; (not modulus), &nbsp; so the absolute value of the
<br>remainder is used for this task.
 
Line 1,987 ⟶ 2,279:
lerp(u, grad( pick(ab+1), x , ym, zm ), ,
grad( pick(bb+1), xm, ym, zm )))) /1</syntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
 
(Output note: &nbsp; this REXX program uses '''100''' decimal digit precision, but '''20''' decimal digits would've been adequate.)
 
(Note that REXX uses &nbsp; ''decimal'' &nbsp; floating point, &nbsp; not binary.)
<pre>
Perlin noise for the 3D point [3.14 42 7] ───► 0.136919958784
Line 2,409 ⟶ 2,701:
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="ecmascriptwren">var permutation = [
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,
9,476

edits