### Post by shadow008 on May 29, 2013 15:06:13 GMT -5

From freespace.virgin.net/hugo.elias/models/m_perlin.htm I implemented perlin noise in b4gl.

Fairly simple, yet uncommented (sorry) code. This example REQUIRES THE TOOL BOX PLUGIN. At least for saving the image. You can comment out those parts if you so please.

Things to note: the "random" number generator is seeded. So the same seed = the same random number every time. Basically allows for seamlessness from one texture to another one generated with *size of texture* offset.

Plus, I got the code to finally work nice and fast, generating one 128x128 section about every second on my computer. (Pre-optimization, it was taking more than 10 seconds per section to produce a really grainy, uniformly torn, awful looking image)

Also, heightmaps.

Making larger images? Just bump up the integer in CreateLargePerlinMap (4 = 512x512 image). You can also play with line 115 "pNoise = PerlinNoise..." to see what kind of effects you can get.

Results:

...just kidding, no results.

Here's the link: dl.dropboxusercontent.com/u/5319168/Test%20seed%2077%20256x256.bmp

Fairly simple, yet uncommented (sorry) code. This example REQUIRES THE TOOL BOX PLUGIN. At least for saving the image. You can comment out those parts if you so please.

`const NOISE_MAX as integer = 79`

dim GLOBAL_SEED = 36

const MARBLE_EFFECT = TRUE

const WOOD_EFFECT = TRUE

type MARBLE_PARAMS

dim xPeriod as single

dim yPeriod as single

dim turbPower as single

dim cutoff as single

dim effect as single

end type

type WOOD_PARAMS

dim rings as single

dim turbPower as single

dim effect as single

end type

dim Marble as MARBLE_PARAMS

dim Wood as WOOD_PARAMS

function Noise(x as integer, y as integer) as integer

'Seeded "random" number generator

dim n as single = GLOBAL_SEED

n = (n + x) / ((n + y)) * 1103515245 * NOISE_MAX + n

return (int(n / 65535)) % NOISE_MAX

endfunction

function Cosine_Interpolation(a as single, b as single, x as single)

dim ft as single = x * 3.1415927

dim f as single = (1 - cos(ft)) * .5

return a*(1-f) + b*f

endfunction

function InterpolatedNoise(x as single, y as single)

dim integer_X as integer = x

dim fractional_X as single = x - integer_X

dim integer_Y as integer = y

dim fractional_Y as single = y - integer_Y

dim v1 as single = Noise(integer_X, integer_Y)

dim v2 as single = Noise(integer_X + 1, integer_Y)

dim v3 as single = Noise(integer_X , integer_Y + 1)

dim v4 as single = Noise(integer_X + 1, integer_Y + 1)

dim i1 as single = Cosine_Interpolation(v1 , v2 , fractional_X)

dim i2 as single = Cosine_Interpolation(v3 , v4 , fractional_X)

return Cosine_Interpolation(i1 , i2 , fractional_Y)

endfunction

function PerlinNoise_2D(x as single, y as single, persistance as single, octaves as integer) as single

dim total as single = 0

dim frequency as single

dim amplitude as single

dim i

x = x + RND_MAX * 2

frequency = pow(2, i)

amplitude = pow(persistance, octaves)

total = total + InterpolatedNoise(x / frequency , y / frequency) * amplitude

return total

endfunction

function PerlinNoise(x as single, y as single, p as single, iterations as integer, decStart as single) as single

dim total as single

dim decimator as single = decStart

dim i

total = PerlinNoise_2D(x / decimator, y / decimator, p, 0) / (NOISE_MAX * 1.0)

if iterations = 0 then return total : endif

decimator = decimator / 2.0

for i = 1 to iterations - 1

total = total + PerlinNoise_2D(x / decimator, y / decimator, p, i-2) / (NOISE_MAX * 1.0) * .5

decimator = decimator / 2.0

next

total = total / (iterations / 3.0)

return total

endfunction

sub SetMarbleParams(xPer as single, yPer as single, turb as single, cutoff as single)

Marble.xPeriod = xPer

Marble.yPeriod = yPer

Marble.turbPower = turb

Marble.cutoff = cutoff

endsub

sub SetWoodParams(rings as single, turb as single)

Wood.rings = rings

Wood.turbPower = turb

endsub

function CreateLargePerlinMap(size as single, TextureName as string)

dim x,y

dim pNoise as single

dim xyValue as single

dim sineVal as single

dim rings as single = 1.0

dim xVal as single

dim yVal as single

dim distVal as single

dim noiseBuffer as single

glReadBuffer(GL_FRONT)

glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT)

glPushMatrix()

glViewport(0, 0, size, size)

glMatrixMode(GL_PROJECTION)

glLoadIdentity()

glOrtho(0.0, size * 1.0, 0.0, size * 1.0, 0.1, 1000.0)

glMatrixMode(GL_MODELVIEW)

glLoadIdentity()

gluLookAt(0,0,1, 0,0,0, 0,1,0)

for x = 0 to size

for y = 0 to size

glBegin(GL_POINTS)

pNoise = PerlinNoise(x, y, .5, 8, 32)

'pNoise = pNoise * pNoise

if MARBLE_EFFECT then

xyValue = (x * Marble.xPeriod / size) + (y * Marble.yPeriod / size) + (Marble.turbPower * pNoise)

sineVal = abs(sin(xyValue * 3.14159))

if sineVal < Marble.cutoff then

Marble.effect = sineVal

else

Marble.effect = pNoise

endif

endif

if WOOD_EFFECT then

xVal = (x - size / 2) / size

yVal = (y - size / 2) / size

distVal = (sqrt(xVal * xVal + yVal * yVal) + Wood.turbPower * pNoise) * 1.02

sineVal = abs(sin(2 * Wood.rings * distVal * 3.14159))

if distVal > .5 then

noiseBuffer = sineVal

else

noiseBuffer = 0

endif

noiseBuffer = 1 - noiseBuffer

Wood.effect = noiseBuffer

endif

if MARBLE_EFFECT then

if Marble.effect < Marble.cutoff and Marble.Effect > 0 then

pNoise = (pNoise + Marble.effect + .8) / 10.0

endif

endif

if WOOD_EFFECT then

pNoise = (pNoise + .15) * Wood.effect

endif

glColor3f ( pNoise, pNoise, pNoise)

glVertex2f( x, y)

glEnd()

WindowTitle( ((x / size) * 100) + "% Complete")

next

next

glPopMatrix()

SwapBuffers()

SaveBMP(0, 0, size, size, TextureName)

return 0

endfunction

SetMarbleParams(2, 1, .5, .15)

SetWoodParams(1.0, .2)

CreateLargePerlinMap(256.0, "Test seed 36 256x256.bmp")

WindowTitle("Done")

end

Things to note: the "random" number generator is seeded. So the same seed = the same random number every time. Basically allows for seamlessness from one texture to another one generated with *size of texture* offset.

Plus, I got the code to finally work nice and fast, generating one 128x128 section about every second on my computer. (Pre-optimization, it was taking more than 10 seconds per section to produce a really grainy, uniformly torn, awful looking image)

Also, heightmaps.

Making larger images? Just bump up the integer in CreateLargePerlinMap (4 = 512x512 image). You can also play with line 115 "pNoise = PerlinNoise..." to see what kind of effects you can get.

Results:

...just kidding, no results.

Here's the link: dl.dropboxusercontent.com/u/5319168/Test%20seed%2077%20256x256.bmp