为什么我的Perlin噪声会产生超出预期范围的波动值,并产生具有硬边的非重复瓷砖?

时间:2020-01-20 20:20:51

标签: php procedural-generation perlin-noise

因此,我基于https://flafla2.github.io/2014/08/09/perlinnoise.html编写了我的php perlin noise实现(末尾代码),结果很奇怪。

总而言之,这是通过将0和1之间的每个值映射到0x0和0xFF之间的值并将其重复三次而获得的x和y在0和5之间的灰度图像。同样,为了安全起见,该值也被截断。

perlin weirdness

关于这个所谓的灰度的第一件事是,它实际上不是灰度。颜色是有效的,因为被截断了。但是,存在彩色和白色色块 ,因为值不在0和1之间,而是(在这种情况下)介于-21.80774134234120.055290825771之间(从同一程序获得) )。

根据我之前调试此东西时看到的内容,我猜颜色超过1,白色为负数(而且,当我在代码中添加abs()时,我摆脱了所有纯白色区域)。

根据我对Perlin噪声的了解,它应该是连续的。如果x或y是精确单位,则不会绘制这些线。

此外,在本教程的评论中,它还说返回的值绝不能超过[0,1]边界。显然是。这里发生了什么?并不是说我不喜欢这些模式或任何东西,而是我认为使用有效的Perlin噪声可能会得到类似的结果。

注意:图像是像素化的,因为我可能以最愚蠢和费解的方式生成图像。请不要抱怨。

<?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
?>

1 个答案:

答案 0 :(得分:1)

您在fade函数中翻转了一个符号。您有 6 + 15 ,该位置应为 6 {{1} } -

15

在完成更改后,我得到了

public static double fade(double t) {
    return t * t * t * (t * (t * 6 - 15) + 10);         // 6t^5 - 15t^4 + 10t^3
}
相关问题