Реализация алгоритма шума Перлина - PullRequest
0 голосов
/ 07 января 2019

У меня возникли проблемы с реализацией алгоритма перлин-шума, подробно описанного ниже. Алгоритм производит вывод, который явно неверен, демонстрируя мозаику вдоль линий сетки и градиентов, которые на самом деле не выглядят случайными вообще.

Perlin()
for(var/x = origin_x, x < limit_x, x++)
     for(var/y = origin_y, y < limit_y, y++)
        OctavePerlin(x/scale, y/scale, 1, octaves, virility)

/proc/OctavePerlin(var/x, var/y, var/z, var/octaves, var/persistence)
 var/total = 0
 var/frequency = 1
 var/amplitude = 1
 var/maxValue = 0           // Used for normalizing result to 0.0 - 1.0
 for(var/i = 0; i < octaves; i++)
    total += perlin(x * frequency, y * frequency, z * frequency) * amplitude

     maxValue += amplitude

     amplitude *= persistence
     frequency *= 2

 return total/maxValue

 var/list/perlin_permutation = list(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 )

var/perlin_p[512]

/proc/Perlin()
 for(var/x = 1; x <= 512; x++)
     perlin_p[x] = perlin_permutation[x % 256]

/proc/perlin(var/x, var/y, var/z) 

 var/xi = x & 255
 var/yi = y & 255
 var/zi = z & 255
 var/xf = x - round(x)
 var/yf = y - round(y)
 var/zf = z - round(z)
 var/u = fade(xf)
 var/v = fade(yf)
 var/w = fade(zf)

 var/aaa = perlin_p[perlin_p[perlin_p[    xi ]+    yi ]+    zi ]
 var/aba = perlin_p[perlin_p[perlin_p[    xi ]+(yi++)]+    zi ]
 var/aab = perlin_p[perlin_p[perlin_p[    xi ]+    yi ]+(zi++)]
 var/abb = perlin_p[perlin_p[perlin_p[    xi ]+(yi++)]+(zi++)]
 var/baa = perlin_p[perlin_p[perlin_p[(xi++)]+    yi ]+    zi ]
 var/bba = perlin_p[perlin_p[perlin_p[(xi++)]+(yi++)]+    zi ]
 var/bab = perlin_p[perlin_p[perlin_p[(xi++)]+    yi ]+(zi++)]
 var/bbb = perlin_p[perlin_p[perlin_p[(xi++)]+(yi++)]+(zi++)]

 var/x1 = lerp(grad (aaa, xf  , yf  , zf),
            grad (baa, xf-1, yf  , zf),
            u)

 var/x2 = lerp(grad (aba, xf  , yf-1, zf),
            grad (bba, xf-1, yf-1, zf),
            u)

 var/y1 = lerp(x1, x2, v)

 x1 = lerp(grad (aab, xf  , yf  , zf-1),
            grad (bab, xf-1, yf  , zf-1),
            u)
 x2 = lerp(grad (abb, xf  , yf-1, zf-1),
            grad (bbb, xf-1, yf-1, zf-1),
            u)

 var/y2 = lerp (x1, x2, v)

 return (lerp (y1, y2, w)+1)/2

/proc/grad(var/hash, var/x, var/y, var/z)

 switch(hash & 0xF)

     if (0x0)
        return  x + y
     if (0x1)
        return -x + y
     if (0x2)
        return  x - y
     if (0x3)
        return -x - y
     if (0x4)
        return  x + z
     if (0x5)
        return -x + z
     if (0x6)
        return  x - z
     if (0x7)
        return -x - z
     if (0x8)
        return  y + z
     if (0x9)
        return -y + z
     if (0xA)
        return  y - z
     if (0xB)
        return -y - z
     if (0xC)
        return  y + x
     if (0xD)
        return -y + z
     if (0xE)
        return  y - x
     if (0xF)
        return -y - z
     else
        return 0 // never happens

/proc/fade(var/t)
 return t * t * t * (t * (t * 6 - 15) + 10)

/proc/lerp(var/a, var/b, var/x)
 return a + x * (b - a)

Вывод этого вывода вместо карты шума перлина: Неправильный вывод, показывающий мозаику вдоль линий сетки

Этот код выше получен из модели, установленной этим кодом ниже; https://gist.github.com/Flafla2/f0260a861be0ebdeef76

...