Perlin Noise V1.2 - Updated 2nd Apr 2012
1. Update has table based faster perlin noise functions...
2. Separate plugin just for simplex noise functions... (added to download attached to this post)
This a standard perlin noise plugin for Dark Basic Pro.
(download has and ".rtf" file with all the latest functions)
You can have access (using pn) of 8 perlin noise sets.
Use the plugin for creating
TERRAINS, TEXTURES, CLOUDS and anything you may be able to think of.
DOWNLOAD link is attached to this post. Usual stuff, dll into the plugins-user dir and the ini goes into the keywords dir...
NB:
Although DBP passes and retrieves values using FLOATS, the internals of the perlin noise plugin does all its calculations using double precision. I have also converted a few of the internal functions direct into assembler code and I've used a cosine interpolate instead of a cubic function as this increase of speed is necessary.
Commands and Functions:
NOISE GET HEIGHT ==(pn,x,y)
NOISE GET HEIGHT TILED ==(pn,x,y,width,height)
NOISE SET PARAMS ==pn,pers,freq,ampl,oct,seed
NOISE GET PERSISTANCE ==(pn)
NOISE GET FREQUENCY ==(pn)
NOISE GET AMPLITUDE ==(pn)
NOISE GET OCTAVES ==(pn)
NOISE GET RANDOMSEED ==(pn)
NOISE SET PERSISTANCE ==pn,pers
NOISE SET FREQUENCY ==pn,freq
NOISE SET AMPLITUDE ==pn,ampl
NOISE SET OCTAVES ==pn,oct
NOISE SET RANDOMSEED ==pn,seed
NOISE GET HEIGHT BYTE ==(pn,x,y)
NOISE GET HEIGHT BYTE ABS ==(pn,x,y)
NOISE GET HEIGHT BYTE TOP ==(pn,x,y)
NOISE GET HEIGHT TILED BYTE ==(pn,x,y,width,height)
NOISE GET HEIGHT TILED BYTE ABS==(pn,x,y,width,height)
NOISE GET HEIGHT TILED BYTE TOP==(pn,x,y,width,height)
See docs in the attached download for extra commands...
Simplex Noise functions: (example further below)
~~~~~~~~~~~~~~~~~~~~~~~
SIMPLEX NOISE FUNCTIONS
~~~~~~~~~~~~~~~~~~~~~~~
value# = SIMPLEX NOISE 2D(octaves,persistence#,scale#,x#,y#)
value# = SIMPLEX NOISE 3D(octaves,persistence#,scale#,x#,y#,z#)
value# = SIMPLEX NOISE 4D(octaves,persistence#,scale#,x#,y#,z#,w#)
Return values between set bounds:
value# = SIMPLEX SCALED 2D(octaves,persistence#,scale#,lobound#,hibound#,x#,y#)
value# = SIMPLEX SCALED 3D(octaves,persistence#,scale#,lobound#,hibound#,x#,y#,z#)
value# = SIMPLEX SCALED 4D(octaves,persistence#,scale#,lobound#,hibound#,x#,y#,z#,w#)
~~~~~~~~~~~~~~~
BONUS FUNCTIONS
~~~~~~~~~~~~~~~
WL MATRIX NORMALISE==matrixID
value# = WL FSQRT==(num#)
~~~~~~~~~~~~~~~~~~~~~~
PERLIN NOISE FUNCTIONS
~~~~~~~~~~~~~~~~~~~~~~
Set up the permutation tables:
FN NOISE SEED seed
Standard noise functions for customising your own stuff:
value# = FN NOISE 1D(x#)
value# = FN NOISE 2D(x#,y#)
value# = FN NOISE 3D(x#,y#,z#)
Set up the Frequency, Persistence and octaves:
FN SETFPO frequency#,persistence#,octaves
Perlin noise functions:
value# = FN PNOISE 1D(x#)
value# = FN PNOISE 2D(x#,y#)
value# = FN PNOISE 3D(x#,y#,z#)
Ridged perlin noise effect (not tried yet):
value# = FN PNOISE RIDGE(x#,y#,z#,octaves,lacunarity#,gain#,offset#)
The Helper functions NOISE XXXX BYTE returns values as integer 0-255 for easier coding.
pn is from 0 - 7. This gives you 8 noise sets. Although 99% of the time you will only ever need 1.
Example showing how to produce a tiled cloud texture:
Rem Project: Dark Basic Pro Project
Rem Created: Wednesday, September 28, 2011
Rem ***** Main Source File *****
sync off : sync rate 60
NOISE SET PARAMS 0, 0.5, 0.1, 1.5, 8, 0
do
for x=0 to 255
for y=0 to 255
v#=Noise Get Height tiled(0,x,y,256,256)
if v#<0 then v#=0
v#=v#*255
c=v#
if c<0 then c=0
if c>255 then c=255
dot x,y,rgb(c,c,c)
next y
next
sync
text 0,0,"Screen FPS : "+str$(screen fps())
loop
Example showing creation of a seamless terrain:
sync on : sync rate 60 : autocam off
set display mode 800,600,32 : set window off
position camera 0,500,0 : point camera 1024,0,1024
make matrix 1, 2048, 2048, 256, 256
NOISE SET PARAMS 0, 0.5, 0.1, 1.5, 6, 0
for x=0 to 255
for y=0 to 255
hgt = abs(NOISE GET HEIGHT TILED(0,x,y,256,256)) * 255
set matrix height 1, x, y, hgt
next
next
do
shift matrix down 1
shift matrix right 1
update matrix 1
sync
loop
NOISE GET HEIGHT will return a value from -1 to +1.
NOISE GET HEIGHT TILED uses width and height to retrieve a value, ie in the above example.
The above two functions get passed a float value for x and y which means you can get detailed height values between the coordinates. ie you may want to zoom in on terrain which means you will be retrieving values between (x) 0.0 and 1.0. Therefore fractions can be used.
Test code to use the FAST perlin noise:
rem make sure freq# and ampl# add up to 2.0 for best results
noise fast params 4, 0.01, 1.99, 255
sync on : sync rate 60 : sync
lock pixels
for x=0 to 256
for y=0 to 256
c# = ( (noise fast get2d(x,y)) * 255.0 )
c = int(c#) and 255
ink rgb(c,c,c)
dot x,y
next
next
unlock pixels
sp=0
ink 0xffffff,0xffffff
for x=0 to 200 step 10
v# = NOISE FAST GET2D( x, x )
s$ = ""
s$ = str$(v#)
text 256,sp,s$
sp = sp + 12
next
sync
wait key
Any problems then please do let me know as this is the first plugin for Dark Basic Pro I've ever written...
NEW!!!
SOURCE CODE:
http://wlgfx.t15.org/programming-2/dbp-and-gdk-projects/dark-basic-pro/perlin-noise-plugin-for-dark-basic-pro/ ***UPDATED***
EDIT: On the TO DO list:
1. Generate complete noise maps and pass it as an image or bitmap.
2. Add some terrain texture blending functions based on noise height map.
3. Add some functions to return values from 0-255 instead of -1 to +1.
4. Add table based faster perlin noise functions.
Here's another sample of what it can do: (source code below image)
Rem Project: Dark Basic Pro Project
Rem Created: Thursday, October 27, 2011
Rem ***** Main Source File *****
autocam off : sync on : sync rate 60 : sync
//
//img = PNoise_Make_texture(0, 0, 256, 255, 0, 0, 64, 2)
//
// set the colours and create the perlin texture
col1=rgb(000,000,128) : col2=rgb(160,080,000)
col3=rgb(032,160,032) : col4=rgb(200,200,200)
img=pn_make_tertext(1, 512, col1, col2, col3, col4, 0, 40)
paste image img,0,0
text 520, 0,hex$(col1)
text 520,12,hex$(col2)
text 520,24,hex$(col3)
text 520,36,hex$(col4)
sync
wait key
end
//
// Functions start here
//
// my 1st attempt to create a terrain type texture using the perlin noise
type pn_RGB
r as integer
g as integer
b as integer
endtype
//
// nt = 0-3 (noise type)
// sprd = rgb spread value
function pn_make_tertext(seed, size, col1, col2, col3, col4, nt, sprd)
dim lay(3) as pn_RGB
// extract RGB values separately
lay(0).r=RGBR(col1) : lay(0).g=RGBG(col1) : lay(0).b=RGBB(col1)
lay(1).r=RGBR(col2) : lay(1).g=RGBG(col2) : lay(1).b=RGBB(col2)
lay(2).r=RGBR(col3) : lay(2).g=RGBG(col3) : lay(2).b=RGBB(col3)
lay(3).r=RGBR(col4) : lay(3).g=RGBG(col4) : lay(3).b=RGBB(col4)
// init perlin noise
NOISE FAST PARAMS 8, 0.02, 1.98, seed
// setup the bitmap
bm=find free bitmap():create bitmap bm,size,size
// lock pixels for fast drawing
lock pixels
// start calculating pixels
for x=0 to size-1
for y=0 to size-1
// get the noise value from the current point (-1 to 1)
v#=NOISE FAST GET2D(x,y)
// set the noise value according to the type
v=int( pn_get_noisetype(v#,nt) )
// get color layer and color value
l=(v and 0xc0) >> 6 // layer 0-3
v=(v and 0x3f) << 2 // reset to 0-255
// calc spread of colours from the correct layer
r=pn_colspread( lay(l).r, sprd )
g=pn_colspread( lay(l).g, sprd )
b=pn_colspread( lay(l).b, sprd )
// plot the pixel
dot x, y, rgb( r, g, b )
next
next
// unlock pixels
unlock pixels
// get image
img=find free image():get image img,0,0,size-1,size-1
// delete bitmap and return image ID
delete bitmap bm
endfunction img
function pn_colspread( c, s )
a=c+rnd(s*2)-s
if a<0
a=0
else
if a>255
a=255
endif
endif
endfunction a
function pn_get_noisetype(v#,ntype)
select ntype
case 0:
v#=(v#+1.0)*127.0
endcase
case 1:
v#=v#*255.0
if v#<0.0
v#=256.0-v#
endif
endcase
case 2:
v#=v#*255.0
if v#<0.0
v#=v#+256.0
endif
endcase
case 3:
v#=v#*255.0
if v#<0.0
v#=0.0
endif
endcase
endselect
if v#<0
v#=0
else
if v#>255
v#=255
endif
endif
endfunction v#
Simplex Noise example:
sync rate 60
sync on
sync
while scancode() <> 27
x = rnd(512)
y = rnd(512)
lock pixels
for w = 0 to 511
for h = 0 to 511
px# = w + x
py# = h + y
` change the first value (octaves for detail)
` This call scales down the noise value and returns
` the value between the lo and hi boundary range
v = simplex scaled 2d( 3, 1.0, 0.01, 0.0, 255.0, px#, py# )
` This call returns a value between -1.0 and +1.0
`v = int( simplex noise 2d( 1, 1, 0.1, px#, py# ) * 255.0 )
c = rgb( v, v, v )
dot w, h, c
next
NEXT
unlock pixels
sync
repeat
UNTIL scancode() = 57
ENDWHILE
Youtube video (not very good quality) showing real-time simplex noise:
Mental arithmetic? Me? (That's for computers) I can't subtract a fart from a plate of beans!
Warning! May contain Nuts!