Refactored API to take amplitudes instead of resolution/decayFn.

This commit is contained in:
Bruce Hill 2017-06-19 15:35:26 -07:00
parent 48f9da8196
commit 98e741ab9e
2 changed files with 59 additions and 50 deletions

View File

@ -11,12 +11,13 @@ local function rng()
local r = love.math.newRandomGenerator(1)
return function() return r:random() end
end
local n1,g1 = Noise.make1d(8,rng(),decay)
local n2,g2 = Noise.make2d(9,rng(),decay)
local n3,g3 = Noise.make3d(11,rng(),decay)
local s1,s1g = Noise.make1dShader(9,rng(),decay)
local s2,s2g = Noise.make2dShader(13,rng(),decay)
local s3,s3g = Noise.make3dShader(17,rng(),decay)
local makeAmps = Noise.makeAmplitudes
local n1,g1 = Noise.make1d(makeAmps(8, decay), rng())
local n2,g2 = Noise.make2d(makeAmps(9, decay), rng())
local n3,g3 = Noise.make3d(makeAmps(11, decay), rng())
local s1,s1g = Noise.make1dShader(makeAmps(9, decay), rng())
local s2,s2g = Noise.make2dShader(makeAmps(13, decay), rng())
local s3,s3g = Noise.make3dShader(makeAmps(17, decay), rng())
local cw,ch = W/2,H/3
local canv = lg.newCanvas(cw,ch)

View File

