Understanding 1d Perlin Noise

Started by
17 comments, last by JTippetts 12 years, 8 months ago
Wow, looks like a fantastic source of info! Will definitely spend some time digging through there. Looking forward to more in the future too.
Advertisement
You probably won't see this comment, but in case you do, I'm not sure my Perlin Noise is functioning correctly. Despite me having the persistence value set at 1/4, the transition from one to another doesn't seem to be smoothed out (here's the image). Do you happen to know what's likely to cause this?
Can you post your code?
Thanks for the reply. I'm using DarkBasic Pro, but hopefully you can make sense of it. The value for glob_PerlinNoise_Persistance# is set at 0.25, and the value of glob_PerlinNoise_OctaveMax is set at 3.

Code that calls the function.


FOR var_PositionX = 0 TO var_WorldGen_WorldWidth - 1
var_X# = var_PositionX / var_WorldGen_WorldWidth#
var_X# = var_X# * var_WorldGen_Regions

arr_WorldGen_WidthData(var_PositionX) = var_WorldGen_Dirt_BorderStart + ((((func_PerlinNoise1D_Combined(var_X#) + 1.0) * var_WorldGen_HeightVariation) / 2.0) - (var_WorldGen_HeightVariation / 2))
NEXT var_PositionX


Perlin Noise code.


FUNCTION func_PerlinNoise1D_Combined(var_X#)
var_Total# = 0

FOR var_Octave = 0 TO glob_PerlinNoise_OctaveMax
var_Frequency = 2 ^ var_Octave
var_Amplitude# = glob_PerlinNoise_Persistance# ^ var_Octave

var_Total# = var_Total# + func_PerlinNoise1D_Interpolate(var_X# * var_Frequency) * var_Amplitude#
NEXT var_Octave

ENDFUNCTION var_Total#

FUNCTION func_PerlinNoise1D_Interpolate(var_X#)
var_X_Integer = INT(var_X#)
var_X_Fraction# = var_X# - var_X_Integer

var_SmoothNoise_1# = func_PerlinNoise1D_Smooth(var_X_Integer)
var_SmoothNoise_2# = func_PerlinNoise1D_Smooth(var_X_Integer + 1)

var_Interpolate# = func_PerlinNoise1D_InterpolateCosine(var_SmoothNoise_1#, var_SmoothNoise_2#, var_X_Fraction#)
ENDFUNCTION var_Interpolate#

FUNCTION func_PerlinNoise1D_InterpolateCosine(var_SmoothNoise_1#, var_SmoothNoise_2#, var_X_Fraction#)
var_Value1# = var_X_Fraction# * 3.1415927
var_Value2# = (1 - COS(var_Value1#)) * 0.5

var_InterpolateCosine# = var_SmoothNoise_1# * (1 - var_Value2#) + var_SmoothNoise_2# * var_Value2#
ENDFUNCTION var_InterpolateCosine#

FUNCTION func_PerlinNoise1D_Smooth(var_X)
var_SmoothNoise# = func_PerlinNoise1D_Random(var_X) / 2.0 + func_PerlinNoise1D_Random(var_X - 1) / 4.0 + func_PerlinNoise1D_Random(var_X + 1) / 4.0
ENDFUNCTION var_SmoothNoise#

FUNCTION func_PerlinNoise1D_Random(var_X)
var_X = (var_X << 13) ~~ var_X
var_Random# = (1.0 - ((var_X * (glob_WorldGen_Seed * var_X * var_X * 15731 + 789221) + 1376312589) && 0x7fffffff) / 1073741824.0)
ENDFUNCTION var_Random#
In the image that you posted, how many array samples are represented? Does one height sample represent a column of pixels, or a column of larger blocks? I'm not seeing anything in the posted code that jumps out at me, but it would be useful to see what you are doing to between the posted code and drawing to the screen.
That's determined using your "region" method. This is the code that converts the output from the Perlin Noise (which will be a value from -1.0 to 1.0) into something that's usable.

[color=#1C2837][size=2][color=#000000]arr_WorldGen_WidthData[color=#666600]([color=#000000]var_PositionX[color=#666600])[color=#000000] [color=#666600]=[color=#000000] var_WorldGen_Dirt_BorderStart [color=#666600]+[color=#000000] [color=#666600](((([color=#000000]func_PerlinNoise1D_Combined[color=#666600]([color=#000000]var_X[color=#880000]#) + 1.0) * var_WorldGen_HeightVariation) / 2.0) - (var_WorldGen_HeightVariation / 2))

To break it down a bit, there are three main values being combined in the code, but only this one is relevant to my problem: [color=#1C2837][font=CourierNew, monospace][size=2][color=#666600](((([color=#000000]func_PerlinNoise1D_Combined[color=#666600]([color=#000000]var_X[color=#880000]#) + 1.0) * var_WorldGen_HeightVariation) / 2.0)[/font]". Here you see the value "[color=#880000][font=CourierNew, monospace][size=2]var_WorldGen_HeightVariation[/font]" appear; this is the maximum amount of blocks I want the border to be able to vary, which is set at 0.05% of the total map height. The Perlin Noise function is called, and immediately after being called the value it returns (again, -1.0 to 1.0) is increased by 1.0. This gets multiplied by "[color=#880000][font=CourierNew, monospace][size=2]var_WorldGen_HeightVariation[/font]" and then divided by 2.0. I'm making it sound more complicated then it really is, since It's pretty much just cross multiplication.

Hopefully I answered your question, but if not let me know. Off to work for now, but I'll be able to elaborate further after I'm back.
What I'm asking is how are you converting the array full of noise values to the image that is shown on screen? Does each element in the array correspond to the height of one column of pixels in the output image? If that is the case, then it seems you have an interpolation problem. Or is one element in the array correspond to a column of blocks, where the blocks are comprised of some MxN pixels? If this is the case, then it is possible you don't really have a problem, since "magnifying" what is essentially a pixel array would serve to also magnify the stepped jaggedness of a function.
Oh sorry, I understand now. One element in the array is equivalent to one column of blocks. I was using the Cosine interpolation method (which was probably unnecessary to begin with since I'm dealing with blocks, not smooth lines), but I switched it to Linear and it's working wonderfully now. Thanks yet again!
You're welcome, glad that you got it working.

This topic is closed to new replies.

Advertisement