2015-10-29 2 views
3

В настоящее время я изучаю Löve 2d/Lua и пытаюсь изо всех сил генерировать шум с использованием алгоритма Perlin Noise.Lua - Perlin Noise Generation - Получение баров, а не квадратов

Я адаптированный улучшенного код Noise Кена Перлина здесь:

код отредактированного с исправлениями в ответ Дуги

-- original code by Ken Perlin: http://mrl.nyu.edu/~perlin/noise/ 

perlin = {} 
perlin.p = {} 
perlin.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,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 
} 
perlin.size = 256 
perlin.gx = {} 
perlin.gy = {} 
perlin.randMax = 256 

function perlin:load() 
    for i=1,self.size do 
     self.p[i] = self.permutation[i] 
     self.p[256+i] = self.p[i] 
    end 
end 

function perlin:noise(x, y, z) 
    local X = math.floor(x) % 256 
    local Y = math.floor(y) % 256 
    local Z = math.floor(z) % 256 
    x = x - math.floor(x) 
    y = y - math.floor(y) 
    z = z - math.floor(z) 
    local u = fade(x) 
    local v = fade(y) 
    local w = fade(z) 
    local A = self.p[X+1]+Y 
    local AA = self.p[A+1]+Z 
    local AB = self.p[A+2]+Z 
    local B = self.p[X+2]+Y 
    local BA = self.p[B+1]+Z 
    local BB = self.p[B+2]+Z 

    return lerp(w, lerp(v, lerp(u, grad(self.p[AA+1], x , y , z ), 
            grad(self.p[BA+1], x-1, y , z )), 
          lerp(u, grad(self.p[AB+1], x , y-1, z ), 
            grad(self.p[BB+1], x-1, y-1, z ))), 
        lerp(v, lerp(u, grad(self.p[AB+2], x , y , z-1), 
            grad(self.p[BA+2], x-1, y , z-1)), 
          lerp(u, grad(self.p[AB+2], x , y-1, z-1), 
            grad(self.p[BB+2], x-1, y-1, z-1)))) 
end 

function fade(t) 
    return t * t * t * (t * (t * 6 - 15) + 10) 
end 

function lerp(t, a, b) 
    return a + t * (b - a) 
end 

function grad(hash, x, y, z) 
    local h = hash % 16 
    local u = h < 8 and x or y 
    local v = h < 4 and y or ((h == 12 or h == 14) and x or z) 
    return ((h % 2) == 0 and u or -u) + ((h % 3) == 0 and v or -v) 
end 

и вот мой main.lua Леве сценарий:

требует 'шума'

function love.load() 
    perlin:load() 
    -- love.graphics.setBackgroundColor(255, 255, 255) 
    love.window.setMode(500, 500) 
end 

function love.update(dt) 

end 

function love.draw() 
    for i=1,500 do 
     for j=1,500 do 
      local x = perlin:noise(i/10, j/10, 0.3) 
      love.graphics.setColor(math.floor(x*255), math.floor(x*255), math.floor(x*255)) 
      love.graphics.rectangle("fill", 5*(i-1), 5*(j-1), 5, 5) 
     end 
    end 
end 

Проблемы Я сталкиваюсь что, а не получать хорошее изображение псевдослучайных квадратов, я получаю некоторые градиентные полосы, как это:

noise generated in Löve 2d

Я очень озадачен, почему я м, не получая обычного шума.

EDIT: Вот рабочий рендеринг!

working rendering of perlin noise

ответ

4

Одна проблема:

local X = math.floor(x) and 255 
local Y = math.floor(y) and 255 
local Z = math.floor(z) and 255 

должен быть

local X = math.floor(x) & 255 
local Y = math.floor(y) & 255 
local Z = math.floor(z) & 255 

если у вас есть Lua 5.3.x. Если у вас более ранняя версия Lua, есть побитовые библиотеки, которые могут или не могут быть доступны для Löve. Таким образом, в этом случае вы можете использовать:

local X = math.floor(x) % 256 
local Y = math.floor(y) % 256 
local Z = math.floor(z) % 256 

Объяснение: Оператор конъюнкции and возвращает свой первый аргумент, если это значение является ложным или ноль; в противном случае, и возвращает свой второй аргумент.

+0

спасибо, большое спасибо! Я просматривал документы Lua перед публикацией и не мог найти ничего о побитовых операциях, поэтому это было очень полезно при очистке! Тем более, что Love использует Lua 5.1, поэтому у меня нет доступа к 5.2 или 5.3, даже если бы я хотел. – GHandel

0

Вы используете and заменить & (побитовое и), я обновил свой пример ниже (с использованием метода BitAND от Lua - Bitwise Logical Operations), и заменили места, где вы использовали and, который включает в себя первоначальное заявление или X, Y, Z в perlin:load и декларации h в grad. Я тестировал его с помощью любви, и результат выглядит корректно.

-- original code by Ken Perlin: http://mrl.nyu.edu/~perlin/noise/ 
local function BitAND(a,b)--Bitwise and 
    local p,c=1,0 
    while a>0 and b>0 do 
     local ra,rb=a%2,b%2 
     if ra+rb>1 then c=c+p end 
     a,b,p=(a-ra)/2,(b-rb)/2,p*2 
    end 
    return c 
end 

perlin = {} 
perlin.p = {} 
perlin.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,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 
} 
perlin.size = 256 
perlin.gx = {} 
perlin.gy = {} 
perlin.randMax = 256 

function perlin:load() 
    for i=1,self.size do 
     self.p[i] = self.permutation[i] 
     self.p[255+i] = self.p[i] 
    end 
end 

function perlin:noise(x, y, z) 
    local X = BitAND(math.floor(x), 255) + 1 
    local Y = BitAND(math.floor(y), 255) + 1 
    local Z = BitAND(math.floor(z), 255) + 1 

    x = x - math.floor(x) 
    y = y - math.floor(y) 
    z = z - math.floor(z) 
    local u = fade(x) 
    local v = fade(y) 
    local w = fade(z) 
    local A = self.p[X]+Y 
    local AA = self.p[A]+Z 
    local AB = self.p[A+1]+Z 
    local B = self.p[X+1]+Y 
    local BA = self.p[B]+Z 
    local BB = self.p[B+1]+Z 

    return lerp(w, lerp(v, lerp(u, grad(self.p[AA ], x , y , z ), 
            grad(self.p[BA ], x-1, y , z )), 
          lerp(u, grad(self.p[AB ], x , y-1, z ), 
            grad(self.p[BB ], x-1, y-1, z ))), 
        lerp(v, lerp(u, grad(self.p[AA+1], x , y , z-1), 
            grad(self.p[BA+1], x-1, y , z-1)), 
          lerp(u, grad(self.p[AB+1], x , y-1, z-1), 
            grad(self.p[BB+1], x-1, y-1, z-1)))) 
end 


function fade(t) 
    return t * t * t * (t * (t * 6 - 15) + 10) 
end 

function lerp(t, a, b) 
    return a + t * (b - a) 
end 

function grad(hash, x, y, z) 
    local h = BitAND(hash, 15) 
    local u = h < 8 and x or y 
    local v = h < 4 and y or ((h == 12 or h == 14) and x or z) 
    return ((h and 1) == 0 and u or -u) + ((h and 2) == 0 and v or -v) 
end 
Смежные вопросы