@ -10,37 +10,44 @@ local function cdf_prime(x, dx)
return (0.31831 * exp(-2/PI * x*x) * abs(x)*dx)/sqrt(1-exp(-2/PI*x*x))
end
local function _defaultArgs(resolution,random,decayFn)
if not resolution then resolution = 4 end
local function _defaultArgs(amplitudes,random)
if amplitudes == nil then amplitudes = 5 end
if type(amplitudes) == 'number' then
amplitudes = noise.makeAmplitudes(amplitudes, function(x) return .1^x end)
end
if not random then random = math.random end
if not decayFn then decayFn = function(x) return .1^x end end
return resolution,random,decayFn
return amplitudes, random
end
local function _amplitudesAndOffsets(decayFn,numAmplitudes, numOffsets, random)
local function calculateSigma(amplitudes)
local sigma = 0
local amplitudes = {}
for i=1,numAmplitudes do
local a = decayFn((i-1+random())/numAmplitudes)
amplitudes[i] = a
assert(a > 0.0001)
sigma = sigma + a^2
for _,a in ipairs(amplitudes) do
sigma = sigma + a*a
end
sigma = math.sqrt(sigma/2)
return math.sqrt(sigma/2)
end
local function makeOffsets(count, random)
local offsets = {}
for i=1,numOffsets do
for i=1,count do
offsets[i] = random()*TAU
end
return amplitudes,sigma,offsets
return offsets
end
local function sign(x)
if x == 0 then return 0
elseif x < 0 then return -1 else return 1 end
noise.makeAmplitudes = function(count, fn)
local amplitudes = {}
for i=1,count do
amplitudes[i] = fn((i-.5)/count)
end
return amplitudes
end
noise.make1d = function(resolution,random,decayFn)
resolution,random,decayFn = _defaultArgs(resolution,random,decayFn)
local amplitudes,sigma,offsets = _amplitudesAndOffsets(decayFn,resolution,resolution,random)
noise.make1d = function(amplitudes,random)
amplitudes, random = _defaultArgs(amplitudes, random)
local resolution = #amplitudes
local sigma = calculateSigma(amplitudes)
local offsets = makeOffsets(#amplitudes, random)
local function noise(x)
local n = 0
for i,a in ipairs(amplitudes) do
@ -63,9 +70,11 @@ noise.make1d = function(resolution,random,decayFn)
return noise, gradient
end
noise.make2d = function(resolution,random,decayFn)
resolution,random,decayFn = _defaultArgs(resolution,random,decayFn)
local amplitudes,sigma,offsets = _amplitudesAndOffsets(decayFn,resolution,2*resolution,random)
noise.make2d = function(amplitudes, random)
amplitudes, random = _defaultArgs(amplitudes, random)
local resolution = #amplitudes
local sigma = calculateSigma(amplitudes)
local offsets = makeOffsets(2*#amplitudes, random)
sigma = sigma/sqrt(2)
local function noise(x,y)
local n = 0
@ -100,9 +109,11 @@ noise.make2d = function(resolution,random,decayFn)
return noise, gradient
end
noise.make3d = function(resolution,random,decayFn)
resolution,random,decayFn = _defaultArgs(resolution,random,decayFn)
local amplitudes,sigma,offsets = _amplitudesAndOffsets(decayFn,resolution,3*resolution,random)
noise.make3d = function(amplitudes, random)
amplitudes, random = _defaultArgs(amplitudes, random)
local resolution = #amplitudes
local sigma = calculateSigma(amplitudes)
local offsets = makeOffsets(3*#amplitudes, random)
sigma = sigma/sqrt(3)
local function noise(x,y,z)
-- Find the biggest fibonacci number F_n such that F_n < resolution
@ -228,15 +239,14 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
}
]]
noise.make1dShader = function(resolution,random,decayFn)
resolution,random,decayFn = _defaultArgs(resolution,random,decayFn)
if type(resolution) ~= 'number' or (resolution % 1 > 0) or (resolution <= 0) then
error("Resolution must be a positive integer.")
end
noise.make1dShader = function(amplitudes, random)
amplitudes, random = _defaultArgs(amplitudes, random)
local resolution = #amplitudes
local sigma = calculateSigma(amplitudes)
local offsets = makeOffsets(#amplitudes, random)
local shaderCode = "#define RESOLUTION "..tostring(resolution).."\n"..shader1d
local noiseShader = lg.newShader(shaderCode)
local gradShader = lg.newShader("#define GRADIENT\n"..shaderCode)
local amplitudes,sigma,offsets = _amplitudesAndOffsets(decayFn,resolution,resolution,random)
do -- Dumb hack to work around a bug in Love 0.10.2 not sending the last value
table.insert(amplitudes, 1.)
table.insert(offsets, 1.)
@ -299,15 +309,14 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
}
]]
noise.make2dShader = function(resolution,random,decayFn)
resolution,random,decayFn = _defaultArgs(resolution,random,decayFn)
if type(resolution) ~= 'number' or (resolution % 1 > 0) or (resolution <= 0) then
error("Resolution must be a positive integer.")
end
noise.make2dShader = function(amplitudes, random)
amplitudes, random = _defaultArgs(amplitudes, random)
local resolution = #amplitudes
local sigma = calculateSigma(amplitudes)
local offsets = makeOffsets(2*#amplitudes, random)
local shaderCode = "#define RESOLUTION "..tostring(resolution).."\n"..shader2d
local noiseShader = lg.newShader(shaderCode)
local gradShader = lg.newShader("#define GRADIENT\n"..shaderCode)
local amplitudes,sigma,offsets = _amplitudesAndOffsets(decayFn,resolution,2*resolution,random)
sigma = sigma/sqrt(2)
local offsets2 = {}
for i=1,#offsets-1,2 do
@ -405,15 +414,14 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
}
]]
noise.make3dShader = function(resolution,random,decayFn)
resolution,random,decayFn = _defaultArgs(resolution,random,decayFn)
if type(resolution) ~= 'number' or (resolution % 1 > 0) or (resolution <= 0) then
error("Resolution must be a positive integer.")
end
noise.make3dShader = function(amplitudes, random)
amplitudes, random = _defaultArgs(amplitudes, random)
local resolution = #amplitudes
local sigma = calculateSigma(amplitudes)
local offsets = makeOffsets(3*#amplitudes, random)
local shaderCode = "#define RESOLUTION "..tostring(resolution).."\n"..shader3d
local noiseShader = lg.newShader(shaderCode)
local gradShader = lg.newShader("#define GRADIENT\n"..shaderCode)
local amplitudes,sigma,offsets = _amplitudesAndOffsets(decayFn,resolution,3*resolution,random)
sigma = sigma/sqrt(3)
local offsets2 = {}
for i=1,#offsets-1,3 do