如何在 Lua 中生成平铺 Perlin 噪声?

目前我只有一堆乱七八糟的代码:http://pastebin.com/F9Dc7pbR

它既不平铺,也不好看(由于声望问题,我无法发布它,你只能相信我的话)。

我还找到了这个可以平铺的噪声示例代码:http://pastebin.com/cmuTBSJY

但我不能使用它,因为我不知道 Python 或者它如何转换成 lua。有什么想法吗?

编辑:澄清一下,它需要能够在 X 和 Y 轴上包裹回来并触摸自己。

点赞
用户1793220
用户1793220

以下是原问题中的 Python 代码转换成 Lua 的版本。它生成平铺噪声:

-- 创建 256 个打乱的数
local perm = {}
for i = 1, 256 do
   table.insert(perm, math.random(#perm + 1), i)
end

-- 重复列表
for i = 1, 256 do
   perm[i+256] = perm[i]
end

-- 生成 256 个方向
local dirs = {}
for a = 0, 255 do
   table.insert(dirs, { math.cos(a * 2.0 * math.pi / 256),
                        math.sin(a * 2.0 * math.pi / 256) })
end

local function noise(x, y, per)
   local function surflet(grid_x, grid_y)
      local dist_x, dist_y = math.abs(x - grid_x), math.abs(y - grid_y)
      local poly_x = 1 - 6 * dist_x ^ 5 + 15 * dist_x ^ 4 - 10 * dist_x ^ 3
      local poly_y = 1 - 6 * dist_y ^ 5 + 15 * dist_y ^ 4 - 10 * dist_y ^ 3
      local hashed = perm[(perm[(math.floor(grid_x) % per) + 1] + math.floor(grid_y) % per) + 1]
      local grad = (x - grid_x)  * dirs[hashed][1] + (y - grid_y) * dirs[hashed][2]
      return poly_x * poly_y * grad
   end
   local int_x, int_y = math.floor(x), math.floor(y)
   return surflet(int_x+0, int_y+0) + surflet(int_x+1, int_y+0) +
          surflet(int_x+0, int_y+1) + surflet(int_x+1, int_y+1)
end

local function fBm(x, y, per, octs)
   local val = 0
   for o = 0, octs - 1 do
      val = val + (0.5 ^ o * noise(x * 2 ^ o, y * 2 ^ o, per * 2 ^ o))
   end
   return val
end

local size, freq, octs = 128, 1/32.0, 5

-- 生成 128x128 的数据点
local data = {}
for y = 1, size do
   local line = {}
   for x = 1, size do
      table.insert(line, math.floor((fBm(x*freq, y*freq, math.floor(size*freq), octs) + 1) * 128))
   end
   table.insert(data, line)
end

-- 为了演示,我们生成一个 PGM 文件,
-- 很容易转换成 PNG 文件。
local out = { "P2", "128 128", "255" }
for y = 1, size do
   local line = {}
   for x = 1, size do
      table.insert(line, tostring(data[y][x]))
   end
   table.insert(out, table.concat(line, " "))
end
local pgm_data = table.concat(out, "\n") .. "\n"

-- 现在我们使用 ImageMagick 把它转换成 PNG。

-- 我们将尝试本地使用 https://github.com/leafo/magick
-- 要使用它,请使用 `luarocks install magick` 安装它,
-- 并用 `luajit` 运行此脚本。
local ok, magick = pcall(require, "magick")
if ok then
   local im = magick.load_image_from_blob(pgm_data)
   im:set_format("pgm")
   im:write("noise.png")
else
   -- 如果我们没有该库,则只需从命令行调用 ImageMagick。
   local fd = io.open("noise.pgm", "w")
   fd:write(pgm_data)
   fd:close()
   os.execute("convert noise.pgm noise.png")
end
2017-03-01 22:26:41