Simple Noise 1D,2D and 3D

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Simple Noise 1D,2D and 3D

Post by D.J.Peters »

file: simplenoise.bi

Code: Select all

#ifndef __SIMPLENOISE_BI__
#define __SIMPLENOISE_BI__
const as integer NOIZESIZE = 255

dim shared as single noise(NOIZESIZE,NOIZESIZE,NOIZESIZE)

sub init constructor
  randomize timer
  for x as integer=0 to NOIZESIZE
    for y as integer = 0 to NOIZESIZE
      for z as integer = 0 to NOIZESIZE
        noise(x,y,z)=rnd()
      next  
    next
  next
end sub  


function smoothNoise1d(x as single) as single
  x=abs(x)
  dim as integer iX1=int(x)
  dim as integer iX2=ix1+1
  dim as single tx=x-iX1
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  dim as single l=noise(iX1,0,0)
  dim as single r=noise(iX2,0,0)
  dim as single v=l + (r-l)*tx
  return v
end function

function smoothNoise2d(x as single, y as single) as single
  x=abs(x)
  y=abs(y)
  dim as integer iX1=int(x)
  dim as integer iY1=int(y)
  dim as integer iX2=ix1+1
  dim as integer iY2=iy1+1
  dim as single tx=x-iX1
  dim as single ty=y-iY1
  
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  iY1 and= NOIZESIZE
  iY2 and= NOIZESIZE
  
  dim as single lt=noise(iX1,iY1,0)
  dim as single rt=noise(iX2,iY1,0)
  dim as single rb=noise(iX2,iY2,0)
  dim as single lb=noise(iX1,iY2,0)
  
  dim as single sxt=lt + (rt-lt)*tx
  dim as single sxb=lb + (rb-lb)*tx
  
  dim as single v=sxt+(sxb-sxt)*ty
  return v
end function

function smoothNoise3d(x as single, y as single, z as single) as single
  x=abs(x)
  y=abs(y)
  z=abs(z)
  dim as integer iX1=int(x)
  dim as integer iY1=int(y)
  dim as integer iZ1=int(z)
  dim as integer iX2=ix1+1
  dim as integer iY2=iy1+1
  dim as integer iZ2=iz1+1
  dim as single tx=x-iX1
  dim as single ty=y-iY1
  dim as single tz=z-iZ1
  
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  iY1 and= NOIZESIZE
  iY2 and= NOIZESIZE
  iZ1 and= NOIZESIZE
  iZ2 and= NOIZESIZE
  
  dim as single ltf=noise(iX1,iY1,iZ1)
  dim as single rtf=noise(iX2,iY1,iZ1)
  dim as single rbf=noise(iX2,iY2,iZ1)
  dim as single lbf=noise(iX1,iY2,iZ1)
  dim as single sxtf=ltf + (rtf-ltf)*tx
  dim as single sxbf=lbf + (rbf-lbf)*tx
  
  dim as single ltb=noise(iX1,iY1,iZ2)
  dim as single rtb=noise(iX2,iY1,iZ2)
  dim as single rbb=noise(iX2,iY2,iZ2)
  dim as single lbb=noise(iX1,iY2,iZ2)
  dim as single sxtb = ltb + (rtb-ltb)*tx
  dim as single sxbb = lbb + (rbb-lbb)*tx
  
  dim as single vf = sxtf+(sxbf-sxtf)*ty
  dim as single vb = sxtb+(sxbb-sxtb)*ty
  dim as single v = vf + (vb-vf)*tz
   
  return v
end function

