I'm currently learning Löve 2d/Lua and trying my hand at generating noise using the Perlin Noise algorithm.
I've adapted Ken Perlin's Improved Noise code here:
Code edited with fixes per Doug's answer
-- 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
and here's my main.lua
Löve script:
require 'noise'
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
The problem I'm encountering is that rather than getting a nice image of pseudorandom squares, I'm getting some gradient-like bars like this:
I'm pretty stumped as to why I'm not getting the usual noise rendering.
EDIT: Here's the working rendering!
The advantages of simplex noise over Perlin noise: Simplex noise has lower computational complexity and requires fewer multiplications. Simplex noise scales to higher dimensions (4D, 5D) with much less computational cost: the complexity is. for.
Perlin noise is a popular procedural generation algorithm invented by Ken Perlin. It can be used to generate things like textures and terrain procedurally, meaning without them being manually made by an artist or designer. The algorithm can have 1 or more dimensions, which is basically the number of inputs it gets.
Gaussian noise is the closest match to the classic Perlin Noises from before Designer 2017 2.1, despite the name. See also the newer Perlin Noise for a newer, slightly different version of the classic.
To generate Perlin noise in one dimension, you associate a pseudo-random gradient (or slope) for the noise function with each integer coordinate, and set the function value at each integer coordinate to zero.
One problem:
local X = math.floor(x) and 255
local Y = math.floor(y) and 255
local Z = math.floor(z) and 255
should be
local X = math.floor(x) & 255
local Y = math.floor(y) & 255
local Z = math.floor(z) & 255
assuming you have Lua 5.3.x. If you have an earlier version of Lua, there are bitwise libraries that may or may not be available for Löve. So, in this case you can use:
local X = math.floor(x) % 256
local Y = math.floor(y) % 256
local Z = math.floor(z) % 256
Explanation: The conjunction operator and
returns its first argument if this value is false or nil; otherwise, and returns its second argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With