Author Topic: Perlin Noise implementation  (Read 2525 times)

Offline CptnRoughnight

  • Mr. Polyvector
  • ***
  • Posts: 114
    • View Profile
Perlin Noise implementation
« on: 2013-Dec-14 »
Hi,

here is my Perlin Noise implementation. Feel free to use in your projects!

Code: GLBasic [Select]
//****************************************
//** Perlin Noise Implementatio
//** Date: 14.12.2013
//****************************************

TYPE TPerlin
        d%
        f#
        result#
        fracX#
        fracY#
        total#
        octaves
        pnum%
    per_Prim_1%[]
    per_Prim_2%[]

        FUNCTION InitNoise:num%
                self.d% = 0
                self.f# = 0
                self.result = 0
                self.fracX = 0
                self.fracY = 0
                self.total = 0
                self.octaves = 0
                self.pnum% = num%

                DIMDATA self.per_Prim_1%[],15731,15733,15737,15739,15749,15761,15767,15773,15787,15791,15797,15803,15809,15817,15823
                DIMDATA self.per_Prim_2%[],789221,789227,789251,789311,789323,789331,789343,789367,789377,789389,789391,789407,789419,789443,789473
        ENDFUNCTION


        FUNCTION Noise#:n%,octave
                self.d = BXOR(ASL(n,13),n)

                RETURN (1.0 - (BAND((self.d * (self.d * self.d * self.per_Prim_1%[self.pnum] + self.per_Prim_2%[self.pnum]) + 1376312627),2147483647)) / 1073741824.0)
        ENDFUNCTION

        FUNCTION Cos_Interpolate#:a#,b#,x#
                self.f# = COS(PI * x#)

                self.f# = (1-self.f#) * 0.5;
                RETURN a# *(1-self.f#)+b# *self.f#;
        ENDFUNCTION


        FUNCTION Noise2D#:x%,y%
                RETURN self.Noise(x * 46349 + y * 46351, 1)
        ENDFUNCTION


        FUNCTION Smooth_Noise2D#:x%,y%
                self.result = (self.Noise2D(x-1,y-1) + self.Noise2D(x+1,y-1) + self.Noise2D(x-1,y+1) + self.Noise2D(x+1,y+1)) / 16
                self.result = self.result +( (self.Noise2D(x-1,y) + self.Noise2D(x+1,y) + self.Noise2D(x,y-1) + self.Noise2D(x,y+1)) / 8)
                self.result = self.result +( self.Noise2D(x,y) / 4 )
                RETURN self.result;

        ENDFUNCTION


        FUNCTION InterpolatedNoise2D#:x%,y%
                self.fracX# = x - INTEGER(x)
                self.fracY# = y - INTEGER(y)

                RETURN self.Cos_Interpolate(self.Cos_Interpolate(self.Smooth_Noise2D(INTEGER(x#), INTEGER(y#)), self.Smooth_Noise2D(INTEGER(x#) + 1, INTEGER(y#)), self.fracX#),self.Cos_Interpolate(self.Smooth_Noise2D(INTEGER(x#), INTEGER(y#)), self.Smooth_Noise2D(INTEGER(x#) + 1, INTEGER(y#)), self.fracX#),            self.fracY#)

        ENDFUNCTION

        FUNCTION GetPerlinNoise2D#:x#,y#,pers#,freq#,amp#,oct
                self.total# = 0

                FOR self.octaves = 0 TO oct
                        freq# = freq*2
                        amp# = amp*pers
                        self.total# = self.total# + (self.InterpolatedNoise2D(x#*freq#,y#*freq#)*amp#)
                NEXT
                RETURN self.total
        ENDFUNCTION
ENDTYPE

edit:

and the test program :

Code: GLBasic [Select]
// --------------------------------- //
// Project: Perlin
// Start: Tuesday, September 10, 2013
// IDE Version: 11.171


GLOBAL map[]
GLOBAL x,y
GLOBAL p AS TPerlin

DIM map[10001]

CONSTANT PI = 3.141593
p.InitNoise(4)

FOR x= 0 TO 99
        FOR y = 0 TO 99
                map[x+y*100] = (p.GetPerlinNoise2D(x,y,0.8,0.1,1,5)+1)/255 * 255
                DEBUG "map: "+map[x+y*100]+"\n"
        NEXT
NEXT

FOR x= 0 TO 99
        FOR y = 0 TO 99
                DRAWRECT x*4,y*4,4,4,RGB(map[x+y*100]*200,0,0)

        NEXT
NEXT

SHOWSCREEN

MOUSEWAIT
 

Edit : Strange PI Bug :D
« Last Edit: 2014-May-03 by Moru »
Es ist kein Mond....

A young band from Thuringia with a lot of potential :
http://youtu.be/diMBlNspsD8

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Perlin Noise implementation
« Reply #1 on: 2013-Dec-14 »
Thanks for posting this Dr. Fist, I will have a good play with this later  :booze:

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline Moru

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 1748
    • View Profile
    • Homepage
Re: Perlin Noise implementation
« Reply #2 on: 2013-Dec-14 »
Great, always wanted to play with perlin noise! Is there any seed somewhere to get different results?

Offline CptnRoughnight

  • Mr. Polyvector
  • ***
  • Posts: 114
    • View Profile
Re: Perlin Noise implementation
« Reply #3 on: 2013-Dec-14 »
Ahhh my fault!

for seeding, there are two arrays in the Perlin Type, with

Code: GLBasic [Select]
perlin.InitNoise( seed )
 

you can access them!
Es ist kein Mond....

A young band from Thuringia with a lot of potential :
http://youtu.be/diMBlNspsD8

Offline Schranz0r

  • Premium User :)
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 4948
  • O Rly?
    • View Profile
Re: Perlin Noise implementation
« Reply #4 on: 2013-Dec-15 »
thats cool!

Now the 3D and we good to go! :D
I <3 DGArray's :D

PC:
AMD RYzen 7 1700 @3.9Ghz, 16GB HyperX Fury 2600Mhz Ram, HIS 7970 GHz Edition @3GB, Windows 10 Pro 64Bit, MSi Tomahawk B350 Mainboard

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Perlin Noise implementation
« Reply #5 on: 2013-Dec-15 »
I've made 2 changes as the colours where off. 1st change just does the raw perlin & keeps its -1 to +1 range & 2nd is the draw part where it selects the colour based on whats in the array.
Code: GLBasic [Select]
//from
map[x+y*100] = (p.GetPerlinNoise2D(x,y,0.8,0.1,1,5)+1)/255 * 255
//to
map[x+y*100] = p.GetPerlinNoise2D(x,y,0.8,0.1,1,5)

//and drawing from
DRAWRECT x*4,y*4,4,4,RGB(map[x+y*100]*200,0,0)
//to
DRAWRECT x*4,y*4,4,4,RGB(((map[x+y*100])+1)*128,0,0)
 

You can see the difference in the below 2 pics. Fun routine to play with  :D

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3317
  • Integrated Brain
    • View Profile
Re: Perlin Noise implementation
« Reply #6 on: 2013-Dec-15 »
Really it's intersting In VRay or another Render Engines sometime I show and Pick Perlin Noise, I think always it's in refelections or Specular colors... BUt it's really cool like this Basic can do, very very complex things in Basic...

Another cuestion Fuzzy, sorry for the question , this it's something from  Mathematics, ins't?¿ then the utility of the perlin Noise, for what can be usefull, in graphical stages can be inetersting for Bumps, or change a bit the surfaces of objects, but numerically or in another kind of application...

I'm not sure if I expressed well... :-[ :-[


A bit of Explanation (WIKIPEDIA)
Seems Perlin Noise was for the Film Tron.. it's similar to White Noise (I think this it's used in Audio like Pink Noise),
Ken Perlín Who invented the Perlin Noise won an Academy Award for this the Perlin Noise, coriouslly TRON don't won the Awards for the Visual FX... (Really the film it's a bit bored  :D )
« Last Edit: 2013-Dec-15 by mentalthink »

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Perlin Noise implementation
« Reply #7 on: 2013-Dec-15 »
@Mentalthink, Yes Perlin noise is a mathematical way of creating noise that while looking random it isn't random at all so the same noise can be created again easily. Here's a good description about the history of it & how it came about from the creator himself (also discovered he created the 1st ever shading language) http://www.noisemachine.com/talk1/

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3317
  • Integrated Brain
    • View Profile
Re: Perlin Noise implementation
« Reply #8 on: 2013-Dec-15 »
Thanks Fuzzy for the info...

***Sorry in my post I want delete the little text, because I put this little info under the post...
Thanks for the link I take a look  :good:

Offline Slydog

  • Prof. Inline
  • *****
  • Posts: 924
  • KodeSource
    • View Profile
    • KodeSource
Re: Perlin Noise implementation
« Reply #9 on: 2013-Dec-16 »
Awesome.  Looking great!

(except perhaps your Pi value: (not sure what difference it makes, just caught my eye!)
CONSTANT PI = 3.141562 <- your code
CONSTANT PI = 3.141593 <- should be)

I attempted a Perlin Noise function / type while working on the Minecraft style voxels here:
http://www.glbasic.com/forum/index.php?topic=9499.msg82316#msg82316

Here's the code used:
Code: GLBasic [Select]
TYPE TPerlineNoise
        maxWidth%
        maxHeight%
        noise#[]
        isNoiseInitialized% = FALSE

        FUNCTION Create: width%, height%
                self.maxWidth = width
                self.maxHeight = height
                self.GenerateNoise()
        ENDFUNCTION

        /// Gets the value for a specific X and Y coordinate
        /// results in range [-1, 1] * maxHeight
        FUNCTION GetRandomHeight#: x#, y#, maxHeight#, frequency#, amplitude#, persistance#, octaves%
                LOCAL i%
                LOCAL finalValue# = 0.0
                GenerateNoise()

                FOR i = 0 TO octaves-1
                        INC finalValue, GetSmoothNoise(x * frequency, y * frequency) * amplitude
                        frequency = frequency * 2.0
                        amplitude = amplitude * persistance
                NEXT

                IF finalValue < -1.0
                        finalValue = -1.0
                ELSEIF finalValue > 1.0
                        finalValue = 1.0
                ENDIF

                RETURN finalValue * maxHeight
        ENDFUNCTION

        //This function is a simple bilinear filtering function which is good (and easy) enough.
        FUNCTION GetSmoothNoise#: x#, y#
                LOCAL finalValue# = 0.0
                LOCAL fractionX# = x - INTEGER(x)
                LOCAL fractionY# = y - INTEGER(y)
                LOCAL x1% = MOD(INTEGER(x) + self.maxWidth, self.maxWidth)
                LOCAL y1% = MOD(INTEGER(y) + self.maxHeight, self.maxHeight)
                //for cool art deco looking images, do +1 for X2 and Y2 instead of -1...
                LOCAL x2% = MOD(INTEGER(x) + self.maxWidth - 1, self.maxWidth)
                LOCAL y2% = MOD(INTEGER(y) + self.maxHeight - 1, self.maxHeight)
                INC finalValue, fractionX * fractionY * self.noise[x1][y1]
                INC finalValue, fractionX * (1 - fractionY) * self.noise[x1][y2]
                INC finalValue, (1 - fractionX) * fractionY * self.noise[x2][y1]
                INC finalValue, (1 - fractionX) * (1 - fractionY) * self.noise[x2][y2]
                RETURN finalValue
        ENDFUNCTION

        /// create a array of randoms
        FUNCTION GenerateNoise:
                LOCAL x%, y%
                IF self.isNoiseInitialized THEN RETURN                                  // A boolean variable in the class to make sure we only do this once
                DIM self.noise[self.maxWidth][self.maxHeight]                   // Create the noise table where MAX_WIDTH and MAX_HEIGHT are set to some value>0

                FOR x = 0 TO self.maxWidth-1
                        FOR y = 0 TO self.maxHeight-1
                                self.noise[x][y] = (RandomFloat() - 0.5) * 2.0  // Generate noise between -1 and 1
                        NEXT
                NEXT
                self.isNoiseInitialized = TRUE
        ENDFUNCTION

        FUNCTION ToSprite:
                LOCAL x%, y%
                LOCAL sprite% = GENSPRITE()
                LOCAL colour%
                CREATESCREEN 0, sprite, self.maxWidth, self.maxHeight
                USESCREEN 0

                FOR x = 0 TO self.maxWidth-1
                        FOR y = 0 TO self.maxHeight-1
                                colour = GetRandomHeight(x,y, 127, 0.15, 1, 0.15, 3) + 128//x#, y#, maxHeight#, frequency#, amplitude#, persistance#, octaves%
                                SETPIXEL x, y, RGB(colour, colour, colour)
                        NEXT
                NEXT

                USESCREEN -1
                RETURN sprite
        ENDFUNCTION
ENDTYPE

And how I call it:
Code: GLBasic [Select]
//x#, y#, maxHeight#, frequency#, amplitude#, persistance#, octaves%
height = noise.GetRandomHeight(x,z, 1, 0.1, 1, 0.15, 3)

See below for a screeny of the results.
Mine is only a 2D version.  It would be cool to see a 3D version that creates caves, just like Minecraft.  Now, mine only defines the top surface of the landscape.

Keep it up, I love Perlin noise since I heard about it researching how Minecraft generates it's endless landscapes.
« Last Edit: 2013-Dec-16 by Slydog »
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Offline CptnRoughnight

  • Mr. Polyvector
  • ***
  • Posts: 114
    • View Profile
AW: Perlin Noise implementation
« Reply #10 on: 2013-Dec-16 »
:D very nice!

My PI value o.O, thats a strange mistake. .. thanks for it! :D
Es ist kein Mond....

A young band from Thuringia with a lot of potential :
http://youtu.be/diMBlNspsD8

Offline Moru

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 1748
    • View Profile
    • Homepage
Re: Perlin Noise implementation
« Reply #11 on: 2013-Dec-16 »
All since the Atari I was dreaming of how to use perlin noise to create landscapes, very nice :-) And yes, was trying to figure out how to do 3D noise but I think that is slightly above my horizon at the moment.

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3317
  • Integrated Brain
    • View Profile
Re: Perlin Noise implementation
« Reply #12 on: 2013-Dec-16 »
Really I don't know perin noise it's for terrains, this demo in the Image in voxels it's great!!!

Offline CptnRoughnight

  • Mr. Polyvector
  • ***
  • Posts: 114
    • View Profile
Re: Perlin Noise implementation
« Reply #13 on: 2013-Dec-16 »
Perlin is indeed intended for textures, but for example, Minecraft uses this algorhythm for the terrain generation.
First, it will determine the level of landscapes, then, in several passes the "Dungeons".

Es ist kein Mond....

A young band from Thuringia with a lot of potential :
http://youtu.be/diMBlNspsD8

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Perlin Noise implementation
« Reply #14 on: 2013-Dec-17 »
There is a simplex noise post on the forum & that includes 3d. It's the successor to perlin by the creator.

Lee

Sent from my C6603 using Tapatalk

"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)