Итак, я написал свою реализацию перлинового шума php (код в конце) на основе https://flafla2.github.io/2014/08/09/perlinnoise.html, и я получаю странные результаты.
Подводя итог, здесь представляет собой изображение градаций серого для x и y между 0 и 5, полученное путем сопоставления каждого значения между 0 и 1 со значением между 0x0 и 0xFF и повторения его трижды. Кроме того, значение усечено, чтобы быть на безопасной стороне.
Первое, что следует заметить в этой предполагаемой шкале серого, - это не на самом деле оттенки серого. Цвета действительны из-за усечения. Тем не менее, цветные и белые пятна существуют , поскольку значения находятся не между 0 и 1, а (в данном случае) между -21.807741342341
и 20.055290825771
(полученными из той же программы).
Исходя из того, что я видел при отладке этой вещи ранее, я бы предположил, что цвета больше 1, а белые отрицательны (также, когда я добавляю abs()
к коду, я избавляюсь от всего чистого белые области).
Из того, что я понимаю о перлин-шуме, он должен быть непрерывным. Не с этими линиями, нарисованными там, где x или y является точной единицей.
Кроме того, в комментариях к учебнику говорится, что возвращаемые значения никогда не должны превышать границу [0,1]. Очевидно, это так. Что здесь происходит? Не то, чтобы мне не нравились эти паттерны или что-то в этом роде, но я думаю, что с помощью рабочего перлин-шума можно, вероятно, получить нечто подобное.
Примечание. путь возможен. Пожалуйста, не жалуйтесь.
<?php
class perlin{
public function __construct(){
$this->p=array_merge($this->permutation,$this->permutation);
//print_r($this->p);
}
private $permutation=array(93, 127, 136, 113, 54, 147, 1, 165, 82, 43, 7, 125, 149, 244, 192, 100, 48, 39, 96, 98, 255, 60, 22, 158, 171, 137, 23, 72, 142, 166, 11, 94, 92, 87, 139, 247, 111, 236, 61, 188, 86, 250, 151, 9, 14, 90, 8, 124, 180, 179, 157, 17, 141, 209, 35, 242, 42, 184, 186, 172, 21, 215, 162, 227, 74, 121, 177, 253, 214, 220, 66, 230, 109, 46, 239, 119, 175, 238, 19, 6, 95, 15, 229, 190, 226, 26, 88, 182, 106, 76, 27, 49, 212, 213, 25, 89, 56, 219, 205, 164, 83, 38, 146, 5, 102, 170, 115, 181, 103, 228, 211, 31, 155, 197, 232, 204, 52, 199, 173, 148, 101, 85, 153, 156, 3, 224, 47, 33, 208, 150, 114, 116, 129, 145, 50, 160, 183, 140, 36, 217, 185, 233, 132, 107, 135, 75, 221, 191, 223, 81, 32, 10, 243, 18, 65, 246, 248, 78, 176, 225, 131, 55, 29, 80, 99, 16, 71, 112, 163, 62, 123, 51, 195, 251, 178, 67, 44, 105, 159, 30, 104, 174, 4, 152, 57, 133, 252, 45, 120, 256, 207, 70, 202, 201, 68, 189, 84, 169, 53, 254, 168, 12, 59, 249, 206, 63, 200, 128, 37, 77, 108, 64, 28, 122, 196, 167, 91, 117, 231, 187, 34, 69, 41, 110, 241, 40, 154, 237, 73, 143, 58, 245, 20, 234, 235, 222, 97, 210, 193, 161, 203, 216, 118, 24, 126, 194, 79, 218, 2, 13, 138, 130, 134, 240, 144, 198);
//generated by seq 1 256|shuf|sed 's/$/,/g'|tr '\n' ' '
public $repeat=0;
private $p=array();
private function inc($num){
$num++;
if($this->repeat>0){
$num%=$this->repeat;
}
return $num;
}
private function fade(float $t){
return $t*$t*$t*($t*($t*6+15)+10);
}
public function perlin(float $x,float $y,float $z){
if($this->repeat>0){
$x=$x%$this->repeat;
$y=$y%$this->repeat;
$z=$z%$this->repeat;
}
$xi=(int)($x) & 255;
$yi=(int)($y) & 255;
$zi=(int)($z) & 255;
$xf=$x-(int)($x);
$yf=$y-(int)($y);
$zf=$z-(int)($z);
//echo "$xi $yi $zi $xf $yf $zf<br>\n\n";
$u=$this->fade($xf);
$v=$this->fade($yf);
$w=$this->fade($zf);
$aaa=$this->p[$this->p[$this->p[ $xi ]+ $yi ]+ $zi ];
$aba=$this->p[$this->p[$this->p[ $xi ]+$this->inc($yi)]+ $zi ];
$aab=$this->p[$this->p[$this->p[ $xi ]+ $yi ]+$this->inc($zi)];
$abb=$this->p[$this->p[$this->p[ $xi ]+$this->inc($yi)]+$this->inc($zi)];
$baa=$this->p[$this->p[$this->p[$this->inc($xi)]+ $yi ]+ $zi ];
$bba=$this->p[$this->p[$this->p[$this->inc($xi)]+$this->inc($yi)]+ $zi ];
$bab=$this->p[$this->p[$this->p[$this->inc($xi)]+ $yi ]+$this->inc($zi)];
$bbb=$this->p[$this->p[$this->p[$this->inc($xi)]+$this->inc($yi)]+$this->inc($zi)];
$x1=$this->lerp($this->grad($aaa,$xf,$yf,$zf),
$this->grad($baa,$xf-1,$yf,$zf),$u);
$x2=$this->lerp($this->grad($aba,$xf,$yf-1,$zf),
$this->grad($bba,$xf-1,$yf-1,$zf),$u);
$y1=$this->lerp($x1,$x2,$v);
$x1=$this->lerp($this->grad($aab,$xf,$yf,$zf-1),
$this->grad($bab,$xf-1,$yf,$zf-1),$u);
$x2=$this->lerp($this->grad($abb,$xf,$yf-1,$zf-1),
$this->grad($bbb,$xf-1,$yf-1,$zf-1),$u);
$y2=$this->lerp($x1,$x2,$v);
return ($this->lerp($y1,$y2,$w)+1)/2;
}
private function grad(int $hash,float $x,float $y,float $z){
switch($hash & 0xF){
case 0x0: return $x+$y;
case 0x1: return -$x + $y;
case 0x2: return $x - $y;
case 0x3: return -$x - $y;
case 0x4: return $x + $z;
case 0x5: return -$x + $z;
case 0x6: return $x - $z;
case 0x7: return -$x - $z;
case 0x8: return $y + $z;
case 0x9: return -$y + $z;
case 0xA: return $y - $z;
case 0xB: return -$y - $z;
case 0xC: return $y + $x;
case 0xD: return -$y + $z;
case 0xE: return $y - $x;
case 0xF: return -$y - $z;
default: return 0;
}
}
private function lerp(float $a,float $b,float $x){
return $a+$x*($b-$a);
}
}
?>
Минимальный пример недопустимого значения:
<?php
require("perlin.php");
$noise=new perlin;
echo $noise->perlin(1.5,0.5,0); //return 1.4375
?>