function turbulence1d(x as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  while(size >= 1)
    value += smoothNoise1d(x / size) * size
    size /= 2.0
  wend
  value*=0.5
  return value/initialSize
end function

function turbulence2d(x as single, y as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  while(size >= 1)
    value += smoothNoise2d(x / size, y / size) * size
    size /= 2.0
  wend
  value*=0.5
  return value/(initialSize-1)
end function

function turbulence3d(x as single, y as single, z as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  while(size >= 1)
    value += smoothNoise3d(x / size, y / size, z/size) * size
    size /= 2.0
  wend
  value*=0.5
  return value/(initialSize-1)
end function

#endif ' __SIMPLENOISE_BI__
file: test2d.bas

Code: Select all

#include once "simplenoise.bi"

screenres NOIZESIZE,NOIZESIZE,8,2
screenset 1,0
for i as integer = 0 to 255
  palette i,i,i,i
next

do
  for t as integer=1 to 256 step 4
    windowtitle "turbul. 2d: " & t
    for x as integer=0 to NOIZESIZE
      for y as integer=0 to NOIZESIZE
        pset (x,y),int( 255*turbulence2d(x,y,t) )
      next
    next
    flip
    sleep 20
    if inkey()<>"" then end
  next

  for t as integer=256 to 1 step 4
    windowtitle "turbul. 2d: " & t
    for x as integer=0 to NOIZESIZE
      for y as integer=0 to NOIZESIZE
        pset (x,y),int( 255*turbulence2d(x,y,t) )
      next
    next
    flip
    sleep 20
    if inkey()<>"" then end
  next
loop
file: test3d.bas

Code: Select all

#include once "simplenoise.bi"

screenres NOIZESIZE,NOIZESIZE,8,2
screenset 1,0
for i as integer = 0 to 255
  palette i,i,i,i
next

do

  for t as integer=256 to 16 step -16   
    windowtitle "turbul. 3d: " & t
    for z as integer=0 to NOIZESIZE
      for x as integer=0 to NOIZESIZE
        for y as integer=0 to NOIZESIZE
          pset (x,y),int( 255*turbulence3d(x,y,z,t) )
        next
      next
      flip
      sleep 20
      if inkey()<>"" then end
    next
  next

  for t as integer=16 to 256 step 16   
    windowtitle "turbul. 3d: " & t
    for z as integer=0 to NOIZESIZE
      for x as integer=0 to NOIZESIZE
        for y as integer=0 to NOIZESIZE
          pset (x,y),int( 255*turbulence3d(x,y,z,t) )
        next
      next
      flip
      sleep 20
      if inkey()<>"" then end
    next
  next
loop
apimpnamedshane
Posts: 2
Joined: Jun 02, 2020 19:27

Re: Simple Noise 1D,2D and 3D

Post by apimpnamedshane »

Is there a simple way to make the height map from the 2d function tileable? I'm trying to make a procedurally generated open world.
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Simple Noise 1D,2D and 3D

Post by badidea »

What do you mean with "tileable"?
That left / right and top / bottom fit seamless? That seems to be the case already
See this example (.bi and .bas files combined and reduced "noizesize" to better see the borders / edges):

Code: Select all

const as integer NOIZESIZE = 15 '255

dim shared as single noise(NOIZESIZE,NOIZESIZE,NOIZESIZE)

sub init constructor
  randomize timer
  for x as integer=0 to NOIZESIZE
    for y as integer = 0 to NOIZESIZE
      for z as integer = 0 to NOIZESIZE
        noise(x,y,z)=rnd()
      next 
    next
  next
end sub 

function smoothNoise1d(x as single) as single
  x=abs(x)
  dim as integer iX1=int(x)
  dim as integer iX2=ix1+1
  dim as single tx=x-iX1
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  dim as single l=noise(iX1,0,0)
  dim as single r=noise(iX2,0,0)
  dim as single v=l + (r-l)*tx
  return v
end function

function smoothNoise2d(x as single, y as single) as single
  x=abs(x)
  y=abs(y)
  dim as integer iX1=int(x)
  dim as integer iY1=int(y)
  dim as integer iX2=ix1+1
  dim as integer iY2=iy1+1
  dim as single tx=x-iX1
  dim as single ty=y-iY1
 
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  iY1 and= NOIZESIZE
  iY2 and= NOIZESIZE
 
  dim as single lt=noise(iX1,iY1,0)
  dim as single rt=noise(iX2,iY1,0)
  dim as single rb=noise(iX2,iY2,0)
  dim as single lb=noise(iX1,iY2,0)
 
  dim as single sxt=lt + (rt-lt)*tx
  dim as single sxb=lb + (rb-lb)*tx
 
  dim as single v=sxt+(sxb-sxt)*ty
  return v
end function

function smoothNoise3d(x as single, y as single, z as single) as single
  x=abs(x)
  y=abs(y)
  z=abs(z)
  dim as integer iX1=int(x)
  dim as integer iY1=int(y)
  dim as integer iZ1=int(z)
  dim as integer iX2=ix1+1
  dim as integer iY2=iy1+1
  dim as integer iZ2=iz1+1
  dim as single tx=x-iX1
  dim as single ty=y-iY1
  dim as single tz=z-iZ1
 
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  iY1 and= NOIZESIZE
  iY2 and= NOIZESIZE
  iZ1 and= NOIZESIZE
  iZ2 and= NOIZESIZE
 
  dim as single ltf=noise(iX1,iY1,iZ1)
  dim as single rtf=noise(iX2,iY1,iZ1)
  dim as single rbf=noise(iX2,iY2,iZ1)
  dim as single lbf=noise(iX1,iY2,iZ1)
  dim as single sxtf=ltf + (rtf-ltf)*tx
  dim as single sxbf=lbf + (rbf-lbf)*tx
 
  dim as single ltb=noise(iX1,iY1,iZ2)
  dim as single rtb=noise(iX2,iY1,iZ2)
  dim as single rbb=noise(iX2,iY2,iZ2)
  dim as single lbb=noise(iX1,iY2,iZ2)
  dim as single sxtb = ltb + (rtb-ltb)*tx
  dim as single sxbb = lbb + (rbb-lbb)*tx
 
  dim as single vf = sxtf+(sxbf-sxtf)*ty
  dim as single vb = sxtb+(sxbb-sxtb)*ty
  dim as single v = vf + (vb-vf)*tz
   
  return v
end function

function turbulence1d(x as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  while(size >= 1)
    value += smoothNoise1d(x / size) * size
    size /= 2.0
  wend
  value*=0.5
  return value/initialSize
end function

function turbulence2d(x as single, y as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  while(size >= 1)
    value += smoothNoise2d(x / size, y / size) * size
    size /= 2.0
  wend
  value*=0.5
  return value/(initialSize-1)
end function

function turbulence3d(x as single, y as single, z as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  while(size >= 1)
    value += smoothNoise3d(x / size, y / size, z/size) * size
    size /= 2.0
  wend
  value*=0.5
  return value/(initialSize-1)
end function

const SW = 800, SH = 600

screenres SW, SH, 32

for x as integer = 0 to SW - 1
  for y as integer = 0 to SH - 1
    dim as integer i = int(255 * turbulence2d(x, y, 8))
    pset (x, y), rgb(i, i, 0)
  next
next
sleep
ShawnLG
Posts: 142
Joined: Dec 25, 2008 20:21

Re: Simple Noise 1D,2D and 3D

Post by ShawnLG »

It is faster to multiply with the recipical instead of all thoes ugly divisions.

Code: Select all

'Replaced divisions with reciprocals, ShawnLG
#Ifndef __SIMPLENOISE_BI__
#define __SIMPLENOISE_BI__
const as integer NOIZESIZE = 255

dim shared as single noise(NOIZESIZE,NOIZESIZE,NOIZESIZE)

sub init constructor
  randomize timer
  for x as integer=0 to NOIZESIZE
    for y as integer = 0 to NOIZESIZE
      for z as integer = 0 to NOIZESIZE
        noise(x,y,z)=rnd()
      next 
    next
  next
end sub 


function smoothNoise1d(x as single) as single
  x=abs(x)
  dim as integer iX1=int(x)
  dim as integer iX2=ix1+1
  dim as single tx=x-iX1
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  dim as single l=noise(iX1,0,0)
  dim as single r=noise(iX2,0,0)
  dim as single v=l + (r-l)*tx
  return v
end function

function smoothNoise2d(x as single, y as single) as single
  x=abs(x)
  y=abs(y)
  dim as integer iX1=int(x)
  dim as integer iY1=int(y)
  dim as integer iX2=ix1+1
  dim as integer iY2=iy1+1
  dim as single tx=x-iX1
  dim as single ty=y-iY1
 
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  iY1 and= NOIZESIZE
  iY2 and= NOIZESIZE
 
  dim as single lt=noise(iX1,iY1,0)
  dim as single rt=noise(iX2,iY1,0)
  dim as single rb=noise(iX2,iY2,0)
  dim as single lb=noise(iX1,iY2,0)
 
  dim as single sxt=lt + (rt-lt)*tx
  dim as single sxb=lb + (rb-lb)*tx
 
  dim as single v=sxt+(sxb-sxt)*ty
  return v
end function

function smoothNoise3d(x as single, y as single, z as single) as single
  x=abs(x)
  y=abs(y)
  z=abs(z)
  dim as integer iX1=int(x)
  dim as integer iY1=int(y)
  dim as integer iZ1=int(z)
  dim as integer iX2=ix1+1
  dim as integer iY2=iy1+1
  dim as integer iZ2=iz1+1
  dim as single tx=x-iX1
  dim as single ty=y-iY1
  dim as single tz=z-iZ1
 
  iX1 and= NOIZESIZE
  iX2 and= NOIZESIZE
  iY1 and= NOIZESIZE
  iY2 and= NOIZESIZE
  iZ1 and= NOIZESIZE
  iZ2 and= NOIZESIZE
 
  dim as single ltf=noise(iX1,iY1,iZ1)
  dim as single rtf=noise(iX2,iY1,iZ1)
  dim as single rbf=noise(iX2,iY2,iZ1)
  dim as single lbf=noise(iX1,iY2,iZ1)
  dim as single sxtf=ltf + (rtf-ltf)*tx
  dim as single sxbf=lbf + (rbf-lbf)*tx
 
  dim as single ltb=noise(iX1,iY1,iZ2)
  dim as single rtb=noise(iX2,iY1,iZ2)
  dim as single rbb=noise(iX2,iY2,iZ2)
  dim as single lbb=noise(iX1,iY2,iZ2)
  dim as single sxtb = ltb + (rtb-ltb)*tx
  dim as single sxbb = lbb + (rbb-lbb)*tx
 
  dim as single vf = sxtf+(sxbf-sxtf)*ty
  dim as single vb = sxtb+(sxbb-sxtb)*ty
  dim as single v = vf + (vb-vf)*tz
   
  return v
end function

function turbulence1d(x as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  Dim As Single recpsize = 1/size
  while(size >= 1)
    value += smoothNoise1d(x * recpsize) * size
    size *= 0.5
    recpsize *= 2.0
  Wend
  return 0.5*value/initialSize
end function

function turbulence2d(x as single, y as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  Dim As Single recpsize = 1/size
  while(size >= 1)
    value += smoothNoise2d(x * recpsize, y * recpsize) * size
    size *= 0.5
    recpsize *= 2.0
  Wend
  return 0.5*value/(initialSize-1)
end function

function turbulence3d(x as single, y as single, z as single, size as single) as single
  dim as single value, initialSize=any
  if size<1 then size=1
  initialSize = size
  Dim As Single recpsize = 1/size
  while(size >= 1)
    value += smoothNoise3d(x * recpsize, y * recpsize, z * recpsize) * size
    size *= 0.5
    recpsize *= 2.0
  Wend
  return 0.5*value/(initialSize-1)
end function

#endif ' __SIMPLENOISE_BI__
Post Reply