Hey, I've recently been working on a module for Simplex Noise and Gaussian Bluring (so the noise looks a bit better), but aren't sure weather either of the two is actually working, since I've never seen either in such a raw unedited state before.
My Module:
[lua]
-----------------------------------------------
---Simplex Noise Module, Translated by Levybreak
--Original Source: [url]http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf[/url]
--(The code there is in java)
--Just as a note, there's a fuckton of math in here. Don't try and calculate this shit real time.
--Get lanes and prcess it in a seperate thread. Please. Really.
-----------------------------------------------
local math = math
local table = table
local string = string
local tonumber = tonumber
local tostring = tostring
local ipairs = ipairs
--local print = print
--local debug = debug
module("SimplexNoise")
local Gradients3D = {{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}};
local Gradients4D = {{0,1,1,1}, {0,1,1,-1}, {0,1,-1,1}, {0,1,-1,-1},
{0,-1,1,1}, {0,-1,1,-1}, {0,-1,-1,1}, {0,-1,-1,-1},
{1,0,1,1}, {1,0,1,-1}, {1,0,-1,1}, {1,0,-1,-1},
{-1,0,1,1}, {-1,0,1,-1}, {-1,0,-1,1}, {-1,0,-1,-1},
{1,1,0,1}, {1,1,0,-1}, {1,-1,0,1}, {1,-1,0,-1},
{-1,1,0,1}, {-1,1,0,-1}, {-1,-1,0,1}, {-1,-1,0,-1},
{1,1,1,0}, {1,1,-1,0}, {1,-1,1,0}, {1,-1,-1,0},
{-1,1,1,0}, {-1,1,-1,0}, {-1,-1,1,0}, {-1,-1,-1,0}};
local p = {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};
-- To remove the need for index wrapping, double the permutation table length
for i=1,#p do
p[i-1] = p[i]
p[i] = nil
end
for i=1,#Gradients3D do
Gradients3D[i-1] = Gradients3D[i]
Gradients3D[i] = nil
end
for i=1,#Gradients4D do
Gradients4D[i-1] = Gradients4D[i]
Gradients4D[i] = nil
end
local perm = {}
for i=0,255 do
perm[i] = p[i]
perm[i+256] = p[i]
end
-- A lookup table to traverse the simplex around a given point in 4D.
-- Details can be found where this table is used, in the 4D noise method.
local simplex = {
{0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0},
{0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
{1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0},
{1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
{2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0},
{2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}};
local function Dot2D(tbl, x, y)
return tbl[1]*x + tbl[2]*y;
end
local function Dot3D(tbl, x, y, z)
return tbl[1]*x + tbl[2]*y + tbl[3]*z
end
local function Dot4D( tbl, x,y,z,w)
return tbl[1]*x + tbl[2]*y + tbl[3]*z + tbl[3]*w;
end
local function SomeBitwiseShit(arg1,arg2)
return arg1 & arg2
end
local Prev2D = {}
-- 2D simplex noise
function Noise2D(xin, yin)
if Prev2D[xin] and Prev2D[xin][yin] then return Prev2D[xin][yin] end
local n0, n1, n2; -- Noise contributions from the three corners
-- Skew the input space to determine which simplex cell we're in
local F2 = 0.5*(math.sqrt(3.0)-1.0);
local s = (xin+yin)*F2; -- Hairy factor for 2D
local i = math.floor(xin+s);
local j = math.floor(yin+s);
local G2 = (3.0-math.sqrt(3.0))/6.0;
local t = (i+j)*G2;
local X0 = i-t; -- Unskew the cell origin back to (x,y) space
local Y0 = j-t;
local x0 = xin-X0; -- The x,y distances from the cell origin
local y0 = yin-Y0;
-- For the 2D case, the simplex shape is an equilateral triangle.
-- Determine which simplex we are in.
local i1, j1; -- Offsets for second (middle) corner of simplex in (i,j) coords
if(x0>y0) then
i1=1
j1=0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
else
i1=0
j1=1 -- upper triangle, YX order: (0,0)->(0,1)->(1,1)
end
-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
-- c = (3-sqrt(3))/6
local x1 = x0 - i1 + G2; -- Offsets for middle corner in (x,y) unskewed coords
local y1 = y0 - j1 + G2;
local x2 = x0 - 1.0 + 2.0 * G2; -- Offsets for last corner in (x,y) unskewed coords
local y2 = y0 - 1.0 + 2.0 * G2;
-- Work out the hashed gradient indices of the three simplex corners
local ii = SomeBitwiseShit(i , 255)
local jj = SomeBitwiseShit(j , 255)
local gi0 = perm[ii+perm[jj]] % 12;
local gi1 = perm[ii+i1+perm[jj+j1]] % 12;
local gi2 = perm[ii+1+perm[jj+1]] % 12;
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0*x0-y0*y0;
if t0<0 then
n0 = 0.0;
else
t0 = t0 * t0
n0 = t0 * t0 * Dot2D(Gradients3D[gi0], x0, y0); -- (x,y) of Gradients3D used for 2D gradient
end
local t1 = 0.5 - x1*x1-y1*y1;
if (t1<0) then
n1 = 0.0;
else
t1 = t1*t1
n1 = t1 * t1 * Dot2D(Gradients3D[gi1], x1, y1);
end
local t2 = 0.5 - x2*x2-y2*y2;
if (t2<0) then
n2 = 0.0;
else
t2 = t2*t2
n2 = t2 * t2 * Dot2D(Gradients3D[gi2], x2, y2);
end
-- Add contributions from each corner to get the final noise value.
-- The result is scaled to return values in the localerval [-1,1].
local retval = 70.0 * (n0 + n1 + n2)
if not Prev2D[xin] then Prev2D[xin] = {} end
Prev2D[xin][yin] = retval
return retval;
end
local Prev3D = {}
-- 3D simplex noise
function Noise3D(vecIn)
local xin = vecIn.x
local yin = vecIn.y
local zin = vecIn.z
if Prev3D[xin] and Prev3D[xin][yin] and Prev3D[xin][yin][zin] then return Prev3D[xin][yin][zin] end
local n0, n1, n2, n3; -- Noise contributions from the four corners
-- Skew the input space to determine which simplex cell we're in
local F3 = 1.0/3.0;
local s = (xin+yin+zin)*F3; -- Very nice and simple skew factor for 3D
local i = math.floor(xin+s);
local j = math.floor(yin+s);
local k = math.floor(zin+s);
local G3 = 1.0/6.0; -- Very nice and simple unskew factor, too
local t = (i+j+k)*G3;
local X0 = i-t; -- Unskew the cell origin back to (x,y,z) space
local Y0 = j-t;
local Z0 = k-t;
local x0 = xin-X0; -- The x,y,z distances from the cell origin
local y0 = yin-Y0;
local z0 = zin-Z0;
-- For the 3D case, the simplex shape is a slightly irregular tetrahedron.
-- Determine which simplex we are in.
local i1, j1, k1; -- Offsets for second corner of simplex in (i,j,k) coords
local i2, j2, k2; -- Offsets for third corner of simplex in (i,j,k) coords
if (x0>=y0) then
if (y0>=z0) then
i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; -- X Y Z order
elseif (x0>=z0) then
i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; -- X Z Y order
else
i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; -- Z X Y order
end
else -- x0<y0
if (y0<z0) then
i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; -- Z Y X order
elseif (x0<z0) then
i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; -- Y Z X order
else
i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; -- Y X Z order
end
end
-- A step of (1,0,0) in (i,
I'm blinded by code. Could you show us some actually working pictures? As much as I'd love to go though and read all this code...
Well, I think it'd be best If I took a video, probably, since some of my tests are animated.
[QUOTE=Levybreak;17887557]Well, I think it'd be best If I took a video, probably, since some of my tests are animated.[/QUOTE]
Dying to see a video
[url]http://www.wegame.com/watch/Simplex_Noise_Test/[/url]
I'm working on a second test with the noise at a different scale and in a larger area, but garry's infinite loop detection keeps going off because of the huge amount of math that needs to be done for each pixel. (Even if it is only done once)
[editline]10:10PM[/editline]
[url]http://www.wegame.com/watch/Simplex_Noise_Test_2/[/url]
That took a fucking long ass time to be computed.
[editline]11:16PM[/editline]
[url]http://www.wegame.com/watch/Simplex_Noise_Test_3/[/url]
Test number 3. Code used:
[lua]
require("SimplexNoise")
concommand.Add("SimplexNoise2DTest",function(ply,cmd,arg)
local tbl = {}
local loopnum = -1
hook.Add("Think","MassivelyCool",function()
loopnum = loopnum+1
for colum=1,32 do
local i = (32*loopnum)+colum
if not tbl[i] then tbl[i] = {} end
for ii=1,256 do
local num = SimplexNoise.Noise2D(i/10,ii/10)
num = num+1
num = num*128
tbl[i][ii] = num
end
end
if loopnum >= 8 then hook.Remove("Think","MassivelyCool") end
end)
hook.Add("HUDPaint","SimplexTest",function()
for i=1,256 do
if not tbl[i] then tbl[i] = {} end
for ii=1,256 do
if not tbl[i][ii] then tbl[i][ii] = 255 end
local num = tbl[i][ii]
surface.SetDrawColor(num,num,num,255)
surface.DrawRect(i,ii,1,1)
end
end
end)
end)
concommand.Add("SimplexNoise3DTest",function(ply,cmd,arg)
--[[local frameNum = 0
local VecTbl = {}
for i=1,64 do
VecTbl[i] = {}
for ii=1,64 do
VecTbl[i][ii] = Vector(i/10,ii/10,0)
end
end]]
local VecTbl = {}
local frame = 0
local num = 0
local i = 1
hook.Add("Think","MassivelyCool",function()
num = num + 1
i = math.ceil(num)
frame = frame+1
if frame > 10 then frame = 1 end
if not VecTbl[i] then VecTbl[i] = {} end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
frame = frame+1
if frame > 10 then frame = 1 end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
local num = SimplexNoise.Noise3D(Vector(i/10,ii/10,frame/10))
num = num+1
num = num*128
if not VecTbl[i][ii][frame] then VecTbl[i][ii][frame] = {} end
VecTbl[i][ii][frame] = num
end
if num >= 256 then hook.Remove("Think","MassivelyCool") end
end)
local playFrame = 0
hook.Add("HUDPaint","SimplexTest",function()
playFrame = playFrame + 1
if playFrame > 10 then playFrame = 1 end
for i=1,256 do
if not VecTbl[i] then VecTbl[i] = {} end
for ii=1,256 do
if not VecTbl[i][ii] then VecTbl[i][ii] = {} end
if not VecTbl[i][ii][playFrame] then VecTbl[i][ii][playFrame] = 255 end
local num = VecTbl[i][ii][playFrame]
surface.SetDrawColor(num,num,num,255)
surface.DrawRect(i,ii,1,1)
end
end
end)
end)
concommand.Add("SimplexNoise4DTest",function(ply,cmd,arg)
local VecTbl = {}
for i=1,75 do
VecTbl[i] = {}
for ii=1,75 do
VecTbl[i][ii] = Vector(i/20,ii/20,0)
end
end
hook.Add("HUDPaint","SimplexTest",function()
for i=1,75 do
for ii=1,75 do
VecTbl[i][ii].z = math.floor(ply:GetPos().x)/20
local num = SimplexNoise.Noise4D(VecTbl[i][ii],math.floor(ply:GetPos().y)/20)
num = num+1
num = num*128
surface.SetDrawColor(num,num,num,255)
surface.DrawRect(i,ii,1,1)
end
end
end)
end)
--Blur Testing Stuff follows. I'm not sure as to weather it actually works or not......meh.
local function Average(...)
local ret = 0
for k,v in ipairs({...}) do
ret = ret + v
end
return ret/#{...}
end
local function StandardDevitation(...)
local ret = 0
local avg = Average(...)
for k,v in ipairs({...}) do
ret = ret + (v-avg)^2
end
local maxs = #{...}
return math.sqrt(ret/maxs)
end
local function GetValuesWithin(tbl,n,cx,cy,mins,maxs)
local ret = {}
local val = math.Round(n/2)
for i=math.Clamp(cx-val,mins,maxs),math.Clamp(cx+val,mins,maxs) do
for ii=math.Clamp(cy-val,mins,maxs),math.Clamp(cy+val,mins,maxs) do
table.insert(ret,tbl[i][ii])
end
end
return unpack(ret)
end
local function DoThatShit(tbl,ntbl)
local loopnum = -1
hook.Add("Think","AnotherOneRioght",function()
loopnum = loopnum+1
for colum=1,32 do
local i = (loopnum*32)+colum
if not ntbl[i] then ntbl[i] = {} end
for ii=1,256 do
local dev = StandardDevitation(GetValuesWithin(tbl,4,i,ii,1,256))
ntbl[i][ii] = tbl[i][ii]-SimplexNoise.GBlur1D(i,dev)
ntbl[i][ii] = ntbl[i][ii]-SimplexNoise.GBlur1D(ii,dev)
end
end
if loopnum >= 8 then
hook.Remove("Think","AnotherOneRioght")
end
end)
end
concommand.Add("SimplexNoise2DBlurTest",function(ply,cmd,arg)
local tbl = {}
local ntbl = {}
local loopnum = -1
hook.Add("Think","MassivelyCool",function()
loopnum = loopnum+1
for colum=1,32 do
local i = (32*loopnum)+colum
if not tbl[i] then tbl[i] = {} end
for ii=1,256 do
local num = SimplexNoise.Noise2D(i/10,ii/10)
num = num+1
num = num*128
tbl[i][ii] = num
end
end
if loopnum >= 8 then
DoThatShit(tbl,ntbl)
hook.Remove("Think","MassivelyCool")
end
end)
hook.Add("HUDPaint","SimplexTest",function()
for i=1,256 do
if not ntbl[i] then ntbl[i] = {} end
for ii=1,256 do
if not ntbl[i][ii] then ntbl[i][ii] = 255 end
local num = ntbl[i][ii]
surface.SetDrawColor(num,num,num,255)
surface.DrawRect(i,ii,1,1)
end
end
end)
end)
[/lua]
When these types of things come out, I can not for the life of me conceptualize one practical usage for them. The only thing that comes to mind is TV static, in 2d3d space, but that's it.
Can anyone beat me to a useful concept?
2-3 fps at the video? :l
[QUOTE=The-Stone;17895268]2-3 fps at the video? :l[/QUOTE]
it's not much higher than that for me to begin with. Calculating the noise chops it in half, and then the recording doesn't help too much either. As I said, for the love of god, don't calculate this shit in the main thread unless you have to.
[editline]11:02AM[/editline]
[QUOTE=CptFuzzies;17892085]When these types of things come out, I can not for the life of me conceptualize one practical usage for them. The only thing that comes to mind is TV static, in 2d3d space, but that's it.
Can anyone beat me to a useful concept?[/QUOTE]
It can be useful for adding cohesive randomness to effects and such, and generating procedural textures.
And adding random turbulence to something, once I add in the turbulence effect to the noise.
[editline]11:05AM[/editline]
I'd also like to add the the module itself is vanilla lua (aside form the bitwise &... you'd need to download LuaBit or the like for that), so it could be used for non-gmod purposes.
[editline]11:32AM[/editline]
[url]http://www.noisemachine.com/talk1/index.html[/url]
Has alot of information on how noise ise useful, though.
[editline]11:58AM[/editline]
[url]http://www.wegame.com/watch/Turbulent_Simplex_Noise/[/url]
Turbulence. :D
math.Rand and math.random are your friends, but I love Gaussian stuff. I'll ponder through the libraries within my mind and find some inspiration to use this.
The main point is that if you send it the same values, it produces the same output.
Sorry, you need to Log In to post a reply to this thread.